umx_compiler

UMX virtual machine "Monkey" interpreter / bytecode compiler
git clone git://bsandro.tech/umx_compiler
Log | Files | Refs

commit 8885f23423bb7f442000fab6261d9fb427b930e9
parent 734ab8682a5f8bcff89e9bf5f344852d9e849929
Author: bsandro <email@bsandro.tech>
Date:   Mon, 13 Jun 2022 18:34:51 +0300

parser: integer literal support

Diffstat:
Mast/ast.go | 13+++++++++++++
Mparser/parser.go | 14++++++++++++++
Mparser/parser_test.go | 30++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/ast/ast.go b/ast/ast.go @@ -109,3 +109,16 @@ func (p *Program) String() string { } return out.String() } + +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 +} diff --git a/parser/parser.go b/parser/parser.go @@ -5,6 +5,7 @@ import ( "interp/ast" "interp/lexer" "interp/token" + "strconv" ) const ( @@ -41,6 +42,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 } @@ -129,6 +131,18 @@ func (p *Parser) parseIdentifier() ast.Expression { return &ast.Identifier{Token: p.curToken, 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("error parsing %q as int64", p.curToken.Literal) + p.errors = append(p.errors, msg) + return nil + } + lit.Value = value + return lit +} + func (p *Parser) curTokenIs(t token.TokenType) bool { return p.curToken.Type == t } diff --git a/parser/parser_test.go b/parser/parser_test.go @@ -135,3 +135,33 @@ func TestIdentifierExpression(t *testing.T) { t.Errorf("ident.TokenLiteral() is not 'foo' but %s", ident.TokenLiteral()) } } + +func TestIntegerLiteralExpression(t *testing.T) { + input := "8;" + l := lexer.New(input) + p := New(l) + prg := p.ParseProgram() + checkParserErrors(t, p) + + if len(prg.Statements) != 1 { + t.Fatalf("statements count is not 1 but %d", len(prg.Statements)) + } + + statement, ok := prg.Statements[0].(*ast.ExpressionStatement) + if !ok { + t.Fatalf("prg.Statements[0] is not ExpressionStatement but %T", prg.Statements[0]) + } + + literal, ok := statement.Expression.(*ast.IntegerLiteral) + if !ok { + t.Fatalf("statement.Expression is not IntegerLiteral but %T", statement.Expression) + } + + if literal.Value != 8 { + t.Errorf("literal.Value is not 8 but %d", literal.Value) + } + + if literal.TokenLiteral() != "8" { + t.Errorf("literal.TokenLiteral is not '8' but %s", literal.TokenLiteral()) + } +}