aboutsummaryrefslogtreecommitdiff
path: root/parser/parser.go
diff options
context:
space:
mode:
Diffstat (limited to 'parser/parser.go')
-rw-r--r--parser/parser.go78
1 files changed, 69 insertions, 9 deletions
diff --git a/parser/parser.go b/parser/parser.go
index 0c4a9b7..e02595c 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -17,6 +17,7 @@ const (
PRODUCT // *
PREFIX // -X or !X
CALL // myFunction(X)
+ INDEX // array[index]
)
var precedences = map[token.TokenType]int{
@@ -29,6 +30,7 @@ var precedences = map[token.TokenType]int{
token.SLASH: PRODUCT,
token.ASTERISK: PRODUCT,
token.LPAREN: CALL,
+ token.LBRACKET: INDEX,
}
type (
@@ -56,6 +58,7 @@ func New(l *lexer.Lexer) *Parser {
p.prefixParseFns = make(map[token.TokenType]prefixParseFn)
p.registerPrefix(token.IDENT, p.parseIdentifier)
p.registerPrefix(token.INT, p.parseIntegerLiteral)
+ p.registerPrefix(token.STRING, p.parseStringLiteral)
p.registerPrefix(token.BANG, p.parsePrefixExpression)
p.registerPrefix(token.MINUS, p.parsePrefixExpression)
p.registerPrefix(token.TRUE, p.parseBoolean)
@@ -63,6 +66,8 @@ func New(l *lexer.Lexer) *Parser {
p.registerPrefix(token.LPAREN, p.parseGroupedExpression)
p.registerPrefix(token.IF, p.parseIfExpression)
p.registerPrefix(token.FUNCTION, p.parseFunctionLiteral)
+ p.registerPrefix(token.LBRACKET, p.parseArrayLiteral)
+ p.registerPrefix(token.LBRACE, p.parseHashLiteral)
p.infixParseFns = make(map[token.TokenType]infixParseFn)
p.registerInfix(token.PLUS, p.parseInfixExpression)
@@ -75,6 +80,7 @@ func New(l *lexer.Lexer) *Parser {
p.registerInfix(token.GT, p.parseInfixExpression)
p.registerInfix(token.LPAREN, p.parseCallExpression)
+ p.registerInfix(token.LBRACKET, p.parseIndexExpression)
// Read two tokens, so curToken and peekToken are both set
p.nextToken()
@@ -254,6 +260,10 @@ func (p *Parser) parseIntegerLiteral() ast.Expression {
return lit
}
+func (p *Parser) parseStringLiteral() ast.Expression {
+ return &ast.StringLiteral{Token: p.curToken, Value: p.curToken.Literal}
+}
+
func (p *Parser) parsePrefixExpression() ast.Expression {
expression := &ast.PrefixExpression{
Token: p.curToken,
@@ -394,32 +404,82 @@ func (p *Parser) parseFunctionParameters() []*ast.Identifier {
func (p *Parser) parseCallExpression(function ast.Expression) ast.Expression {
exp := &ast.CallExpression{Token: p.curToken, Function: function}
- exp.Arguments = p.parseCallArguments()
+ exp.Arguments = p.parseExpressionList(token.RPAREN)
return exp
}
-func (p *Parser) parseCallArguments() []ast.Expression {
- args := []ast.Expression{}
+func (p *Parser) parseExpressionList(end token.TokenType) []ast.Expression {
+ list := []ast.Expression{}
- if p.peekTokenIs(token.RPAREN) {
+ if p.peekTokenIs(end) {
p.nextToken()
- return args
+ return list
}
p.nextToken()
- args = append(args, p.parseExpression(LOWEST))
+ list = append(list, p.parseExpression(LOWEST))
for p.peekTokenIs(token.COMMA) {
p.nextToken()
p.nextToken()
- args = append(args, p.parseExpression(LOWEST))
+ list = append(list, p.parseExpression(LOWEST))
}
- if !p.expectPeek(token.RPAREN) {
+ if !p.expectPeek(end) {
+ return nil
+ }
+
+ return list
+}
+
+func (p *Parser) parseArrayLiteral() ast.Expression {
+ array := &ast.ArrayLiteral{Token: p.curToken}
+
+ array.Elements = p.parseExpressionList(token.RBRACKET)
+
+ return array
+}
+
+func (p *Parser) parseIndexExpression(left ast.Expression) ast.Expression {
+ exp := &ast.IndexExpression{Token: p.curToken, Left: left}
+
+ p.nextToken()
+ exp.Index = p.parseExpression(LOWEST)
+
+ if !p.expectPeek(token.RBRACKET) {
+ return nil
+ }
+
+ return exp
+}
+
+func (p *Parser) parseHashLiteral() ast.Expression {
+ hash := &ast.HashLiteral{Token: p.curToken}
+ hash.Pairs = make(map[ast.Expression]ast.Expression)
+
+ for !p.peekTokenIs(token.RBRACE) {
+ p.nextToken()
+ key := p.parseExpression(LOWEST)
+
+ if !p.expectPeek(token.COLON) {
+ return nil
+ }
+
+ p.nextToken()
+ value := p.parseExpression(LOWEST)
+
+ hash.Pairs[key] = value
+
+ if !p.peekTokenIs(token.RBRACE) && !p.expectPeek(token.COMMA) {
+ return nil
+ }
+ }
+
+ if !p.expectPeek(token.RBRACE) {
return nil
}
- return args
+ return hash
}
func (p *Parser) registerPrefix(tokenType token.TokenType, fn prefixParseFn) {