Skip to content

Commit

Permalink
fix src->mir using a custom fork of 'pest'
Browse files Browse the repository at this point in the history
The fork adds a state reference to the Pratt parser and all its
closures, allowing us to pass around 'self' nicely.
  • Loading branch information
Arav K committed May 23, 2023
1 parent 9a7bffc commit 929ad2f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 64 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "pest"]
path = pest
url = https://github.com/bal-e/pest.git
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
1 change: 1 addition & 0 deletions pest
Submodule pest added at c0c8c6
122 changes: 60 additions & 62 deletions src/mir/src.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ pub struct Parser<'a> {
expr: RecExpr<Expr>,
/// The source code being parsed.
code: &'a str,
/// A cached Pratt parser for expressions.
pratt: PrattParser<Rule>,
/// A list of variable bindings in scope.
binds: FxHashMap<Symbol, Id>,
/// Variable bindings from outer scopes.
Expand All @@ -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<Rule>) -> 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 => {
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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<Rule>) -> (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))
}
}

Expand Down

0 comments on commit 929ad2f

Please sign in to comment.