about summary refs log tree commit diff
path: root/pkg/lang/parser
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/parser')
-rw-r--r--pkg/lang/parser/errors.go60
-rw-r--r--pkg/lang/parser/exprs.go8
-rw-r--r--pkg/lang/parser/parser.go7
-rw-r--r--pkg/lang/parser/stmts.go8
4 files changed, 74 insertions, 9 deletions
diff --git a/pkg/lang/parser/errors.go b/pkg/lang/parser/errors.go
new file mode 100644
index 0000000..a020e01
--- /dev/null
+++ b/pkg/lang/parser/errors.go
@@ -0,0 +1,60 @@
+package parser
+
+import (
+	"fmt"
+	"jinx/pkg/lang/scanner/token"
+	"jinx/pkg/libs/source"
+)
+
+type ErrFunctionNoThisAllowed struct {
+	At source.Loc
+}
+
+func (e ErrFunctionNoThisAllowed) Error() string {
+	return fmt.Sprintf("non-method function cannot have 'this' as parameter at %v", e.At)
+}
+
+type ErrFunctionLiteralNoThisAllowed struct {
+	At source.Loc
+}
+
+func (e ErrFunctionLiteralNoThisAllowed) Error() string {
+	return fmt.Sprintf("function literal cannot have 'this' as parameter at %v", e.At)
+}
+
+type ErrExpectedToken struct {
+	At     source.Loc
+	Wanted token.TokenKind
+	Got    token.Token
+}
+
+func (e ErrExpectedToken) Error() string {
+	return fmt.Sprintf("unexpected token %v, wanted %v at %v", e.Got, e.Wanted, e.At)
+}
+
+type ErrExpectedStatementEnd struct {
+	At  source.Loc
+	Got token.Token
+}
+
+func (e ErrExpectedStatementEnd) Error() string {
+	return fmt.Sprintf("expected statement end, got %v at %v", e.Got, e.At)
+}
+
+type ErrExpectedUnitExpressionStart struct {
+	At  source.Loc
+	Got token.Token
+}
+
+func (e ErrExpectedUnitExpressionStart) Error() string {
+	return fmt.Sprintf("unexpected token %v, wanted unit expression start at %v", e.Got, e.At)
+}
+
+type ErrExpectedValueLiteral struct {
+	At  source.Loc
+	Got token.Token
+}
+
+func (e ErrExpectedValueLiteral) Error() string {
+	return fmt.Sprintf("unexpected token %v, wanted value literal %v", e.Got, e.At)
+}
diff --git a/pkg/lang/parser/exprs.go b/pkg/lang/parser/exprs.go
index 48d1a8c..1603838 100644
--- a/pkg/lang/parser/exprs.go
+++ b/pkg/lang/parser/exprs.go
@@ -1,7 +1,6 @@
 package parser
 
 import (
-	"fmt"
 	"jinx/pkg/lang/ast"
 	"jinx/pkg/lang/scanner/token"
 )
@@ -207,7 +206,8 @@ func (p *Parser) parseUnitExpr() (ast.Expr, error) {
 	case token.KwTrue, token.KwFalse, token.KwNull, token.KwThis:
 		return p.parseValueLitExpr()
 	default:
-		panic(fmt.Errorf("unexpected token '%v', wanted unit expression start", p.peek().Kind))
+		tok := p.peek()
+		return ast.Expr{}, ErrExpectedUnitExpressionStart{tok.At, tok}
 	}
 }
 
@@ -250,7 +250,7 @@ func (p *Parser) parseFnLitExpr() (ast.Expr, error) {
 	}
 
 	if hasThis {
-		return ast.Expr{}, fmt.Errorf("function literal cannot have 'this' parameter")
+		return ast.Expr{}, ErrFunctionLiteralNoThisAllowed{fnTok.At}
 	}
 
 	// TODO: Also parse just an expression
@@ -406,6 +406,6 @@ func (p *Parser) parseValueLitExpr() (ast.Expr, error) {
 			Value: ast.ExprThis{},
 		}, nil
 	default:
-		panic(fmt.Errorf("unexpected token '%v', wanted value literal", tok))
+		return ast.Expr{}, ErrExpectedValueLiteral{At: tok.At, Got: tok}
 	}
 }
diff --git a/pkg/lang/parser/parser.go b/pkg/lang/parser/parser.go
index 0ff4b09..d939e4b 100644
--- a/pkg/lang/parser/parser.go
+++ b/pkg/lang/parser/parser.go
@@ -1,7 +1,6 @@
 package parser
 
 import (
-	"fmt"
 	"jinx/pkg/lang/ast"
 	"jinx/pkg/lang/scanner/token"
 )
@@ -88,7 +87,11 @@ func (p *Parser) next() token.Token {
 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 token.Token{}, ErrExpectedToken{
+			At:     tok.At,
+			Wanted: kind,
+			Got:    tok,
+		}
 	}
 
 	return tok, nil
diff --git a/pkg/lang/parser/stmts.go b/pkg/lang/parser/stmts.go
index c20f7a0..fe5c65b 100644
--- a/pkg/lang/parser/stmts.go
+++ b/pkg/lang/parser/stmts.go
@@ -1,7 +1,6 @@
 package parser
 
 import (
-	"fmt"
 	"jinx/pkg/lang/ast"
 	"jinx/pkg/lang/scanner/token"
 )
@@ -154,7 +153,7 @@ func (p *Parser) parseFnDeclStmt() (ast.Stmt, error) {
 	}
 
 	if hasThis {
-		return ast.Stmt{}, fmt.Errorf("function cannot have 'this' as a parameter")
+		return ast.Stmt{}, ErrFunctionNoThisAllowed{At: fnTok.At}
 	}
 
 	block, err := p.parseBlock()
@@ -640,7 +639,10 @@ func (p *Parser) parseEmptyStmt() (ast.Stmt, error) {
 func (p *Parser) parseStmtEnd() error {
 	tok := p.peek()
 	if !tok.CanEndStmt() {
-		return fmt.Errorf("wanted statement end, received: '%v'", tok.Kind)
+		return ErrExpectedStatementEnd{
+			At:  tok.At,
+			Got: tok,
+		}
 	}
 	p.next()
 	return nil