Parse call expressions and gets rid of the TODOs in parse let and return.

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2025-01-05 16:59:06 -08:00
parent 985cf24fbc
commit 44f936affb
4 changed files with 165 additions and 46 deletions

View file

@ -49,6 +49,7 @@ func New(l *lexer.Lexer) *Parser {
p.registerInfix(token.LT, p.parseInfixExpression)
p.registerInfix(token.EQ, p.parseInfixExpression)
p.registerInfix(token.NOT_EQ, p.parseInfixExpression)
p.registerInfix(token.LPAREN, p.parseCallExpression)
// TODO: figure out why this can't be done from `parseProgram`
p.nextToken()
p.nextToken()
@ -90,7 +91,7 @@ func (p *Parser) parseBlockStatement() *ast.BlockStatement {
if stmt != nil {
block.Statements = append(block.Statements, stmt)
}
// Consume the semicolon.
// Consume the last token in the statement.
p.nextToken()
}
return block
@ -105,8 +106,10 @@ func (p *Parser) parseLetStatement() ast.Statement {
if !p.nextTokenIfPeekIs(token.ASSIGN) {
return nil
}
// TODO: Skipping until we find the semicolon to avoid parsing the expression.
for !p.curTokenIs(token.SEMICOLON) {
// Consume the assign.
p.nextToken()
stmt.Value = p.parseExpression(LOWEST)
if p.peekTokenIs(token.SEMICOLON) {
p.nextToken()
}
return stmt
@ -115,8 +118,8 @@ func (p *Parser) parseLetStatement() ast.Statement {
func (p *Parser) parseReturnStatement() ast.Statement {
stmt := &ast.ReturnStatement{Token: p.curToken}
p.nextToken()
// TODO: Skipping until we find the semicolon to avoid parsing the expression.
for !p.curTokenIs(token.SEMICOLON) {
stmt.ReturnValue = p.parseExpression(LOWEST)
if p.peekTokenIs(token.SEMICOLON) {
p.nextToken()
}
return stmt
@ -272,6 +275,35 @@ func (p *Parser) parseFunctionParameters() []*ast.Identifier {
return params
}
func (p *Parser) parseCallExpression(function ast.Expression) ast.Expression {
call := &ast.CallExpression{Token: p.curToken, Function: function}
call.Arguments = p.parseCallArguments()
return call
}
func (p *Parser) parseCallArguments() []ast.Expression {
args := []ast.Expression{}
if p.peekTokenIs(token.RPAREN) {
p.nextToken()
return args
}
// Consume the LPAREN
p.nextToken()
args = append(args, p.parseExpression(LOWEST))
for p.peekTokenIs(token.COMMA) {
// Consume last token of the previous expression.
p.nextToken()
// Consume the comma.
p.nextToken()
args = append(args, p.parseExpression(LOWEST))
}
if !p.nextTokenIfPeekIs(token.RPAREN) {
// TODO: Would be good to emit an error here.
return nil
}
return args
}
func (p *Parser) curTokenIs(typ token.TokenType) bool {
return p.curToken.Type == typ
}