Created
August 18, 2020 05:25
-
-
Save mrnugget/4ea12bc08345c7f13881e6b600c32a46 to your computer and use it in GitHub Desktop.
Change the Monkey parser to expect expression statements to either end in a semicolon, a closing brace (because of `if (x) { foo }`) or EOF
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
diff --git a/parser/parser.go b/parser/parser.go | |
index dbd581d..c7ebdf9 100644 | |
--- a/parser/parser.go | |
+++ b/parser/parser.go | |
@@ -114,6 +114,20 @@ func (p *Parser) expectPeek(t token.TokenType) bool { | |
} | |
} | |
+func (p *Parser) expectStatementEnd() bool { | |
+ switch p.peekToken.Type { | |
+ case token.SEMICOLON, token.EOF: | |
+ p.nextToken() | |
+ return true | |
+ case token.RBRACE: | |
+ // do not consume it | |
+ return true | |
+ default: | |
+ p.peekError(token.SEMICOLON) | |
+ return false | |
+ } | |
+} | |
+ | |
func (p *Parser) Errors() []string { | |
return p.errors | |
} | |
@@ -202,9 +216,7 @@ func (p *Parser) parseExpressionStatement() *ast.ExpressionStatement { | |
stmt.Expression = p.parseExpression(LOWEST) | |
- if p.peekTokenIs(token.SEMICOLON) { | |
- p.nextToken() | |
- } | |
+ p.expectStatementEnd() | |
return stmt | |
} | |
diff --git a/parser/parser_test.go b/parser/parser_test.go | |
index 75f08bf..6865628 100644 | |
--- a/parser/parser_test.go | |
+++ b/parser/parser_test.go | |
@@ -656,6 +656,23 @@ func TestCallExpressionParsing(t *testing.T) { | |
testInfixExpression(t, exp.Arguments[2], 4, "+", 5) | |
} | |
+func TestCallExpressionWithoutParens(t *testing.T) { | |
+ input := `puts "hello"` | |
+ | |
+ l := lexer.New(input) | |
+ p := New(l) | |
+ _ = p.ParseProgram() | |
+ | |
+ errs := p.Errors() | |
+ if len(errs) != 1 { | |
+ t.Errorf("expected parser errors, but got none") | |
+ } | |
+ | |
+ if have, want := errs[0], "expected next token to be ;, got STRING instead"; have != want { | |
+ t.Errorf("wrong error. want=%q, have=%q", want, have) | |
+ } | |
+} | |
+ | |
func TestCallExpressionParameterParsing(t *testing.T) { | |
tests := []struct { | |
input string |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment