add variable declaration with binary expressions

This commit is contained in:
Kurt Hutten IrevDev
2022-11-26 08:31:10 +11:00
parent e300cf4a76
commit ab9fb05e30
2 changed files with 64 additions and 30 deletions

View File

@ -1,25 +1,40 @@
import { recast } from "./recast"; import { recast } from './recast'
import { Program } from "./abstractSyntaxTree"; import { Program } from './abstractSyntaxTree'
import { abstractSyntaxTree } from "./abstractSyntaxTree"; import { abstractSyntaxTree } from './abstractSyntaxTree'
import { lexer } from "./tokeniser"; import { lexer } from './tokeniser'
import { Token } from "./tokeniser"; import { Token } from './tokeniser'
describe("recast", () => { describe('recast', () => {
it("recasts a simple program", () => { it('recasts a simple program', () => {
const code = "1 + 2"; const code = '1 + 2'
const {ast, tokens } = code2ast(code); const { ast } = code2ast(code)
const recasted = recast(ast); const recasted = recast(ast)
expect(recasted).toBe(code); expect(recasted).toBe(code)
}); })
}); it('variable declaration', () => {
const code = 'const myVar = 5'
const { ast } = code2ast(code)
const recasted = recast(ast)
expect(recasted).toBe(code)
})
it("variable declaration that's binary with string", () => {
const code = "const myVar = 5 + 'yo'"
const { ast } = code2ast(code)
const recasted = recast(ast)
expect(recasted).toBe(code)
const codeWithOtherQuotes = 'const myVar = 5 + "yo"'
const { ast: ast2 } = code2ast(codeWithOtherQuotes)
expect(recast(ast2)).toBe(codeWithOtherQuotes)
})
})
// helpers // helpers
function code2ast(code: string): { ast: Program; tokens: Token[] } { function code2ast(code: string): { ast: Program; tokens: Token[] } {
const tokens = lexer(code); const tokens = lexer(code)
const ast = abstractSyntaxTree(tokens); const ast = abstractSyntaxTree(tokens)
return { return {
ast, ast,
tokens tokens,
} }
} }

View File

@ -1,27 +1,46 @@
import { Program, BinaryExpression, BinaryPart } from "./abstractSyntaxTree"; import { Program, BinaryExpression, BinaryPart } from './abstractSyntaxTree'
export function recast(ast: Program, previousWrittenCode = ''): string { export function recast(ast: Program, previousWrittenCode = ''): string {
return ast.body return ast.body
.map((statement) => { .map((statement) => {
if(statement.type === "ExpressionStatement") { if (statement.type === 'ExpressionStatement') {
if(statement.expression.type === "BinaryExpression") { if (statement.expression.type === 'BinaryExpression') {
return recastBinaryExpression(statement.expression); return recastBinaryExpression(statement.expression)
} }
} else if (statement.type === 'VariableDeclaration') {
return statement.declarations
.map((declaration) => {
if (declaration.init.type === 'BinaryExpression') {
return `${statement.kind} ${
declaration.id.name
} = ${recastBinaryExpression(declaration.init)}`
} else if (declaration.init.type === 'Literal') {
return `${statement.kind} ${declaration.id.name} = ${declaration.init.value}`
} }
return statement.type; return ''
}) })
.join("\n"); .join('')
}
return statement.type
})
.join('\n')
} }
function recastBinaryExpression(expression: BinaryExpression): string { function recastBinaryExpression(expression: BinaryExpression): string {
return `${recastBinaryPart(expression.left)} ${expression.operator} ${recastBinaryPart(expression.right)}` return `${recastBinaryPart(expression.left)} ${
expression.operator
} ${recastBinaryPart(expression.right)}`
} }
function recastBinaryPart(part: BinaryPart): string { function recastBinaryPart(part: BinaryPart): string {
if(part.type === "Literal") { if (part.type === 'Literal') {
return String(part?.value); if (typeof part.value === 'string') {
} else if(part.type === "Identifier") { const quote = part.raw.includes('"') ? '"' : "'"
return part.name; return `${quote}${part.value}${quote}`
} }
throw new Error(`Cannot recast ${part}`); return String(part?.value)
} else if (part.type === 'Identifier') {
return part.name
}
throw new Error(`Cannot recast ${part}`)
} }