Skip to content

Commit

Permalink
2.6: Add parser of integer literal
Browse files Browse the repository at this point in the history
  • Loading branch information
nibral committed Jan 12, 2019
1 parent 763c848 commit d6f0f9c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
9 changes: 9 additions & 0 deletions ast/ast.go
Expand Up @@ -101,3 +101,12 @@ func (es *ExpressionStatement) String() string {
}
return ""
}

type IntegerLiteral struct {
Token token.Token
Value int64
}

func (il *IntegerLiteral) expressionNode() {}
func (il *IntegerLiteral) TokenLiteral() string { return il.Token.Literal }
func (il *IntegerLiteral) String() string { return il.Token.Literal }
17 changes: 17 additions & 0 deletions parser/parser.go
Expand Up @@ -5,6 +5,7 @@ import (
"monkey_interpreter/ast"
"monkey_interpreter/lexer"
"monkey_interpreter/token"
"strconv"
)

const (
Expand Down Expand Up @@ -47,6 +48,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)

return p
}
Expand Down Expand Up @@ -180,3 +182,18 @@ func (p *Parser) parseIdentifier() ast.Expression {
Value: p.curToken.Literal,
}
}

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
}
31 changes: 31 additions & 0 deletions parser/parser_test.go
Expand Up @@ -131,3 +131,34 @@ func TestIdentifierExpression(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()
checkParserErrors(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())
}
}

0 comments on commit d6f0f9c

Please sign in to comment.