diff --git a/parser/cst/nodes.go b/parser/cst/nodes.go index 98b7999..50c6a1b 100644 --- a/parser/cst/nodes.go +++ b/parser/cst/nodes.go @@ -40,6 +40,10 @@ type ( QualifiedIdent QualifiedIdent Args []any } + IndexExpr struct { + BaseExpr any + IndexExpr any + } SliceType struct { Type any } @@ -84,6 +88,14 @@ type ( } ) +func MakeIndexExpr(baseExpr, indexExpr any) (IndexExpr, error) { + result := IndexExpr{ + BaseExpr: baseExpr, + IndexExpr: indexExpr, + } + return result, nil +} + func AppendToParamSlice(slice, item any) ([]Param, error) { s := slice.([]Param) i := item.(Param) diff --git a/parser/expr_test.go b/parser/expr_test.go index 3b9f5b5..bfc0e92 100644 --- a/parser/expr_test.go +++ b/parser/expr_test.go @@ -47,6 +47,40 @@ func Test_BinOp(t *testing.T) { testStmts(t, tcs) } +func Test_IndexExpr(t *testing.T) { + + tcs := []TestForStmt{ + { + Name: "identifier indexed with uint literal", + Input: `a[1];`, + Output: cst.IndexExpr{ + BaseExpr: cst.QualifiedIdent{Ident: "a"}, + IndexExpr: cst.UintLit{Value: 1}, + }, + }, + { + Name: "identifier indexed with identifier", + Input: `a[i];`, + Output: cst.IndexExpr{ + BaseExpr: cst.QualifiedIdent{Ident: "a"}, + IndexExpr: cst.QualifiedIdent{Ident: "i"}, + }, + }, + { + Name: "function call indexed with uint literal", + Input: `f()[1];`, + Output: cst.IndexExpr{ + BaseExpr: cst.Call{ + QualifiedIdent: cst.QualifiedIdent{Ident: "f"}, + }, + IndexExpr: cst.UintLit{Value: 1}, + }, + }, + } + + testStmts(t, tcs) +} + func Test_IntLit(t *testing.T) { tcs := []TestForStmt{ diff --git a/parser/grammar.bnf b/parser/grammar.bnf index e2a5a41..7667090 100644 --- a/parser/grammar.bnf +++ b/parser/grammar.bnf @@ -140,15 +140,19 @@ Expr5 | PrimaryExpr << $0, nil >> ; -PrimaryExpr -: Operand << $0, nil >> // TODO: // https://go.dev/ref/spec#PrimaryExpr // | Conversion -// | PrimaryExpr Index // | PrimaryExpr Slice +PrimaryExpr +: Operand << $0, nil >> +| PrimaryExpr Index << cst.MakeIndexExpr($0, $1) >> | PrimaryExpr Arguments << cst.MakeCall($0, $1) >> ; +Index +: "[" Expr1 "]" << $1, nil >> +; + Arguments : "(" ")" << nil, nil >> | "(" ExpressionList ")" << $1, nil >>