diff options
| author | Mel <einebeere@gmail.com> | 2022-04-21 03:19:06 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-04-21 03:19:06 +0200 |
| commit | b5a9660b6ac42bce27c746e76013c3ce5992743a (patch) | |
| tree | 0e9bd21a30aae25fe21a7a3994a48ac2cea8c955 /pkg/lang/parser/parser.go | |
| parent | 5267c0e8653b431cfd2c06212cdba4f22225bd02 (diff) | |
| download | jinx-b5a9660b6ac42bce27c746e76013c3ce5992743a.tar.zst jinx-b5a9660b6ac42bce27c746e76013c3ce5992743a.zip | |
Lang parser prototype
Diffstat (limited to 'pkg/lang/parser/parser.go')
| -rw-r--r-- | pkg/lang/parser/parser.go | 99 |
1 files changed, 99 insertions, 0 deletions
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] +} |
