diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..bd66fef --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "pest"] + path = pest + url = https://github.com/bal-e/pest.git diff --git a/Cargo.toml b/Cargo.toml index 73397be..3b0e7d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] egg = "0.9" num-bigint = "0.4" -pest = "2" -pest_derive = "2" +pest = { path = "pest/pest" } +pest_derive = { path = "pest/derive" } rustc-hash = "1.1" symbol_table = "0.3" diff --git a/pest b/pest new file mode 160000 index 0000000..c0c8c69 --- /dev/null +++ b/pest @@ -0,0 +1 @@ +Subproject commit c0c8c69e862f6af1a325988aeeeda199a910d374 diff --git a/src/mir/src.rs b/src/mir/src.rs index 2bc7daf..89a8303 100644 --- a/src/mir/src.rs +++ b/src/mir/src.rs @@ -18,8 +18,6 @@ pub struct Parser<'a> { expr: RecExpr, /// The source code being parsed. code: &'a str, - /// A cached Pratt parser for expressions. - pratt: PrattParser, /// A list of variable bindings in scope. binds: FxHashMap, /// Variable bindings from outer scopes. @@ -30,22 +28,22 @@ pub struct Parser<'a> { impl<'a> Parser<'a> { /// Parse an MIR expression. - fn parse_expr(&mut self, pair: Pair<'a, Rule>) -> Id { - self.pratt - .map_primary(|p| match p.as_rule() { + fn parse_expr(&mut self, pair: Pair<'a, Rule>, pratt: &PrattParser) -> Id { + pratt + .map_primary(|p, this: &mut Self| match p.as_rule() { Rule::expr_int => { let num = p.as_str().parse().unwrap(); - self.expr.add(Expr::Int(num)) + this.expr.add(Expr::Int(num)) }, Rule::expr_var => { - let sym = self.symbols.intern(p.as_str()); - *self.binds.get(&sym).expect("Variable not found!") + let sym = this.symbols.intern(p.as_str()); + *this.binds.get(&sym).expect("Variable not found!") }, Rule::expr_arr => { p.into_inner() - .fold(self.expr.add(Expr::NilArr), |prev, expr| { - let expr = self.parse_expr(expr); - self.expr.add(Expr::Cat([prev, expr])) + .fold(this.expr.add(Expr::NilArr), |prev, expr| { + let expr = this.parse_expr(expr, pratt); + this.expr.add(Expr::Cat([prev, expr])) }) }, Rule::expr_let => { @@ -54,8 +52,8 @@ impl<'a> Parser<'a> { let mut expr = None; for item in p.into_inner() { if item.as_rule() == Rule::bind { - let (sym, expr) = self.parse_bind(item); - self.old_binds.push(OldBind::Swap(sym, expr)); + let (sym, expr) = this.parse_bind(item, pratt); + this.old_binds.push(OldBind::Swap(sym, expr)); to_add += 1; } else { // Parse later, once bindings are applied @@ -64,12 +62,12 @@ impl<'a> Parser<'a> { } // Move the binds into the hashmap atomically (wrt parsing) - let off = self.old_binds.len() - to_add; - for old_bind in self.old_binds[off ..].iter_mut() { + let off = this.old_binds.len() - to_add; + for old_bind in this.old_binds[off ..].iter_mut() { let OldBind::Swap(sym, expr) = *old_bind else { unreachable!() }; *old_bind = OldBind::Sole(sym); - self.binds.entry(sym) + this.binds.entry(sym) .and_modify(|old_expr| { let expr = std::mem::replace(old_expr, expr); *old_bind = OldBind::Swap(sym, expr); @@ -78,79 +76,79 @@ impl<'a> Parser<'a> { } // Parse the subexpression with the updated context - let res = self.parse_expr(expr.unwrap()); + let res = this.parse_expr(expr.unwrap(), pratt); // Restore the previous binds - let len = self.old_binds.len(); - for bind in self.old_binds.drain(off .. len) { + let len = this.old_binds.len(); + for bind in this.old_binds.drain(off .. len) { match bind { OldBind::Swap(sym, expr) => - self.binds.insert(sym, expr), + this.binds.insert(sym, expr), OldBind::Sole(sym) => - self.binds.remove(&sym), + this.binds.remove(&sym), }; } res }, - Rule::expr => self.parse_expr(p), + Rule::expr => this.parse_expr(p, pratt), _ => unreachable!(), }) - .map_prefix(|op, sub| match op.as_rule() { - Rule::op_neg => self.expr.add(Expr::Neg([sub])), - Rule::op_not => self.expr.add(Expr::Not([sub])), - Rule::op_opt => self.expr.add(Expr::Opt([sub])), + .map_prefix(|op, sub, this: &mut Self| match op.as_rule() { + Rule::op_neg => this.expr.add(Expr::Neg([sub])), + Rule::op_not => this.expr.add(Expr::Not([sub])), + Rule::op_opt => this.expr.add(Expr::Opt([sub])), _ => unreachable!(), }) - .map_postfix(|sub, op| match op.as_rule() { - Rule::op_arr_map => self.expr.add(Expr::MapArr([sub])), - Rule::op_opt_map => self.expr.add(Expr::MapOpt([sub])), + .map_postfix(|sub, op, this: &mut Self| match op.as_rule() { + Rule::op_arr_map => this.expr.add(Expr::MapArr([sub])), + Rule::op_opt_map => this.expr.add(Expr::MapOpt([sub])), _ => unreachable!(), }) - .map_infix(|lhs, op, rhs| match op.as_rule() { - Rule::op_add => self.expr.add(Expr::Add([lhs, rhs])), - Rule::op_sub => self.expr.add(Expr::Sub([lhs, rhs])), - Rule::op_mul => self.expr.add(Expr::Mul([lhs, rhs])), - Rule::op_div => self.expr.add(Expr::Div([lhs, rhs])), - Rule::op_rem => self.expr.add(Expr::Rem([lhs, rhs])), - - Rule::op_and => self.expr.add(Expr::And([lhs, rhs])), - Rule::op_ior => self.expr.add(Expr::IOr([lhs, rhs])), - Rule::op_xor => self.expr.add(Expr::XOr([lhs, rhs])), - Rule::op_shl => self.expr.add(Expr::ShL([lhs, rhs])), - Rule::op_shr => self.expr.add(Expr::ShR([lhs, rhs])), - - Rule::op_iseq => self.expr.add(Expr::IsEq([lhs, rhs])), - Rule::op_isne => self.expr.add(Expr::IsNE([lhs, rhs])), - Rule::op_islt => self.expr.add(Expr::IsLT([lhs, rhs])), - Rule::op_isle => self.expr.add(Expr::IsLE([lhs, rhs])), - Rule::op_isgt => self.expr.add(Expr::IsGT([lhs, rhs])), - Rule::op_isge => self.expr.add(Expr::IsGE([lhs, rhs])), - - Rule::op_toeq => self.expr.add(Expr::ToEq([lhs, rhs])), - Rule::op_tolt => self.expr.add(Expr::ToLT([lhs, rhs])), - - Rule::op_then => self.expr.add(Expr::Then([lhs, rhs])), - Rule::op_else => self.expr.add(Expr::Else([lhs, rhs])), - Rule::op_cat => self.expr.add(Expr::Cat([lhs, rhs])), - Rule::op_exp => self.expr.add(Expr::Exp([lhs, rhs])), - Rule::op_red => self.expr.add(Expr::Red([lhs, rhs])), - Rule::op_mvl => self.expr.add(Expr::MvL([lhs, rhs])), - Rule::op_mvr => self.expr.add(Expr::MvR([lhs, rhs])), + .map_infix(|lhs, op, rhs, this: &mut Self| match op.as_rule() { + Rule::op_add => this.expr.add(Expr::Add([lhs, rhs])), + Rule::op_sub => this.expr.add(Expr::Sub([lhs, rhs])), + Rule::op_mul => this.expr.add(Expr::Mul([lhs, rhs])), + Rule::op_div => this.expr.add(Expr::Div([lhs, rhs])), + Rule::op_rem => this.expr.add(Expr::Rem([lhs, rhs])), + + Rule::op_and => this.expr.add(Expr::And([lhs, rhs])), + Rule::op_ior => this.expr.add(Expr::IOr([lhs, rhs])), + Rule::op_xor => this.expr.add(Expr::XOr([lhs, rhs])), + Rule::op_shl => this.expr.add(Expr::ShL([lhs, rhs])), + Rule::op_shr => this.expr.add(Expr::ShR([lhs, rhs])), + + Rule::op_iseq => this.expr.add(Expr::IsEq([lhs, rhs])), + Rule::op_isne => this.expr.add(Expr::IsNE([lhs, rhs])), + Rule::op_islt => this.expr.add(Expr::IsLT([lhs, rhs])), + Rule::op_isle => this.expr.add(Expr::IsLE([lhs, rhs])), + Rule::op_isgt => this.expr.add(Expr::IsGT([lhs, rhs])), + Rule::op_isge => this.expr.add(Expr::IsGE([lhs, rhs])), + + Rule::op_toeq => this.expr.add(Expr::ToEq([lhs, rhs])), + Rule::op_tolt => this.expr.add(Expr::ToLT([lhs, rhs])), + + Rule::op_then => this.expr.add(Expr::Then([lhs, rhs])), + Rule::op_else => this.expr.add(Expr::Else([lhs, rhs])), + Rule::op_cat => this.expr.add(Expr::Cat([lhs, rhs])), + Rule::op_exp => this.expr.add(Expr::Exp([lhs, rhs])), + Rule::op_red => this.expr.add(Expr::Red([lhs, rhs])), + Rule::op_mvl => this.expr.add(Expr::MvL([lhs, rhs])), + Rule::op_mvr => this.expr.add(Expr::MvR([lhs, rhs])), _ => unreachable!(), }) - .parse(pair.into_inner()) + .parse(pair.into_inner(), self) } /// Parse a bind expression. - fn parse_bind(&mut self, pair: Pair<'a, Rule>) -> (Symbol, Id) { + fn parse_bind(&mut self, pair: Pair<'a, Rule>, pratt: &PrattParser) -> (Symbol, Id) { let mut pairs = pair.into_inner(); let name = pairs.next().unwrap(); let expr = pairs.next().unwrap(); assert!(pairs.next().is_none()); - (self.symbols.intern(name.as_str()), self.parse_expr(expr)) + (self.symbols.intern(name.as_str()), self.parse_expr(expr, pratt)) } }