aboutsummaryrefslogtreecommitdiff
path: root/pkg/lang
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang')
-rw-r--r--pkg/lang/ast/op.go9
-rw-r--r--pkg/lang/parser/parser_test.go57
2 files changed, 62 insertions, 4 deletions
diff --git a/pkg/lang/ast/op.go b/pkg/lang/ast/op.go
index f5fce51..6f48e0c 100644
--- a/pkg/lang/ast/op.go
+++ b/pkg/lang/ast/op.go
@@ -59,14 +59,15 @@ func BinOpFromToken(tok token.Token) (BinOp, bool) {
func (op BinOp) Precedence() int {
switch op {
- case BinOpPlus, BinOpMinus:
+ case BinOpAssign:
return 1
- case BinOpStar, BinOpSlash, BinOpPercent:
+ case BinOpEq, BinOpNeq, BinOpLt, BinOpLte, BinOpGt, BinOpGte:
return 2
- case BinOpAssign:
+ case BinOpPlus, BinOpMinus:
return 3
- case BinOpEq, BinOpNeq, BinOpLt, BinOpLte, BinOpGt, BinOpGte:
+ case BinOpStar, BinOpSlash, BinOpPercent:
return 4
+
default:
panic(fmt.Sprintf("unknown binary operator: %d", op))
}
diff --git a/pkg/lang/parser/parser_test.go b/pkg/lang/parser/parser_test.go
index 64dd67a..f48b6a5 100644
--- a/pkg/lang/parser/parser_test.go
+++ b/pkg/lang/parser/parser_test.go
@@ -210,6 +210,63 @@ func TestVarDecl(t *testing.T) {
}, program.Stmts[0])
}
+func TestAssignPrecedence(t *testing.T) {
+ src := `y = 3 + 4 - x`
+
+ p := cheatWithScanner(t, src)
+ program, err := p.Parse()
+ require.NoError(t, err)
+
+ require.Equal(t, 1, len(program.Stmts))
+
+ require.Equal(t, ast.Stmt{
+ Kind: ast.StmtKindExpr,
+ Value: ast.StmtExpr{
+ Value: ast.Expr{
+ At: source.NewLoc(0, 0),
+ Kind: ast.ExprKindBinary,
+ Value: ast.ExprBinary{
+ Left: ast.Expr{
+ At: source.NewLoc(0, 0),
+ Kind: ast.ExprKindIdent,
+ Value: ast.ExprIdent{Value: ast.IdentNode{At: source.NewLoc(0, 0), Value: "y"}},
+ },
+ Op: ast.BinOpAssign,
+ Right: ast.Expr{
+ At: source.NewLoc(0, 4),
+ Kind: ast.ExprKindBinary,
+ Value: ast.ExprBinary{
+ Left: ast.Expr{
+ At: source.NewLoc(0, 4),
+ Kind: ast.ExprKindBinary,
+ Value: ast.ExprBinary{
+ Left: ast.Expr{
+ At: source.NewLoc(0, 4),
+ Kind: ast.ExprKindIntLit,
+ Value: ast.ExprIntLit{Value: 3},
+ },
+ Op: ast.BinOpPlus,
+ Right: ast.Expr{
+ At: source.NewLoc(0, 8),
+ Kind: ast.ExprKindIntLit,
+ Value: ast.ExprIntLit{Value: 4},
+ },
+ },
+ },
+ Op: ast.BinOpMinus,
+ Right: ast.Expr{
+ At: source.NewLoc(0, 12),
+ Kind: ast.ExprKindIdent,
+ Value: ast.ExprIdent{Value: ast.IdentNode{At: source.NewLoc(0, 12), Value: "x"}},
+ },
+ },
+ },
+ },
+ },
+ },
+ }, program.Stmts[0])
+}
+
func TestEmptyStmt(t *testing.T) {
src := `