aboutsummaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-03-25 01:50:10 +0100
committerDimitri Sokolyuk <demon@dim13.org>2018-03-25 01:50:10 +0100
commite5ed6e13a4adbbe61317194af36c33c82b33c90f (patch)
tree790b5c954959ac852f0072f8bb2bd3137a4dac48 /parser
parent88efa3eb20001d1dc23e6b5a8413ea7adf10294e (diff)
lost chapter
Diffstat (limited to 'parser')
-rw-r--r--parser/parser.go19
-rw-r--r--parser/parser_test.go47
2 files changed, 66 insertions, 0 deletions
diff --git a/parser/parser.go b/parser/parser.go
index 300f2d7..4795761 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -68,6 +68,7 @@ func New(l *lexer.Lexer) *Parser {
p.registerPrefix(token.FUNCTION, p.parseFunctionLiteral)
p.registerPrefix(token.LBRACKET, p.parseArrayLiteral)
p.registerPrefix(token.LBRACE, p.parseHashLiteral)
+ p.registerPrefix(token.MACRO, p.parseMacroLiteral)
p.infixParseFns = make(map[token.TokenType]infixParseFn)
p.registerInfix(token.PLUS, p.parseInfixExpression)
@@ -482,6 +483,24 @@ func (p *Parser) parseHashLiteral() ast.Expression {
return hash
}
+func (p *Parser) parseMacroLiteral() ast.Expression {
+ lit := &ast.MacroLiteral{Token: p.curToken}
+
+ if !p.expectPeek(token.LPAREN) {
+ return nil
+ }
+
+ lit.Parameters = p.parseFunctionParameters()
+
+ if !p.expectPeek(token.LBRACE) {
+ return nil
+ }
+
+ lit.Body = p.parseBlockStatement()
+
+ return lit
+}
+
func (p *Parser) registerPrefix(tokenType token.TokenType, fn prefixParseFn) {
p.prefixParseFns[tokenType] = fn
}
diff --git a/parser/parser_test.go b/parser/parser_test.go
index 7fe5268..df040ad 100644
--- a/parser/parser_test.go
+++ b/parser/parser_test.go
@@ -1088,3 +1088,50 @@ func checkParserErrors(t *testing.T, p *Parser) {
}
t.FailNow()
}
+
+func TestMacroLiteralParsing(t *testing.T) {
+ input := `macro(x, y) { x + y; }`
+
+ l := lexer.New(input)
+ p := New(l)
+ program := p.ParseProgram()
+ checkParserErrors(t, p)
+
+ if len(program.Statements) != 1 {
+ t.Fatalf("program.Statements does not contain %d statements. got=%d\n",
+ 1, len(program.Statements))
+ }
+
+ stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
+ if !ok {
+ t.Fatalf("statement is not ast.ExpressionStatement. got=%T",
+ program.Statements[0])
+ }
+
+ macro, ok := stmt.Expression.(*ast.MacroLiteral)
+ if !ok {
+ t.Fatalf("stmt.Expression is not ast.MacroLiteral. got=%T",
+ stmt.Expression)
+ }
+
+ if len(macro.Parameters) != 2 {
+ t.Fatalf("macro literal parameters wrong. want 2, got=%d\n",
+ len(macro.Parameters))
+ }
+
+ testLiteralExpression(t, macro.Parameters[0], "x")
+ testLiteralExpression(t, macro.Parameters[1], "y")
+
+ if len(macro.Body.Statements) != 1 {
+ t.Fatalf("macro.Body.Statements has not 1 statements. got=%d\n",
+ len(macro.Body.Statements))
+ }
+
+ bodyStmt, ok := macro.Body.Statements[0].(*ast.ExpressionStatement)
+ if !ok {
+ t.Fatalf("macro body stmt is not ast.ExpressionStatement. got=%T",
+ macro.Body.Statements[0])
+ }
+
+ testInfixExpression(t, bodyStmt.Expression, "x", "+", "y")
+}