aboutsummaryrefslogtreecommitdiff
path: root/parser/parser.go
diff options
context:
space:
mode:
authorBobby <[email protected]>2023-11-08 17:56:53 +0000
committerBobby <[email protected]>2023-11-08 17:56:53 +0000
commit152e63c1865d8bc1df36f54218cc9286b7fd1ff2 (patch)
tree4c8b996fb65d8b86a0c0d1ee620ff5f13732963e /parser/parser.go
parentaed19195e4476ed6933eac2d1d748bcdcb4277e7 (diff)
downloadmana-152e63c1865d8bc1df36f54218cc9286b7fd1ff2.tar.xz
mana-152e63c1865d8bc1df36f54218cc9286b7fd1ff2.zip
parse infix operators
Diffstat (limited to 'parser/parser.go')
-rw-r--r--parser/parser.go72
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
+}