Bläddra i källkod

parsing expression -- integer literal expression

runningwater 3 år sedan
förälder
incheckning
7080ab8662
4 ändrade filer med 57 tillägg och 1 borttagningar
  1. 11 1
      ast/ast.go
  2. 1 0
      ast/ast_test.go
  3. 15 0
      parser/parser.go
  4. 30 0
      parser/parser_test.go

+ 11 - 1
ast/ast.go

@@ -148,5 +148,15 @@ func (es *ExpressionStatement) String() string {
 	}
 	return ""
 }
-func (es *ExpressionStatement) statementNode() {
+func (es *ExpressionStatement) statementNode() {}
+
+type IntegerLiteral struct {
+	Token token.Token
+	Value int64
 }
+
+func (i *IntegerLiteral) TokenLiteral() string { return i.Token.Literal }
+
+func (i *IntegerLiteral) String() string { return i.Token.Literal }
+
+func (i *IntegerLiteral) expressionNode() {}

+ 1 - 0
ast/ast_test.go

@@ -22,4 +22,5 @@ func TestString(t *testing.T) {
 	if program.String() != "let myVar = anotherVar;" {
 		t.Errorf("program.String() wrong. got=%q", program.String())
 	}
+	t.Logf("program.String, got = %q", program.String())
 }

+ 15 - 0
parser/parser.go

@@ -5,6 +5,7 @@ import (
 	"github/runnignwater/monkey/ast"
 	"github/runnignwater/monkey/lexer"
 	"github/runnignwater/monkey/token"
+	"strconv"
 )
 
 /**
@@ -50,6 +51,7 @@ func New(l *lexer.Lexer) *Parser {
 
 	p.prefixParseFns = make(map[token.TypeToken]prefixParseFn)
 	p.registerPrefix(token.IDENT, p.parseIdentifier)
+	p.registerPrefix(token.INT, p.parseIntegerLiteral)
 
 	// Read two tokens, so curToken and peekToken are both set
 	p.nextToken()
@@ -165,6 +167,19 @@ func (p *Parser) parseExpression(precedence int) ast.Expression {
 
 	return leftExp
 }
+func (p *Parser) parseIntegerLiteral() ast.Expression {
+	lit := &ast.IntegerLiteral{Token: p.curToken}
+
+	value, err := strconv.ParseInt(p.curToken.Literal, 0, 64)
+	if err != nil {
+		msg := fmt.Sprintf("could not parse %q as integer", p.curToken.Literal)
+		p.errors = append(p.errors, msg)
+		return nil
+	}
+	lit.Value = value
+
+	return lit
+}
 
 func (p *Parser) curTokenIs(t token.TypeToken) bool {
 	return p.curToken.Type == t

+ 30 - 0
parser/parser_test.go

@@ -142,3 +142,33 @@ func TestIdentifier(t *testing.T) {
 		t.Errorf("ident.TokenLiteral() not %s. got=%s", "foobar", ident.TokenLiteral())
 	}
 }
+
+func TestIntegerLiteralExpression(t *testing.T) {
+	input := "5;"
+
+	l := lexer.New(input)
+	p := New(l)
+	program := p.ParseProgram()
+	checkParseErrors(t, p)
+
+	if len(program.Statements) != 1 {
+		t.Fatalf("program has not enough statements. got=%d",
+			len(program.Statements))
+	}
+	stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
+	if !ok {
+		t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
+			program.Statements[0])
+	}
+	literal, ok := stmt.Expression.(*ast.IntegerLiteral)
+	if !ok {
+		t.Fatalf("exp not *ast.IntegerLiteral. got=%T", stmt.Expression)
+	}
+	if literal.Value != 5 {
+		t.Errorf("literal.Value not %d. got=%d", 5, literal.Value)
+	}
+	if literal.TokenLiteral() != "5" {
+		t.Errorf("literal.TokenLiteral not %s. got=%s", "5",
+			literal.TokenLiteral())
+	}
+}