From b5a9660b6ac42bce27c746e76013c3ce5992743a Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 21 Apr 2022 03:19:06 +0200 Subject: Lang parser prototype --- pkg/lang/parser/parser.go | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 pkg/lang/parser/parser.go (limited to 'pkg/lang/parser/parser.go') diff --git a/pkg/lang/parser/parser.go b/pkg/lang/parser/parser.go new file mode 100644 index 0000000..1a9d1d0 --- /dev/null +++ b/pkg/lang/parser/parser.go @@ -0,0 +1,99 @@ +package parser + +import ( + "fmt" + "jinx/pkg/lang/ast" + "jinx/pkg/lang/scanner/token" +) + +type Parser struct { + tokens []token.Token + pos int +} + +func New(tokens []token.Token) *Parser { + return &Parser{tokens: tokens, pos: 0} +} + +func (p *Parser) Parse() (ast.Program, error) { + program := ast.Program{} + + for p.pos < len(p.tokens) { + stmt, err := p.parseStmt() + if err != nil { + return ast.Program{}, err + } + + if err = p.parseStmtEnd(); err != nil { + return ast.Program{}, err + } + + program.Stmts = append(program.Stmts, stmt) + } + + return program, nil +} + +func (p *Parser) parseBlock() (ast.BlockNode, error) { + braceTok, err := p.expect(token.LBrace) + if err != nil { + return ast.BlockNode{}, err + } + + stmts := []ast.Stmt{} + for { + stmt, err := p.parseStmt() + if err != nil { + return ast.BlockNode{}, err + } + + stmts = append(stmts, stmt) + + if err = p.parseStmtEnd(); err != nil { + return ast.BlockNode{}, err + } + + if p.peek().Kind == token.RBrace { + break + } + } + + if _, err := p.expect(token.RBrace); err != nil { + return ast.BlockNode{}, err + } + + return ast.BlockNode{ + At: braceTok.At, + Stmts: stmts, + }, nil +} + +func (p *Parser) parseIdent() (ast.IdentNode, error) { + tok, err := p.expect(token.Ident) + if err != nil { + return ast.IdentNode{}, err + } + + return ast.IdentNode{ + At: tok.At, + Value: tok.Data.(string), + }, nil +} + +func (p *Parser) next() token.Token { + p.pos++ + return p.tokens[p.pos-1] +} + +func (p *Parser) expect(kind token.TokenKind) (token.Token, error) { + tok := p.next() + if tok.Kind != kind { + return token.Token{}, fmt.Errorf("expected %v, got %v", kind, tok.Kind) + } + + return tok, nil +} + +func (p *Parser) peek() token.Token { + return p.tokens[p.pos] +} -- cgit 1.4.1