diff options
Diffstat (limited to 'parser/parser.go')
| -rw-r--r-- | parser/parser.go | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/parser/parser.go b/parser/parser.go index b9fb91f..6645da1 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -20,6 +20,17 @@ const ( CALL // myFunction(X) ) +var precedences = map[tokens.TokenType]int{ + tokens.EQ: EQUALS, + tokens.NOT_EQ: EQUALS, + tokens.LT: LESSGREATER, + tokens.GT: LESSGREATER, + tokens.PLUS: SUM, + tokens.MINUS: SUM, + tokens.SLASH: PRODUCT, + tokens.ASTERISK: PRODUCT, +} + type ( prefixParseFn func() ast.Expression infixParseFn func(ast.Expression) ast.Expression @@ -55,6 +66,17 @@ func New(l *lexer.Lexer) *Parser { p.registerPrefix(tokens.BANG, p.parsePrefixExpression) p.registerPrefix(tokens.MINUS, p.parsePrefixExpression) + // Initialize the infix parse functions. + p.infixParseFns = make(map[tokens.TokenType]infixParseFn) + p.registerInfix(tokens.PLUS, p.parseInfixExpression) + p.registerInfix(tokens.MINUS, p.parseInfixExpression) + p.registerInfix(tokens.SLASH, p.parseInfixExpression) + p.registerInfix(tokens.ASTERISK, p.parseInfixExpression) + p.registerInfix(tokens.EQ, p.parseInfixExpression) + p.registerInfix(tokens.NOT_EQ, p.parseInfixExpression) + p.registerInfix(tokens.LT, p.parseInfixExpression) + p.registerInfix(tokens.GT, p.parseInfixExpression) + return p } @@ -193,14 +215,27 @@ func (p *Parser) noPrefixParseFnError(t tokens.TokenType) { // parseExpression parses an expression. func (p *Parser) parseExpression(precedence int) ast.Expression { - var prefix = p.prefixParseFns[p.curToken.Type] + prefix := p.prefixParseFns[p.curToken.Type] if prefix == nil { p.noPrefixParseFnError(p.curToken.Type) return nil } - var leftExp ast.Expression = prefix() + leftExp := prefix() + + for !p.peekTokenIs(tokens.SEMICOLON) && precedence < p.peekPrecedence() { + infix := p.infixParseFns[p.peekToken.Type] + + if infix == nil { + return leftExp + } + + p.nextToken() + + leftExp = infix(leftExp) + + } return leftExp } @@ -219,6 +254,21 @@ func (p *Parser) parsePrefixExpression() ast.Expression { return expression } +// parseInfixExpression parses an infix expression. +func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression { + expression := &ast.InfixExpression{ + Token: p.curToken, + Operator: p.curToken.Literal, + Left: left, + } + + precedence := p.curPrecedence() + p.nextToken() + expression.Right = p.parseExpression(precedence) + + return expression +} + // curTokenIs returns true if the current token is of the given type. func (p *Parser) curTokenIs(t tokens.TokenType) bool { return p.curToken.Type == t @@ -253,3 +303,21 @@ func (p *Parser) peekError(t tokens.TokenType) { p.errors = append(p.errors, msg) } + +// peek and cur precedences + +func (p *Parser) peekPrecedence() int { + if p, ok := precedences[p.peekToken.Type]; ok { + return p + } + + return LOWEST +} + +func (p *Parser) curPrecedence() int { + if p, ok := precedences[p.curToken.Type]; ok { + return p + } + + return LOWEST +} |
