Skip to content

Commit

Permalink
fix(lex,parse): Allow stop statements (#247)
Browse files Browse the repository at this point in the history
fixes #192
  • Loading branch information
TwitchBronBron authored and sjbarag committed May 29, 2019
1 parent 165b129 commit 3a6f30b
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/lexer/Lexeme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export enum Lexeme {
Rem = "Rem",
Return = "Return",
Step = "Step",
Stop = "Stop",
Sub = "Sub",
Tab = "Tab",
To = "To",
Expand Down
1 change: 1 addition & 0 deletions src/lexer/ReservedWords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export const KeyWords: { [key: string]: L } = {
rem: L.Rem,
return: L.Return,
step: L.Step,
stop: L.Stop,
sub: L.Sub,
to: L.To,
true: L.True,
Expand Down
18 changes: 17 additions & 1 deletion src/parser/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const allowedProperties = [
Lexeme.Rem,
Lexeme.Return,
Lexeme.Step,
Lexeme.Stop,
Lexeme.Sub,
Lexeme.Tab,
Lexeme.To,
Expand Down Expand Up @@ -552,6 +553,10 @@ export class Parser {
return libraryStatement();
}

if (check(Lexeme.Stop)) {
return stopStatement();
}

if (check(Lexeme.If)) {
return ifStatement();
}
Expand Down Expand Up @@ -1113,13 +1118,24 @@ export class Parser {
* Parses an `end` statement
* @returns an AST representation of an `end` statement.
*/
function endStatement(): Stmt.End {
function endStatement() {
let tokens = { end: advance() };

while (match(Lexeme.Newline));

return new Stmt.End(tokens);
}
/**
* Parses a `stop` statement
* @returns an AST representation of a `stop` statement
*/
function stopStatement() {
let tokens = { stop: advance() };

while (match(Lexeme.Newline, Lexeme.Colon));

return new Stmt.Stop(tokens);
}

/**
* Parses a block, looking for a specific terminating Lexeme to denote completion.
Expand Down
21 changes: 21 additions & 0 deletions src/parser/Statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,27 @@ export class End implements Statement {
}
}

export class Stop implements Statement {
constructor(
readonly tokens: {
stop: Token;
}
) {}

accept<R>(visitor: Visitor<R>): BrsType {
//TODO implement this in the runtime. It should pause code execution until a `c` command is issued from the console
throw new Error("Not implemented");
}

get location() {
return {
file: this.tokens.stop.location.file,
start: this.tokens.stop.location.start,
end: this.tokens.stop.location.end,
};
}
}

export class For implements Statement {
constructor(
readonly tokens: {
Expand Down
5 changes: 5 additions & 0 deletions test/lexer/Lexer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ describe("lexer", () => {
]);
});

it("gives the `stop` keyword its own Lexeme", () => {
let { tokens } = Lexer.scan("stop");
expect(tokens.map(t => t.kind)).toEqual([Lexeme.Stop, Lexeme.Eof]);
});

it("aliases '?' to 'print'", () => {
let { tokens } = Lexer.scan("?2");
expect(tokens.map(t => t.kind)).toEqual([Lexeme.Print, Lexeme.Integer, Lexeme.Eof]);
Expand Down
42 changes: 42 additions & 0 deletions test/parser/statement/Stop.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const brs = require("brs");
const { Lexeme } = brs.lexer;
const { Int32 } = brs.types;

const { token, identifier, EOF } = require("../ParserTests");

describe("stop statement", () => {
it("cannot be used as a local variable", () => {
let { statements, errors } = brs.parser.Parser.parse([
token(Lexeme.Stop, "stop"),
token(Lexeme.Equal, "="),
token(Lexeme.True, "true"),
EOF,
]);

//should be an error
expect(errors).toHaveLength(1);
expect(statements).toBeDefined();
expect(statements).not.toBeNull();
expect(statements).toMatchSnapshot();
});

it("is valid as a statement", () => {
let { statements, errors } = brs.parser.Parser.parse([token(Lexeme.Stop, "stop"), EOF]);
expect(errors[0]).toBeUndefined();
expect(statements).toMatchSnapshot();
});

it("can be used as an object property", () => {
let { tokens } = brs.lexer.Lexer.scan(`
sub Main()
theObject = {
stop: false
}
theObject.stop = true
end sub
`);
let { statements, errors } = brs.parser.Parser.parse(tokens);
expect(errors.length).toEqual(0);
expect(statements).toMatchSnapshot();
});
});
Loading

0 comments on commit 3a6f30b

Please sign in to comment.