Skip to content

Commit 6770cab

Browse files
committed
测试
1 parent cd8dc29 commit 6770cab

File tree

2 files changed

+66
-17
lines changed

2 files changed

+66
-17
lines changed

parse-lisp-expression/index.ts

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
function parseAdd(expression: string): Expression {
22
const content = expression.slice("(add ".length, -1);
33
const list = parseList("(" + content + ")");
4-
console.log(list);
4+
// console.log(list);
55
if (Array.isArray(list) && list.length !== 2) {
66
throw Error("Invalid expression");
77
}
@@ -10,7 +10,7 @@ function parseAdd(expression: string): Expression {
1010
function parseLet(expression: string): Expression {
1111
const content = expression.slice("(let ".length, -1);
1212
const list = parseList("(" + content + ")");
13-
console.log(list);
13+
// console.log(list);
1414
if (Array.isArray(list) && list.length == 0) {
1515
throw Error("Invalid expression");
1616
}
@@ -20,14 +20,40 @@ function parseLet(expression: string): Expression {
2020
function parseMult(expression: string): Expression {
2121
const content = expression.slice("(mult ".length, -1);
2222
const list = parseList("(" + content + ")");
23-
console.log(list);
23+
// console.log(list);
2424
if (Array.isArray(list) && list.length !== 2) {
2525
throw Error("Invalid expression");
2626
}
2727
return buildExpression(["mult", ...list]);
2828
}
2929
function buildExpression(list: string | number | ListArray): Expression {
30-
console.log(list);
30+
// console.log(list);
31+
if (Array.isArray(list) && list[0] === "let") {
32+
const variables = list.slice(1, -1).map(buildExpression);
33+
// console.log(variables);
34+
const declarations: VariableDeclarator[] = Array(variables.length / 2)
35+
.fill(0)
36+
.map((_, i) => {
37+
const ident = variables[i * 2];
38+
if (ident.type !== "Identifier") {
39+
throw Error("Invalid identifier");
40+
}
41+
return {
42+
type: "VariableDeclarator",
43+
id: ident,
44+
init: variables[i * 2 + 1],
45+
};
46+
});
47+
return {
48+
type: "LetExpression",
49+
50+
declarations: declarations,
51+
return: {
52+
type: "ReturnStatement",
53+
argument: buildExpression(list[list.length - 1]),
54+
},
55+
};
56+
}
3157
if (typeof list === "string") {
3258
return { type: "Identifier", name: list };
3359
}
@@ -72,9 +98,9 @@ function parseNumeric(expression: string | number): Expression {
7298
}
7399

74100
function evaluate(expression: string): number {
75-
console.log(expression);
101+
// console.log(expression);
76102
const ast = parse(expression);
77-
console.log(ast);
103+
// console.log(ast);
78104
return calculate(ast, new ScopeList());
79105
}
80106
function parse(expression: string): Expression {
@@ -102,8 +128,10 @@ function parseIdentifier(expression: string): Expression {
102128
}
103129

104130
function calculate(expression: Expression, scope: ScopeList): number {
105-
console.log(expression, scope);
131+
// console.log(expression, scope);
106132
switch (expression.type) {
133+
case "Identifier":
134+
return getVariable(scope, expression.name);
107135
case "NumericLiteral":
108136
return expression.value;
109137
case "MultExpression":
@@ -116,8 +144,17 @@ function calculate(expression: Expression, scope: ScopeList): number {
116144
calculate(expression.left, scope) +
117145
calculate(expression.right, scope)
118146
);
147+
case "LetExpression": {
148+
const newScope = new ScopeList(new Map(), scope);
149+
expression.declarations.forEach((declaration) => {
150+
newScope.variables.set(
151+
declaration.id.name,
152+
calculate(declaration.init, newScope),
153+
);
154+
});
155+
return calculate(expression.return.argument, newScope);
156+
}
119157
}
120-
throw Error("Not implemented");
121158
}
122159
export type Expression =
123160
| Identifier
@@ -165,3 +202,15 @@ export interface Identifier {
165202
name: string;
166203
}
167204
export default evaluate;
205+
206+
function getVariable(scope: ScopeList, name: string): number {
207+
if (!scope.parent && !scope.variables.has(name)) {
208+
throw Error("Variable not found:" + name);
209+
}
210+
const value = scope.variables.get(name);
211+
if (scope.variables.has(name) && typeof value !== "undefined") {
212+
return value;
213+
}
214+
if (scope.parent) return getVariable(scope.parent, name);
215+
throw Error("Variable not found:" + name);
216+
}

parse-lisp-expression/test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import { assertEquals } from "../deps.ts";
22
import evaluate from "./index.ts";
3-
4-
Deno.test("parse-lisp-expression", () => {
3+
Deno.test("parse-lisp-expression-1", () => {
4+
assertEquals(2, evaluate("(let x 3 x 2 x)"));
5+
});
6+
Deno.test("parse-lisp-expression-2", () => {
57
assertEquals(9, evaluate("9"));
68
assertEquals(1119, evaluate("1119"));
79
});
8-
Deno.test("parse-lisp-expression", () => {
10+
Deno.test("parse-lisp-expression-3", () => {
911
assertEquals(87912, evaluate("(mult 88 999)"));
1012
});
11-
Deno.test("parse-lisp-expression", () => {
12-
assertEquals(2, evaluate("(let x 3 x 2 x)"));
13-
});
14-
Deno.test("parse-lisp-expression", () => {
13+
14+
Deno.test("parse-lisp-expression-4", () => {
1515
assertEquals(1007, evaluate("(add 8 999)"));
1616
});
17-
Deno.test("parse-lisp-expression", () => {
17+
Deno.test("parse-lisp-expression-5", () => {
1818
assertEquals(14, evaluate("(let x 2 (mult x (let x 3 y 4 (add x y))))"));
1919
});
20-
Deno.test("parse-lisp-expression", () => {
20+
Deno.test("parse-lisp-expression-6", () => {
2121
assertEquals(5, evaluate("(let x 1 y 2 x (add x y) (add x y))"));
2222
});

0 commit comments

Comments
 (0)