-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(parse): Consume try, catch, and end try lexemes
Throwing exceptions and catching them aren't yet supported in `brs`, so executing only the `try` block seems to be a reasonable "bare minimum" approach to try/catch support. Handle `try`, `catch`, and `end try` lexemes in the parser, emitting TryCatch statements for the interpreter to execute naïvely. see #554
- Loading branch information
Showing
10 changed files
with
1,256 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
sub main() | ||
a = 5 | ||
|
||
print "[pre_try] a = " a | ||
try | ||
a = a * 2 | ||
print "[in_try] a = " a | ||
catch e | ||
' currently unimplemented | ||
end try | ||
|
||
print "[post_try] a = " a | ||
end sub |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
const brs = require("brs"); | ||
|
||
const { deindent } = require("../ParserTests"); | ||
|
||
function scan(str) { | ||
return brs.lexer.Lexer.scan(str).tokens; | ||
} | ||
|
||
describe("parser try/catch statements", () => { | ||
let parser; | ||
|
||
beforeEach(() => { | ||
parser = new brs.parser.Parser(); | ||
}); | ||
|
||
it("requires catch to end try block", () => { | ||
const { errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
try | ||
print "in try" | ||
end try | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual( | ||
expect.arrayContaining([new Error("Found unexpected token 'end try'")]) | ||
); | ||
}); | ||
|
||
it("requires variable binding for caught error", () => { | ||
const { errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
try | ||
print "in try" | ||
catch | ||
print "in catch" | ||
end try | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual( | ||
expect.arrayContaining([ | ||
new Error("Expected variable name for caught error after 'catch'"), | ||
]) | ||
); | ||
}); | ||
|
||
it("requires end try or endtry to end catch block", () => { | ||
const { errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
try | ||
print "in try" | ||
catch e | ||
print "in catch" | ||
end if | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual( | ||
expect.arrayContaining([ | ||
new Error( | ||
"(At end of file) Expected 'end try' or 'endtry' to terminate catch block" | ||
), | ||
]) | ||
); | ||
}); | ||
|
||
it("accepts try/catch/end try", () => { | ||
const { statements, errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
try | ||
print "in try" | ||
catch e | ||
print "in catch" | ||
end try | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual([]); | ||
expect(statements).toBeDefined(); | ||
expect(statements).not.toBeNull(); | ||
expect(statements).toMatchSnapshot(); | ||
}); | ||
|
||
it("accepts try/catch/endtry", () => { | ||
const { statements, errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
sub main() | ||
try | ||
print "in try" | ||
catch e | ||
print "in catch" | ||
endtry | ||
end sub | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual([]); | ||
expect(statements).toBeDefined(); | ||
expect(statements).not.toBeNull(); | ||
expect(statements).toMatchSnapshot(); | ||
}); | ||
|
||
it("allows try/catch to nest in try", () => { | ||
const { statements, errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
try | ||
print "outer try" | ||
try | ||
print "inner try | ||
catch e | ||
print "in upper catch" | ||
end try | ||
catch e | ||
print "in catch" | ||
endtry | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual([]); | ||
expect(statements).toBeDefined(); | ||
expect(statements).not.toBeNull(); | ||
expect(statements).toMatchSnapshot(); | ||
}); | ||
|
||
it("allows try and catch as variable names", () => { | ||
const { statements, errors } = parser.parse( | ||
scan( | ||
deindent(` | ||
try = "attempt" | ||
catch = "whoops, dropped it" | ||
`) | ||
) | ||
); | ||
|
||
expect(errors).toEqual([]); | ||
expect(statements).toBeDefined(); | ||
expect(statements).not.toBeNull(); | ||
expect(statements).toMatchSnapshot(); | ||
}); | ||
}); |
Oops, something went wrong.