From ea52b577de11ef1c7cb0f15d7b78cc1e8b2fc9b2 Mon Sep 17 00:00:00 2001 From: susan-garry Date: Mon, 18 Sep 2023 11:03:48 -0400 Subject: [PATCH 1/3] pollen supports the array access postfix operator for arbitrary index expressions --- pollen/src/ast/mod.rs | 4 ++++ pollen/src/main.rs | 21 +++++++++++++++++---- pollen/src/pollen.pest | 9 ++++++--- pollen/tests/paths.pollen | 2 +- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/pollen/src/ast/mod.rs b/pollen/src/ast/mod.rs index 4eca1869..4139cd7d 100644 --- a/pollen/src/ast/mod.rs +++ b/pollen/src/ast/mod.rs @@ -75,6 +75,10 @@ pub enum Expr { op: UOp, expr: Box }, + ArrayAccess { + expr: Box, + idx: Box + }, Record { typ: Typ, fields: Vec diff --git a/pollen/src/main.rs b/pollen/src/main.rs index 60fe51ad..c52b3253 100755 --- a/pollen/src/main.rs +++ b/pollen/src/main.rs @@ -25,6 +25,7 @@ lazy_static! { // Precedence is defined lowest to highest PrattParser::new() + .op(Op::postfix(Rule::array_access)) .op(Op::infix(Rule::or, Left)) .op(Op::infix(Rule::and, Left)) .op(Op::infix(Rule::eq, Left) | Op::infix(Rule::neq, Left)) @@ -625,10 +626,22 @@ fn parse_expr(expression: Pairs) -> Expr { expr: Box::new(exp), } }) - .map_postfix(|lhs, op| { - match op.as_rule() { - rule => unreachable!("{:?} not recognized as a postfix", rule), - } + .map_postfix(|exp, op| { + let idx_expr = match op.as_rule() { + Rule::array_access => { + let mut inner = op.into_inner(); + let Some(expr) = inner.next() else { + unreachable!("array access requires an expression") + }; + parse_expr(expr.into_inner()) + } + rule => unreachable!("{:?} not recognized as a postfix", rule) + }; + + Expr::ArrayAccess { + expr: Box::new(exp), + idx: Box::new(idx_expr) + } }) .map_infix(|lhs, op, rhs| { enum OpType { diff --git a/pollen/src/pollen.pest b/pollen/src/pollen.pest index d36af84d..017ae20f 100644 --- a/pollen/src/pollen.pest +++ b/pollen/src/pollen.pest @@ -115,10 +115,13 @@ obj_initialize = { typ ~ "()" } call_args = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } func_call = { identifier ~ call_args } -term = _{ literal | obj_initialize | func_call | identifier - | "(" ~ expr ~ ")" | "[" ~ expr ~ "]" } +term = _{ (literal | obj_initialize | func_call | identifier + | "(" ~ expr ~ ")" | "[" ~ expr ~ "]") } -expr = { prefix* ~ term ~ (binop ~ prefix* ~ term ) * } +array_access = { "[" ~ expr ~ "]" } +postfix = _{ array_access } + +expr = { prefix* ~ term ~ postfix* ~ (binop ~ prefix* ~ term ~ postfix*) * } /* ----- Statements ---- */ diff --git a/pollen/tests/paths.pollen b/pollen/tests/paths.pollen index f5718f96..50a59ced 100644 --- a/pollen/tests/paths.pollen +++ b/pollen/tests/paths.pollen @@ -9,7 +9,7 @@ def paths() { parset out_paths[(Step*Step)]; for path in Paths { - emit ( path[0] /* path.steps[0], */ + emit ( path.steps[0], path.steps[path.steps.size() - 1]) to out_paths; } From ffc182e20d75690d5248a7e50c7fb2a545948fc5 Mon Sep 17 00:00:00 2001 From: susan-garry Date: Mon, 18 Sep 2023 11:17:06 -0400 Subject: [PATCH 2/3] paths.pollen now has a corresponding paths.expect file --- pollen/tests/parse-out/paths.expect | 101 ++++++++++++++++++++++++++++ pollen/tests/paths.pollen | 2 +- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 pollen/tests/parse-out/paths.expect diff --git a/pollen/tests/parse-out/paths.expect b/pollen/tests/parse-out/paths.expect new file mode 100644 index 00000000..d06374c0 --- /dev/null +++ b/pollen/tests/parse-out/paths.expect @@ -0,0 +1,101 @@ +Prog { + imports: [], + func_defs: [ + FuncDef { + name: Id( + "emit_paths", + ), + args: [], + ret_typ: None, + stmts: [ + ParsetDecl { + id: Id( + "out_paths", + ), + typ: Tuple( + Step, + Step, + ), + graph_id: None, + }, + For { + id: Id( + "path", + ), + iterator: Var( + Id( + "Paths", + ), + ), + body: Block { + stmts: [ + EmitTo { + expr: Tuple { + lhs: ArrayAccess { + expr: FieldAccess { + object: Var( + Id( + "path", + ), + ), + field: Var( + Id( + "steps", + ), + ), + }, + idx: Integer( + 0, + ), + }, + rhs: ArrayAccess { + expr: FieldAccess { + object: Var( + Id( + "path", + ), + ), + field: Var( + Id( + "steps", + ), + ), + }, + idx: BinOpExpr { + lhs: MethodCall { + object: FieldAccess { + object: Var( + Id( + "path", + ), + ), + field: Var( + Id( + "steps", + ), + ), + }, + method: Id( + "size", + ), + args: [], + }, + op: Sub, + rhs: Integer( + 1, + ), + }, + }, + }, + set_id: Id( + "out_paths", + ), + }, + ], + }, + }, + ], + ret: None, + }, + ], +} diff --git a/pollen/tests/paths.pollen b/pollen/tests/paths.pollen index 50a59ced..af104ca8 100644 --- a/pollen/tests/paths.pollen +++ b/pollen/tests/paths.pollen @@ -1,4 +1,4 @@ -def paths() { +def emit_paths() { // Since Pollen doesn't explicitly have path identifiers, // we print the start and end steps of each path // (akin to `odgi paths --idx = graph.og --list-paths --list-paths-start-end`). From de3c665e07873cf1e07b6d62fc8bb5d937c8b3d3 Mon Sep 17 00:00:00 2001 From: susan-garry Date: Mon, 18 Sep 2023 11:23:11 -0400 Subject: [PATCH 3/3] remove unnecessary and unhelpful parenthesis --- pollen/src/pollen.pest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pollen/src/pollen.pest b/pollen/src/pollen.pest index 017ae20f..e8aa1913 100644 --- a/pollen/src/pollen.pest +++ b/pollen/src/pollen.pest @@ -115,8 +115,8 @@ obj_initialize = { typ ~ "()" } call_args = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } func_call = { identifier ~ call_args } -term = _{ (literal | obj_initialize | func_call | identifier - | "(" ~ expr ~ ")" | "[" ~ expr ~ "]") } +term = _{ literal | obj_initialize | func_call | identifier + | "(" ~ expr ~ ")" | "[" ~ expr ~ "]" } array_access = { "[" ~ expr ~ "]" } postfix = _{ array_access }