about summary refs log tree commit diff
path: root/pkg/lang/parser/parser.go
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-04-21 03:19:06 +0200
committerMel <einebeere@gmail.com>2022-04-21 03:19:06 +0200
commitb5a9660b6ac42bce27c746e76013c3ce5992743a (patch)
tree0e9bd21a30aae25fe21a7a3994a48ac2cea8c955 /pkg/lang/parser/parser.go
parent5267c0e8653b431cfd2c06212cdba4f22225bd02 (diff)
downloadjinx-b5a9660b6ac42bce27c746e76013c3ce5992743a.tar.zst
jinx-b5a9660b6ac42bce27c746e76013c3ce5992743a.zip
Lang parser prototype
Diffstat (limited to 'pkg/lang/parser/parser.go')
-rw-r--r--pkg/lang/parser/parser.go99
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]
+}