diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/lang/ast/op.go | 9 | ||||
| -rw-r--r-- | pkg/lang/parser/parser_test.go | 57 |
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 := ` |
