initial recast setup
This commit is contained in:
25
src/lang/recast.test.ts
Normal file
25
src/lang/recast.test.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { recast } from "./recast";
|
||||||
|
import { Program } from "./abstractSyntaxTree";
|
||||||
|
import { abstractSyntaxTree } from "./abstractSyntaxTree";
|
||||||
|
import { lexer } from "./tokeniser";
|
||||||
|
import { Token } from "./tokeniser";
|
||||||
|
|
||||||
|
describe("recast", () => {
|
||||||
|
it("recasts a simple program", () => {
|
||||||
|
const code = "1 + 2";
|
||||||
|
const {ast, tokens } = code2ast(code);
|
||||||
|
const recasted = recast(ast);
|
||||||
|
expect(recasted).toBe(code);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
|
||||||
|
function code2ast(code: string): { ast: Program; tokens: Token[]} {
|
||||||
|
const tokens = lexer(code);
|
||||||
|
const ast = abstractSyntaxTree(tokens);
|
||||||
|
return {
|
||||||
|
ast,
|
||||||
|
tokens
|
||||||
|
}
|
||||||
|
}
|
27
src/lang/recast.ts
Normal file
27
src/lang/recast.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Program, BinaryExpression, BinaryPart } from "./abstractSyntaxTree";
|
||||||
|
|
||||||
|
export function recast(ast: Program, previousWrittenCode = ''): string {
|
||||||
|
return ast.body
|
||||||
|
.map((statement) => {
|
||||||
|
if(statement.type === "ExpressionStatement") {
|
||||||
|
if(statement.expression.type === "BinaryExpression") {
|
||||||
|
return recastBinaryExpression(statement.expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return statement.type;
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function recastBinaryExpression(expression: BinaryExpression): string {
|
||||||
|
return `${recastBinaryPart(expression.left)} ${expression.operator} ${recastBinaryPart(expression.right)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function recastBinaryPart(part: BinaryPart): string {
|
||||||
|
if(part.type === "Literal") {
|
||||||
|
return String(part?.value);
|
||||||
|
} else if(part.type === "Identifier") {
|
||||||
|
return part.name;
|
||||||
|
}
|
||||||
|
throw new Error(`Cannot recast ${part}`);
|
||||||
|
}
|
Reference in New Issue
Block a user