Files
modeling-app/src/lang/abstractSyntaxTree.test.ts

330 lines
8.0 KiB
TypeScript
Raw Normal View History

2022-11-17 16:06:38 +11:00
import { abstractSyntaxTree, findClosingBrace } from "./abstractSyntaxTree";
2022-11-13 11:14:30 +11:00
import { lexer } from "./tokeniser";
2022-11-17 16:06:38 +11:00
describe("findClosingBrace", () => {
test("finds the closing brace", () => {
const basic = "( hey )";
expect(findClosingBrace(lexer(basic), 0)).toBe(4);
2022-11-17 16:06:38 +11:00
const handlesNonZeroIndex =
"(indexForBracketToRightOfThisIsTwo(shouldBeFour)AndNotThisSix)";
expect(findClosingBrace(lexer(handlesNonZeroIndex), 2)).toBe(4);
expect(findClosingBrace(lexer(handlesNonZeroIndex), 0)).toBe(6);
const handlesNested =
"{a{b{c(}d]}eathou athoeu tah u} thatOneToTheLeftIsLast }";
expect(findClosingBrace(lexer(handlesNested), 0)).toBe(18);
2022-11-17 16:06:38 +11:00
// throws when not started on a brace
expect(() => findClosingBrace(lexer(handlesNested), 1)).toThrow();
});
});
2022-11-17 16:06:38 +11:00
2022-11-13 11:14:30 +11:00
describe("testing AST", () => {
test("test 5 + 6", () => {
const tokens = lexer("5 +6");
const result = abstractSyntaxTree(tokens);
expect(result).toEqual({
type: "Program",
start: 0,
end: 4,
body: [
{
type: "ExpressionStatement",
start: 0,
end: 4,
expression: {
type: "BinaryExpression",
start: 0,
end: 4,
left: {
type: "Literal",
start: 0,
end: 1,
value: 5,
raw: "5",
},
operator: "+",
right: {
type: "Literal",
start: 3,
end: 4,
value: 6,
raw: "6",
},
},
},
],
});
});
test("test const myVar = 5", () => {
const tokens = lexer("const myVar = 5");
const { body } = abstractSyntaxTree(tokens);
expect(body).toEqual([
{
type: "VariableDeclaration",
start: 0,
end: 15,
kind: "const",
declarations: [
{
type: "VariableDeclarator",
start: 6,
end: 15,
id: {
type: "Identifier",
start: 6,
end: 11,
name: "myVar",
},
init: {
type: "Literal",
start: 14,
end: 15,
value: 5,
raw: "5",
},
},
],
},
]);
});
test("test multi-line", () => {
const code = `const myVar = 5
const newVar = myVar + 1
`;
const tokens = lexer(code);
const { body } = abstractSyntaxTree(tokens);
expect(body).toEqual([
{
type: "VariableDeclaration",
start: 0,
end: 15,
kind: "const",
declarations: [
{
type: "VariableDeclarator",
start: 6,
end: 15,
id: {
type: "Identifier",
start: 6,
end: 11,
name: "myVar",
},
init: {
type: "Literal",
start: 14,
end: 15,
value: 5,
raw: "5",
},
},
],
},
{
type: "VariableDeclaration",
start: 16,
end: 40,
kind: "const",
declarations: [
{
type: "VariableDeclarator",
start: 22,
end: 40,
id: {
type: "Identifier",
start: 22,
end: 28,
name: "newVar",
},
init: {
type: "BinaryExpression",
start: 31,
end: 40,
left: {
type: "Identifier",
start: 31,
end: 36,
name: "myVar",
},
operator: "+",
right: {
type: "Literal",
start: 39,
end: 40,
value: 1,
raw: "1",
},
},
},
],
},
]);
});
2022-11-14 13:28:16 +11:00
test('test using std function "log"', () => {
const code = `log(5, "hello", aIdentifier)`;
const tokens = lexer(code);
const { body } = abstractSyntaxTree(tokens);
expect(body).toEqual([
{
type: "ExpressionStatement",
start: 0,
end: 28,
expression: {
type: "CallExpression",
start: 0,
end: 28,
callee: {
type: "Identifier",
start: 0,
end: 3,
name: "log",
2022-11-14 13:28:16 +11:00
},
arguments: [
2022-11-14 13:28:16 +11:00
{
type: "Literal",
start: 4,
end: 5,
value: 5,
raw: "5",
2022-11-14 13:28:16 +11:00
},
{
type: "Literal",
start: 7,
end: 14,
value: "hello",
raw: '"hello"',
2022-11-14 13:28:16 +11:00
},
{
type: "Identifier",
start: 16,
end: 27,
name: "aIdentifier",
},
2022-11-14 13:28:16 +11:00
],
optional: false,
},
},
2022-11-14 13:28:16 +11:00
]);
});
2022-11-13 11:14:30 +11:00
});
2022-11-17 20:17:00 +11:00
describe("testing function declaration", () => {
test("fn funcN = () => {}", () => {
const tokens = lexer("fn funcN = () => {}");
const { body } = abstractSyntaxTree(tokens);
2022-11-17 20:17:00 +11:00
expect(body).toEqual([
{
type: "VariableDeclaration",
start: 0,
end: 19,
kind: "fn",
declarations: [
2022-11-17 20:17:00 +11:00
{
type: "VariableDeclarator",
start: 3,
end: 19,
id: {
type: "Identifier",
start: 3,
end: 8,
name: "funcN",
},
init: {
type: "FunctionExpression",
start: 11,
end: 19,
id: null,
params: [],
body: {
type: "BlockStatement",
start: 17,
end: 19,
body: [],
},
2022-11-17 20:17:00 +11:00
},
},
],
},
]);
});
test("fn funcN = (a, b) => {return a + b}", () => {
const tokens = lexer(
["fn funcN = (a, b) => {", " return a + b", "}"].join("\n")
);
const { body } = abstractSyntaxTree(tokens);
expect(body).toEqual([
{
type: "VariableDeclaration",
start: 0,
end: 39,
kind: "fn",
declarations: [
{
type: "VariableDeclarator",
start: 3,
end: 39,
id: {
type: "Identifier",
start: 3,
end: 8,
name: "funcN",
},
init: {
type: "FunctionExpression",
start: 11,
end: 39,
id: null,
params: [
{
type: "Identifier",
start: 12,
end: 13,
name: "a",
},
{
type: "Identifier",
start: 15,
end: 16,
name: "b",
},
],
body: {
type: "BlockStatement",
start: 21,
end: 39,
body: [
{
type: "ReturnStatement",
start: 25,
end: 37,
argument: {
type: "BinaryExpression",
start: 32,
end: 37,
left: {
type: "Identifier",
start: 32,
end: 33,
name: "a",
},
operator: "+",
right: {
type: "Identifier",
start: 36,
end: 37,
name: "b",
},
},
},
],
},
},
},
],
},
2022-11-17 20:17:00 +11:00
]);
});
});