in benchmarks/JetStream2/ARES-6/Basic/parser.js [313:524]
function parseStatement()
{
let statement = {};
statement.lineNumber = consumeKind("userLineNumber").userLineNumber;
program.statements.set(statement.lineNumber, statement);
let command = nextToken();
statement.sourceLineNumber = command.sourceLineNumber;
switch (command.kind) {
case "keyword":
switch (command.string.toLowerCase()) {
case "def":
statement.process = Basic.Def;
statement.name = consumeKind("identifier");
statement.parameters = [];
if (peekToken().string == "(") {
do {
nextToken();
statement.parameters.push(consumeKind("identifier"));
} while (peekToken().string == ",");
}
statement.expression = parseNumericExpression();
break;
case "let":
statement.process = Basic.Let;
statement.variable = parseVariable();
consumeToken("=");
if (statement.process == Basic.Let)
statement.expression = parseNumericExpression();
else
statement.expression = parseStringExpression();
break;
case "go": {
let next = nextToken();
if (next.string == "to")
parseGoToStatement();
else if (next.string == "sub")
parseGoSubStatement();
else
throw new Error("At " + next.sourceLineNumber + ": expected to or sub but got: " + next.string);
break;
}
case "goto":
parseGoToStatement();
break;
case "gosub":
parseGoSubStatement();
break;
case "if":
statement.process = Basic.If;
statement.condition = parseRelationalExpression();
consumeToken("then");
statement.target = parseNonNegativeInteger();
break;
case "return":
statement.process = Basic.Return;
break;
case "stop":
statement.process = Basic.Stop;
break;
case "on":
statement.process = Basic.On;
statement.expression = parseNumericExpression();
if (peekToken().string == "go") {
consumeToken("go");
consumeToken("to");
} else
consumeToken("goto");
statement.targets = [];
for (;;) {
statement.targets.push(parseNonNegativeInteger());
if (peekToken().string != ",")
break;
nextToken();
}
break;
case "for":
statement.process = Basic.For;
statement.variable = consumeKind("identifier").string;
consumeToken("=");
statement.initial = parseNumericExpression();
consumeToken("to");
statement.limit = parseNumericExpression();
if (peekToken().string == "step") {
nextToken();
statement.step = parseNumericExpression();
} else
statement.step = {evaluate: Basic.Const, value: 1};
consumeKind("newLine");
let lastStatement = parseStatements();
if (lastStatement.process != Basic.Next)
throw new Error("At " + lastStatement.sourceLineNumber + ": expected next statement");
if (lastStatement.variable != statement.variable)
throw new Error("At " + lastStatement.sourceLineNumber + ": expected next for " + statement.variable + " but got " + lastStatement.variable);
lastStatement.target = statement;
statement.target = lastStatement;
return statement;
case "next":
statement.process = Basic.Next;
statement.variable = consumeKind("identifier").string;
break;
case "print": {
statement.process = Basic.Print;
statement.items = [];
let ok = true;
while (ok) {
switch (peekToken().string) {
case ",":
nextToken();
statement.items.push({kind: "comma"});
break;
case ";":
nextToken();
break;
case "tab":
nextToken();
consumeToken("(");
statement.items.push({kind: "tab", value: parseNumericExpression()});
break;
case "\n":
ok = false;
break;
default:
if (isStringExpression()) {
statement.items.push({kind: "string", value: parseStringExpression()});
break;
}
statement.items.push({kind: "number", value: parseNumericExpression()});
break;
}
}
break;
}
case "input":
statement.process = Basic.Input;
statement.items = [];
for (;;) {
stament.items.push(parseVariable());
if (peekToken().string != ",")
break;
nextToken();
}
break;
case "read":
statement.process = Basic.Read;
statement.items = [];
for (;;) {
stament.items.push(parseVariable());
if (peekToken().string != ",")
break;
nextToken();
}
break;
case "restore":
statement.process = Basic.Restore;
break;
case "data":
for (;;) {
program.data.push(parseConstant());
if (peekToken().string != ",")
break;
nextToken();
}
break;
case "dim":
statement.process = Basic.Dim;
statement.items = [];
for (;;) {
let name = consumeKind("identifier").string;
consumeToken("(");
let bounds = [];
bounds.push(parseNonNegativeInteger());
if (peekToken().string == ",") {
nextToken();
bounds.push(parseNonNegativeInteger());
}
consumeToken(")");
statement.items.push({name, bounds});
if (peekToken().string != ",")
break;
consumeToken(",");
}
break;
case "option": {
consumeToken("base");
let base = parseNonNegativeInteger();
if (base != 0 && base != 1)
throw new Error("At " + command.sourceLineNumber + ": unexpected base: " + base);
program.base = base;
break;
}
case "randomize":
statement.process = Basic.Randomize;
break;
case "end":
statement.process = Basic.End;
break;
default:
throw new Error("At " + command.sourceLineNumber + ": unexpected command but got: " + command.string);
}
break;
case "remark":
// Just ignore it.
break;
default:
throw new Error("At " + command.sourceLineNumber + ": expected command but got: " + command.string + " (of kind " + command.kind + ")");
}
consumeKind("newLine");
return statement;
}