package parser import ( "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{}, ErrExpectedToken{ At: tok.At, Wanted: kind, Got: tok, } } return tok, nil } func (p *Parser) peek() token.Token { return p.tokens[p.pos] }