From 2749153724d187beed706e4d9cd3a70773eb6908 Mon Sep 17 00:00:00 2001 From: Agustin Godnic Date: Sun, 31 May 2026 20:43:54 -0300 Subject: [PATCH 1/5] Grammar: change binary op rules --- parser/cst/nodes.go | 8 ++++++ parser/grammar.bnf | 48 ++++++++++++++++------------------- parser/precedence_test.go | 53 ++++++++------------------------------- 3 files changed, 40 insertions(+), 69 deletions(-) diff --git a/parser/cst/nodes.go b/parser/cst/nodes.go index 50c6a1b..5ac5c7d 100644 --- a/parser/cst/nodes.go +++ b/parser/cst/nodes.go @@ -86,8 +86,16 @@ type ( Ident string Type any } + ParenthesizedExpr struct { + Expr any + } ) +func MakeParenthesizedExpr(expr any) (ParenthesizedExpr, error) { + result := ParenthesizedExpr{expr} + return result, nil +} + func MakeIndexExpr(baseExpr, indexExpr any) (IndexExpr, error) { result := IndexExpr{ BaseExpr: baseExpr, diff --git a/parser/grammar.bnf b/parser/grammar.bnf index 7667090..52ef784 100644 --- a/parser/grammar.bnf +++ b/parser/grammar.bnf @@ -115,28 +115,15 @@ IfStmt | if Expr1 Block else IfStmt << cst.MakeIf($1, $2, $4) >> ; +// Binary operator precedence is not represented in the grammar. +// It is enforced by compiler passes later on. Expr1 -: Expr1 LogOp Expr2 << cst.MakeBinOp($0, $1, $2) >> -| Expr2 << $0, nil >> -; - -Expr2 -: Expr2 CmpOp Expr3 << cst.MakeBinOp($0, $1, $2) >> -| Expr3 << $0, nil >> -; - -Expr3 -: Expr3 AddOp Expr4 << cst.MakeBinOp($0, $1, $2) >> -| Expr4 << $0, nil >> -; - -Expr4 -: Expr4 MulOp Expr5 << cst.MakeBinOp($0, $1, $2) >> -| Expr5 << $0, nil >> +: Expr1 BinaryOperator Expr5 << cst.MakeBinOp($0, $1, $2) >> +| Expr5 << $0, nil >> ; Expr5 -: UnaryOp Expr5 << cst.MakeUnaryOp($0, $1) >> +: UnaryOperator Expr5 << cst.MakeUnaryOp($0, $1) >> | PrimaryExpr << $0, nil >> ; @@ -164,9 +151,13 @@ ExpressionList ; Operand -: Lit << $0, nil >> -| OperandName << $0, nil >> -| "(" Expr1 ")" << $1, nil >> +: Lit << $0, nil >> +| OperandName << $0, nil >> +| ParenthesizedExpr << $0, nil >> +; + +ParenthesizedExpr +: "(" Expr1 ")" << cst.MakeParenthesizedExpr($1) >> ; OperandName @@ -181,8 +172,13 @@ Lit | uintLiteral << cst.MakeUintLit($0) >> ; -LogOp: "||" | "&&"; -CmpOp: "==" | "!=" | ">" | "<" | ">=" | "<="; -AddOp: "+" | "-" | "|" | "^"; -MulOp: "*" | "/" | "%" | "<<" | ">>" | "&"; -UnaryOp: "-" | "!"; \ No newline at end of file +BinaryOperator: +"||" | "&&" | +"==" | "!=" | +">" | "<" | ">=" | "<=" | +"+" | "-" | +"|" | "&" | "^" | +"*" | "/" | "%" +; + +UnaryOperator: "-" | "!" | "~"; \ No newline at end of file diff --git a/parser/precedence_test.go b/parser/precedence_test.go index e3d0a92..7ba32ee 100644 --- a/parser/precedence_test.go +++ b/parser/precedence_test.go @@ -6,58 +6,25 @@ import ( "github.com/agodnic/avmc/parser/cst" ) -func Test_OperatorPrecedence(t *testing.T) { +func Test_ParenthesizedExpr(t *testing.T) { tcs := []TestForStmt{ { - Name: "+ has lower precedence than *", - Input: `1 + 2 * 3;`, - Output: cst.BinOp{ - R: cst.UintLit{Value: 1}, - Op: "+", - L: cst.BinOp{ - R: cst.UintLit{Value: 2}, - Op: "*", - L: cst.UintLit{Value: 3}, - }, + Name: "parenthesized uint literal", + Input: `(1);`, + Output: cst.ParenthesizedExpr{ + Expr: cst.UintLit{Value: 1}, }, }, { - Name: "* has higher precedence than +", - Input: `1 * 2 + 3;`, - Output: cst.BinOp{ - R: cst.BinOp{ - R: cst.UintLit{Value: 1}, - Op: "*", - L: cst.UintLit{Value: 2}, - }, - Op: "+", - L: cst.UintLit{Value: 3}, - }, - }, - { - Name: "parenthesized expressions have higher precedence than *", - Input: `1 * (2 + 3);`, + Name: "parenthesized operand in binary operation", + Input: `1 + (2);`, Output: cst.BinOp{ R: cst.UintLit{Value: 1}, - Op: "*", - L: cst.BinOp{ - R: cst.UintLit{Value: 2}, - Op: "+", - L: cst.UintLit{Value: 3}, - }, - }, - }, - { - Name: "unary - has higher precedence than +", - Input: `-1 + 2;`, - Output: cst.BinOp{ - R: cst.UnaryOp{ - Op: "-", - Expr: cst.UintLit{Value: 1}, - }, Op: "+", - L: cst.UintLit{Value: 2}, + L: cst.ParenthesizedExpr{ + Expr: cst.UintLit{Value: 2}, + }, }, }, } From 45dda10727e6c802c3f5cc6dab6b4c06a7fb87f5 Mon Sep 17 00:00:00 2001 From: Agustin Godnic Date: Sun, 31 May 2026 20:45:51 -0300 Subject: [PATCH 2/5] Rename grammar rule --- parser/grammar.bnf | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/parser/grammar.bnf b/parser/grammar.bnf index 52ef784..bb27b0e 100644 --- a/parser/grammar.bnf +++ b/parser/grammar.bnf @@ -50,11 +50,11 @@ Stmt ; ExprStmt -: Expr1 << $0, nil >> +: Expr << $0, nil >> ; VarDecl -: var identifier Type "=" Expr1 << cst.MakeVarDecl($1, $2, $4) >> +: var identifier Type "=" Expr << cst.MakeVarDecl($1, $2, $4) >> ; Type @@ -88,16 +88,16 @@ Param ; ConstDecl -: const identifier Type "=" Expr1 << cst.MakeConstDecl($1, $2, $4) >> +: const identifier Type "=" Expr << cst.MakeConstDecl($1, $2, $4) >> ; Assignment -: identifier "=" Expr1 << cst.MakeAssignment($0, $2) >> +: identifier "=" Expr << cst.MakeAssignment($0, $2) >> ; Return : return << cst.MakeReturn(nil) >> -| return Expr1 << cst.MakeReturn($1) >> +| return Expr << cst.MakeReturn($1) >> ; Block @@ -110,15 +110,15 @@ StmtList ; IfStmt -: if Expr1 Block << cst.MakeIf($1, $2, nil) >> -| if Expr1 Block else Block << cst.MakeIf($1, $2, $4) >> -| if Expr1 Block else IfStmt << cst.MakeIf($1, $2, $4) >> +: if Expr Block << cst.MakeIf($1, $2, nil) >> +| if Expr Block else Block << cst.MakeIf($1, $2, $4) >> +| if Expr Block else IfStmt << cst.MakeIf($1, $2, $4) >> ; // Binary operator precedence is not represented in the grammar. // It is enforced by compiler passes later on. -Expr1 -: Expr1 BinaryOperator Expr5 << cst.MakeBinOp($0, $1, $2) >> +Expr +: Expr BinaryOperator Expr5 << cst.MakeBinOp($0, $1, $2) >> | Expr5 << $0, nil >> ; @@ -137,7 +137,7 @@ PrimaryExpr ; Index -: "[" Expr1 "]" << $1, nil >> +: "[" Expr "]" << $1, nil >> ; Arguments @@ -146,8 +146,8 @@ Arguments ; ExpressionList -: Expr1 << []any{$0}, nil >> -| ExpressionList "," Expr1 << append($0.([]any), $2), nil >> +: Expr << []any{$0}, nil >> +| ExpressionList "," Expr << append($0.([]any), $2), nil >> ; Operand @@ -157,7 +157,7 @@ Operand ; ParenthesizedExpr -: "(" Expr1 ")" << cst.MakeParenthesizedExpr($1) >> +: "(" Expr ")" << cst.MakeParenthesizedExpr($1) >> ; OperandName From b8030c6ad28fefa680cbd3d67eef2abbe4b689c9 Mon Sep 17 00:00:00 2001 From: Agustin Godnic Date: Sun, 31 May 2026 20:52:57 -0300 Subject: [PATCH 3/5] Rename parser rule --- parser/grammar.bnf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/grammar.bnf b/parser/grammar.bnf index bb27b0e..c25a523 100644 --- a/parser/grammar.bnf +++ b/parser/grammar.bnf @@ -118,12 +118,12 @@ IfStmt // Binary operator precedence is not represented in the grammar. // It is enforced by compiler passes later on. Expr -: Expr BinaryOperator Expr5 << cst.MakeBinOp($0, $1, $2) >> -| Expr5 << $0, nil >> +: Expr BinaryOperator Term << cst.MakeBinOp($0, $1, $2) >> +| Term << $0, nil >> ; -Expr5 -: UnaryOperator Expr5 << cst.MakeUnaryOp($0, $1) >> +Term +: UnaryOperator Term << cst.MakeUnaryOp($0, $1) >> | PrimaryExpr << $0, nil >> ; From a938ab2fd853a9a871d9a228d369481b19d72b9f Mon Sep 17 00:00:00 2001 From: Agustin Godnic Date: Sun, 31 May 2026 20:56:26 -0300 Subject: [PATCH 4/5] Update comment --- parser/grammar.bnf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/parser/grammar.bnf b/parser/grammar.bnf index c25a523..45f3ec0 100644 --- a/parser/grammar.bnf +++ b/parser/grammar.bnf @@ -127,9 +127,8 @@ Term | PrimaryExpr << $0, nil >> ; -// TODO: // https://go.dev/ref/spec#PrimaryExpr +// TODO: https://go.dev/ref/spec#PrimaryExpr // | Conversion -// | PrimaryExpr Slice PrimaryExpr : Operand << $0, nil >> | PrimaryExpr Index << cst.MakeIndexExpr($0, $1) >> From bd1909bff235a123f189be5899e423c1b61ce75f Mon Sep 17 00:00:00 2001 From: Agustin Godnic Date: Sun, 31 May 2026 21:01:57 -0300 Subject: [PATCH 5/5] Refactor --- parser/expr_test.go | 25 +++++++++++++++++++++++++ parser/precedence_test.go | 33 --------------------------------- 2 files changed, 25 insertions(+), 33 deletions(-) delete mode 100644 parser/precedence_test.go diff --git a/parser/expr_test.go b/parser/expr_test.go index bfc0e92..5a8e700 100644 --- a/parser/expr_test.go +++ b/parser/expr_test.go @@ -46,6 +46,31 @@ func Test_BinOp(t *testing.T) { testStmts(t, tcs) } +func Test_ParenthesizedExpr(t *testing.T) { + + tcs := []TestForStmt{ + { + Name: "parenthesized uint literal", + Input: `(1);`, + Output: cst.ParenthesizedExpr{ + Expr: cst.UintLit{Value: 1}, + }, + }, + { + Name: "parenthesized operand in binary operation", + Input: `1 + (2);`, + Output: cst.BinOp{ + R: cst.UintLit{Value: 1}, + Op: "+", + L: cst.ParenthesizedExpr{ + Expr: cst.UintLit{Value: 2}, + }, + }, + }, + } + + testStmts(t, tcs) +} func Test_IndexExpr(t *testing.T) { diff --git a/parser/precedence_test.go b/parser/precedence_test.go deleted file mode 100644 index 7ba32ee..0000000 --- a/parser/precedence_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package parser - -import ( - "testing" - - "github.com/agodnic/avmc/parser/cst" -) - -func Test_ParenthesizedExpr(t *testing.T) { - - tcs := []TestForStmt{ - { - Name: "parenthesized uint literal", - Input: `(1);`, - Output: cst.ParenthesizedExpr{ - Expr: cst.UintLit{Value: 1}, - }, - }, - { - Name: "parenthesized operand in binary operation", - Input: `1 + (2);`, - Output: cst.BinOp{ - R: cst.UintLit{Value: 1}, - Op: "+", - L: cst.ParenthesizedExpr{ - Expr: cst.UintLit{Value: 2}, - }, - }, - }, - } - - testStmts(t, tcs) -}