return correct AST until compile error
This commit is contained in:
parent
2de4cac1af
commit
4f574e4198
3 changed files with 69 additions and 25 deletions
|
|
@ -29,6 +29,7 @@ import {interpret} from "./interpreter.js";
|
||||||
{v1: "pillars(number, length, shift = 0, direction = UP)", v2: "pillars(3, 10, 0, DOWN);"},
|
{v1: "pillars(number, length, shift = 0, direction = UP)", v2: "pillars(3, 10, 0, DOWN);"},
|
||||||
{v1: "moving_pillars(number, length, shift = 0, direction = DOWN)", v2: "moving_pillars(3, 10, 0, DOWN);"},
|
{v1: "moving_pillars(number, length, shift = 0, direction = DOWN)", v2: "moving_pillars(3, 10, 0, DOWN);"},
|
||||||
{v1: "staircase(number, size, direction = DOWN)", v2: "staircase(3, 1, DOWN);"},
|
{v1: "staircase(number, size, direction = DOWN)", v2: "staircase(3, 1, DOWN);"},
|
||||||
|
{v1: "repeat([start], end){...}", v2: "repeat(5){\n}"},
|
||||||
];
|
];
|
||||||
const slices = {};
|
const slices = {};
|
||||||
for (let i = 0; i < help.length; i++) {
|
for (let i = 0; i < help.length; i++) {
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ export function interpret(init_env, code) {
|
||||||
|
|
||||||
visitParametrizedBlock: (argList, statements) => {
|
visitParametrizedBlock: (argList, statements) => {
|
||||||
let args = argList.map(THIS.evaluate);
|
let args = argList.map(THIS.evaluate);
|
||||||
let start,end;
|
let start, end;
|
||||||
if (args.length===2){
|
if (args.length === 2) {
|
||||||
start = args[0];
|
start = args[0];
|
||||||
end = args[1];
|
end = args[1];
|
||||||
} else {
|
} else {
|
||||||
start =0;
|
start = 0;
|
||||||
end = args[0];
|
end = args[0];
|
||||||
}
|
}
|
||||||
let previous = THIS.current_environment;
|
let previous = THIS.current_environment;
|
||||||
|
|
@ -267,14 +267,8 @@ export function interpret(init_env, code) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
|
||||||
const statements = parse(code);
|
const statements = parse(code);
|
||||||
for (let i = 0; i < statements.length; i++) {
|
for (let i = 0; i < statements.length; i++) {
|
||||||
THIS.execute(statements[i]);
|
THIS.execute(statements[i]);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
73
js/parser.js
73
js/parser.js
|
|
@ -46,8 +46,14 @@ export function parse(code) {
|
||||||
|
|
||||||
const parse = () => {
|
const parse = () => {
|
||||||
let statements = [];
|
let statements = [];
|
||||||
|
|
||||||
while (!is_at_end()) {
|
while (!is_at_end()) {
|
||||||
|
try {
|
||||||
statements.push(declaration());
|
statements.push(declaration());
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
current = tokens.length - 1; // stop compiling
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return statements;
|
return statements;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +72,12 @@ export function parse(code) {
|
||||||
initializer = expression();
|
initializer = expression();
|
||||||
}
|
}
|
||||||
consume(SEMICOLON, "Expected semicolon");
|
consume(SEMICOLON, "Expected semicolon");
|
||||||
return {class: "var", name:name, initializer: initializer, accept: (visitor) => visitor.visitVariableStatement(name, initializer)};
|
return {
|
||||||
|
class: "var",
|
||||||
|
name: name,
|
||||||
|
initializer: initializer,
|
||||||
|
accept: (visitor) => visitor.visitVariableStatement(name, initializer)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const statement = () => {
|
const statement = () => {
|
||||||
|
|
@ -97,7 +108,7 @@ export function parse(code) {
|
||||||
if (match(MOVING_PILLARS)) {
|
if (match(MOVING_PILLARS)) {
|
||||||
return callStatement("moving_pillars");
|
return callStatement("moving_pillars");
|
||||||
}
|
}
|
||||||
if (match(REPEAT)){
|
if (match(REPEAT)) {
|
||||||
return call_block();
|
return call_block();
|
||||||
}
|
}
|
||||||
if (match(LEFT_BRACE)) {
|
if (match(LEFT_BRACE)) {
|
||||||
|
|
@ -130,7 +141,12 @@ export function parse(code) {
|
||||||
|
|
||||||
if (expr.class === 'Variable') {
|
if (expr.class === 'Variable') {
|
||||||
let name = expr.name;
|
let name = expr.name;
|
||||||
return {class: "assign", var_name: name, init_expr: value, accept: (visitor) => visitor.visitAssignExpr(name, value)};
|
return {
|
||||||
|
class: "assign",
|
||||||
|
var_name: name,
|
||||||
|
init_expr: value,
|
||||||
|
accept: (visitor) => visitor.visitAssignExpr(name, value)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error(equals, "Invalid assignment target.");
|
throw error(equals, "Invalid assignment target.");
|
||||||
|
|
@ -150,17 +166,21 @@ export function parse(code) {
|
||||||
return {class: "call", accept: (visitor) => visitor.visitCallStatement(name, args)};
|
return {class: "call", accept: (visitor) => visitor.visitCallStatement(name, args)};
|
||||||
}
|
}
|
||||||
|
|
||||||
const call_block = () =>{
|
const call_block = () => {
|
||||||
const args = arg_expressions();
|
const args = arg_expressions();
|
||||||
consume(LEFT_BRACE, "Expect block");
|
consume(LEFT_BRACE, "Expect block");
|
||||||
const action = block();
|
const action = block();
|
||||||
return {class: "block", accept: (visitor)=> visitor.visitParametrizedBlock(args, action)};
|
return {class: "block", accept: (visitor) => visitor.visitParametrizedBlock(args, action)};
|
||||||
}
|
}
|
||||||
|
|
||||||
const expressionStatement = () => {
|
const expressionStatement = () => {
|
||||||
const value = expression();
|
const value = expression();
|
||||||
consume(SEMICOLON, "Expected semicolon");
|
consume(SEMICOLON, "Expected semicolon");
|
||||||
return {class: "expressionStatement", expression: value, accept: (visitor) => visitor.visitExpressionStatement(value)};
|
return {
|
||||||
|
class: "expressionStatement",
|
||||||
|
expression: value,
|
||||||
|
accept: (visitor) => visitor.visitExpressionStatement(value)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const block = () => {
|
const block = () => {
|
||||||
|
|
@ -178,7 +198,13 @@ export function parse(code) {
|
||||||
let operator = previous();
|
let operator = previous();
|
||||||
let right = comparison();
|
let right = comparison();
|
||||||
const left = expr;
|
const left = expr;
|
||||||
expr = {class: "binaryExpr", operator: operator, left: expr, right: right, accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)};
|
expr = {
|
||||||
|
class: "binaryExpr",
|
||||||
|
operator: operator,
|
||||||
|
left: expr,
|
||||||
|
right: right,
|
||||||
|
accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +215,13 @@ export function parse(code) {
|
||||||
let operator = previous();
|
let operator = previous();
|
||||||
let right = term();
|
let right = term();
|
||||||
const left = expr;
|
const left = expr;
|
||||||
expr = {class: "binaryExpr", operator: operator, left: expr, right: right, accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)};
|
expr = {
|
||||||
|
class: "binaryExpr",
|
||||||
|
operator: operator,
|
||||||
|
left: expr,
|
||||||
|
right: right,
|
||||||
|
accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +232,13 @@ export function parse(code) {
|
||||||
let operator = previous();
|
let operator = previous();
|
||||||
let right = factor();
|
let right = factor();
|
||||||
const left = expr;
|
const left = expr;
|
||||||
expr = {class: "binaryExpr", operator: operator, left: expr, right: right, accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)};
|
expr = {
|
||||||
|
class: "binaryExpr",
|
||||||
|
operator: operator,
|
||||||
|
left: expr,
|
||||||
|
right: right,
|
||||||
|
accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +249,13 @@ export function parse(code) {
|
||||||
let operator = previous();
|
let operator = previous();
|
||||||
let right = unary();
|
let right = unary();
|
||||||
const left = expr;
|
const left = expr;
|
||||||
expr = {class: "binaryExpr", operator: operator, left: expr, right: right, accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)};
|
expr = {
|
||||||
|
class: "binaryExpr",
|
||||||
|
operator: operator,
|
||||||
|
left: expr,
|
||||||
|
right: right,
|
||||||
|
accept: (visitor) => visitor.visitBinaryExpr(operator, left, right)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +264,12 @@ export function parse(code) {
|
||||||
if (match(BANG, MINUS)) {
|
if (match(BANG, MINUS)) {
|
||||||
let operator = previous();
|
let operator = previous();
|
||||||
let right = unary();
|
let right = unary();
|
||||||
return {class: "unaryExpr", operator: operator, right: right, accept: (visitor) => visitor.visitUnaryExpr(operator, right)};
|
return {
|
||||||
|
class: "unaryExpr",
|
||||||
|
operator: operator,
|
||||||
|
right: right,
|
||||||
|
accept: (visitor) => visitor.visitUnaryExpr(operator, right)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return primary();
|
return primary();
|
||||||
}
|
}
|
||||||
|
|
@ -235,7 +284,7 @@ export function parse(code) {
|
||||||
if (check(NUMBER)) {
|
if (check(NUMBER)) {
|
||||||
advance();
|
advance();
|
||||||
let number = parseFloat(previous().literal);
|
let number = parseFloat(previous().literal);
|
||||||
return {class: "number", value:number, accept: (visitor) => visitor.visitLiteralExpr(number)};
|
return {class: "number", value: number, accept: (visitor) => visitor.visitLiteralExpr(number)};
|
||||||
}
|
}
|
||||||
if (check(STRING)) {
|
if (check(STRING)) {
|
||||||
advance();
|
advance();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue