|
|
@@ -27,7 +27,7 @@ const (
|
|
|
CALL // myFunction(X)
|
|
|
)
|
|
|
|
|
|
-// 指派 token 类型的优先级
|
|
|
+// precedences 指派 token 类型的优先级
|
|
|
var precedences = map[token.TypeToken]int{
|
|
|
token.EQ: EQUALS,
|
|
|
token.NOT_EQ: EQUALS,
|
|
|
@@ -37,6 +37,7 @@ var precedences = map[token.TypeToken]int{
|
|
|
token.MINUS: SUM,
|
|
|
token.ASTERISK: PRODUCT,
|
|
|
token.SLASH: PRODUCT,
|
|
|
+ token.LPAREN: CALL,
|
|
|
}
|
|
|
|
|
|
type (
|
|
|
@@ -81,6 +82,7 @@ func New(l *lexer.Lexer) *Parser {
|
|
|
p.registerInfix(token.NOT_EQ, p.parseInfixExpression)
|
|
|
p.registerInfix(token.GT, p.parseInfixExpression)
|
|
|
p.registerInfix(token.LT, p.parseInfixExpression)
|
|
|
+ p.registerInfix(token.LPAREN, p.parseCallExpression)
|
|
|
|
|
|
// Read two tokens, so curToken and peekToken are both set
|
|
|
p.nextToken()
|
|
|
@@ -89,6 +91,32 @@ func New(l *lexer.Lexer) *Parser {
|
|
|
return p
|
|
|
}
|
|
|
|
|
|
+func (p *Parser) ParseProgram() *ast.Program {
|
|
|
+ program := &ast.Program{}
|
|
|
+ program.Statements = []ast.Statement{}
|
|
|
+
|
|
|
+ for !p.curTokenIs(token.EOF) {
|
|
|
+ stmt := p.parseStatement()
|
|
|
+ if stmt != nil {
|
|
|
+ program.Statements = append(program.Statements, stmt)
|
|
|
+ }
|
|
|
+ p.nextToken()
|
|
|
+
|
|
|
+ }
|
|
|
+ return program
|
|
|
+}
|
|
|
+
|
|
|
+func (p *Parser) parseStatement() ast.Statement {
|
|
|
+ switch p.curToken.Type {
|
|
|
+ case token.LET:
|
|
|
+ return p.parseLetStatement()
|
|
|
+ case token.RETURN:
|
|
|
+ return p.parseReturnStatement()
|
|
|
+ default:
|
|
|
+ return p.parseExpressionStatement()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func (p *Parser) parseIdentifier() ast.Expression {
|
|
|
return &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal}
|
|
|
}
|
|
|
@@ -173,6 +201,13 @@ func (p *Parser) parseIntegerLiteral() ast.Expression {
|
|
|
|
|
|
return lit
|
|
|
}
|
|
|
+func (p *Parser) parseCallExpression(left ast.Expression) ast.Expression {
|
|
|
+ defer untrace(trace("parseCallExpression"))
|
|
|
+ // add(2,3) --> Function: add
|
|
|
+ exp := &ast.CallExpression{Token: p.curToken, Function: left}
|
|
|
+ exp.Arguments = p.parseCallArguments()
|
|
|
+ return exp
|
|
|
+}
|
|
|
func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
|
|
|
defer untrace(trace("parseInfixExpression"))
|
|
|
exp := &ast.InfixExpression{
|
|
|
@@ -233,32 +268,6 @@ func (p *Parser) nextToken() {
|
|
|
p.peekToken = p.l.NextToken()
|
|
|
}
|
|
|
|
|
|
-func (p *Parser) ParseProgram() *ast.Program {
|
|
|
- program := &ast.Program{}
|
|
|
- program.Statements = []ast.Statement{}
|
|
|
-
|
|
|
- for !p.curTokenIs(token.EOF) {
|
|
|
- stmt := p.parseStatement()
|
|
|
- if stmt != nil {
|
|
|
- program.Statements = append(program.Statements, stmt)
|
|
|
- }
|
|
|
- p.nextToken()
|
|
|
-
|
|
|
- }
|
|
|
- return program
|
|
|
-}
|
|
|
-
|
|
|
-func (p *Parser) parseStatement() ast.Statement {
|
|
|
- switch p.curToken.Type {
|
|
|
- case token.LET:
|
|
|
- return p.parseLetStatement()
|
|
|
- case token.RETURN:
|
|
|
- return p.parseReturnStatement()
|
|
|
- default:
|
|
|
- return p.parseExpressionStatement()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// let <identifier> = <expression>;
|
|
|
func (p *Parser) parseLetStatement() *ast.LetStatement {
|
|
|
stmt := &ast.LetStatement{Token: p.curToken}
|
|
|
@@ -275,9 +284,8 @@ func (p *Parser) parseLetStatement() *ast.LetStatement {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- // TODO: we're skipping the expression until we
|
|
|
- // we encounter a semicolon
|
|
|
-
|
|
|
+ p.nextToken()
|
|
|
+ stmt.Value = p.parseExpression(LOWEST)
|
|
|
// ;
|
|
|
for !p.curTokenIs(token.SEMICOLON) {
|
|
|
p.nextToken()
|
|
|
@@ -290,9 +298,8 @@ func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
|
|
|
stmt := &ast.ReturnStatement{Token: p.curToken}
|
|
|
|
|
|
p.nextToken()
|
|
|
+ stmt.ReturnValue = p.parseExpression(LOWEST)
|
|
|
|
|
|
- // TODO: we're skipping the expressions until we
|
|
|
- // encounter a semicolon
|
|
|
for !p.curTokenIs(token.SEMICOLON) {
|
|
|
p.nextToken()
|
|
|
}
|
|
|
@@ -405,3 +412,26 @@ func (p *Parser) ParseFunctionParameters() []*ast.Identifier {
|
|
|
|
|
|
return identifiers
|
|
|
}
|
|
|
+
|
|
|
+func (p *Parser) parseCallArguments() []ast.Expression {
|
|
|
+ args := []ast.Expression{}
|
|
|
+
|
|
|
+ // the case (), then null args
|
|
|
+ if p.peekTokenIs(token.RPAREN) {
|
|
|
+ p.nextToken()
|
|
|
+ return args
|
|
|
+ }
|
|
|
+ p.nextToken()
|
|
|
+ args = append(args, p.parseExpression(LOWEST))
|
|
|
+
|
|
|
+ for p.peekTokenIs(token.COMMA) {
|
|
|
+ p.nextToken()
|
|
|
+ p.nextToken()
|
|
|
+ args = append(args, p.parseExpression(LOWEST))
|
|
|
+ }
|
|
|
+
|
|
|
+ if !p.expectPeek(token.RPAREN) {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return args
|
|
|
+}
|