Skip to content

Commit 643b2e1

Browse files
parse expressions, while blocks, conditionals
1 parent b2ba8db commit 643b2e1

File tree

5 files changed

+237
-71
lines changed

5 files changed

+237
-71
lines changed

src/ir.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ impl Transaction {
5151
}
5252

5353
/// add a new statement to the transaction
54-
pub fn s(&mut self, expr: Stmt) -> StmtId {
55-
self.stmts.push(expr)
54+
pub fn s(&mut self, stmt: Stmt) -> StmtId {
55+
self.stmts.push(stmt)
5656
}
5757

5858
pub fn expr_dont_care(&self) -> ExprId {
@@ -288,6 +288,16 @@ impl SymbolTable {
288288
id
289289
}
290290

291+
pub fn symbol_id_from_name(&self, name: &str) -> Option<SymbolId> {
292+
self.entries.iter().find_map(|(id, entry)| {
293+
if entry.name == name {
294+
Some(id)
295+
} else {
296+
None
297+
}
298+
})
299+
}
300+
291301
pub fn add_with_parent(&mut self, name: String, parent: SymbolId) -> SymbolId {
292302
assert!(
293303
!name.contains('.'),

src/parser.rs

Lines changed: 216 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use pest::Parser;
77
use pest_derive::Parser;
88
use pest::pratt_parser::PrattParser;
99
use pest::iterators::Pairs;
10-
use std::fmt;
10+
use std::{fmt, process::id, vec};
1111
use baa::BitVecValue;
1212

1313
use crate::{ir::*};
@@ -29,41 +29,63 @@ lazy_static::lazy_static! {
2929
};
3030
}
3131

32-
// pub fn parse_expr(pairs: Pairs<Rule>) -> Expr {
33-
// PRATT_PARSER
34-
// .map_primary(|primary| match primary.as_rule() {
35-
// Rule::integer => {
36-
// let int_str = primary.as_str();
37-
// let int_value = int_str.parse::<i32>().unwrap();
38-
// // FIXME: Is this the correct way to convert?
39-
// let bitvec = BitVecValue::from_u64(int_value as u64, 32);
40-
// Expr::Const(bitvec)
41-
// }
42-
// // if primary is an expression (due to parens), recursively parse its inner constituents
43-
// Rule::expr => parse_expr(primary.into_inner()),
44-
// rule => unreachable!("Expr::parse expected atom, found {:?}", rule)
45-
// })
46-
// .map_infix(|lhs, op, rhs| {
47-
// let op = match op.as_rule() {
48-
// Rule::eq => BinOp::Equal,
49-
// Rule::log_and => BinOp::And,
50-
// rule => unreachable!("Expr::parse expected infix operation, found {:?}", rule),
51-
// };
52-
// Expr::Binary {
53-
// op,
54-
// lhs: lhs.
55-
// rhs: Box::new(rhs),
56-
// }
57-
// })
58-
// .map_prefix(|op, arg| {
59-
// let op = match op.as_rule() {
60-
// Rule::negate => UnaryOperator::Negate,
61-
// rule => unreachable!("Expr::parse expected prefix operation, found {:?}", rule),
62-
// };
63-
// Expr::UnaryOp {arg: Box::new(arg) , op: op }
64-
// })
65-
// .parse(pairs)
66-
// }
32+
pub fn parse_expr(pairs: Pairs<Rule>, tr: &mut Transaction, st : &mut SymbolTable) -> ExprId {
33+
PRATT_PARSER
34+
.map_primary(|primary| match primary.as_rule() {
35+
36+
// parse integer literals
37+
Rule::integer => {
38+
let int_str = primary.as_str();
39+
let int_value = int_str.parse::<i32>().unwrap();
40+
// FIXME: Is this the correct way to convert?
41+
let bitvec = BitVecValue::from_u64(int_value as u64, 32);
42+
tr.e(Expr::Const(bitvec))
43+
}
44+
45+
// parse path identifiers
46+
Rule::path_id => {
47+
let path_id = primary.as_str();
48+
let symbol_id = SymbolTable::symbol_id_from_name(st, path_id);
49+
match symbol_id {
50+
Some(id) => tr.e(Expr::Sym(id)),
51+
None => panic!("Referencing undefined symbol: {}", path_id),
52+
}
53+
}
54+
55+
// if primary is an expression (due to parens), recursively parse its inner constituents
56+
Rule::expr => parse_expr(primary.into_inner(), tr, st),
57+
rule => unreachable!("Expr::parse expected atom, found {:?}", rule)
58+
})
59+
60+
// FIXME: two closures require unique access to `*tr` at the same time
61+
// Parse binary expressions
62+
.map_infix(|lhs, op, rhs| {
63+
let op = match op.as_rule() {
64+
Rule::eq => BinOp::Equal,
65+
Rule::log_and => BinOp::And,
66+
rule => unreachable!("Expr::parse expected infix operation, found {:?}", rule),
67+
};
68+
let bin_expression = Expr::Binary(
69+
op,
70+
lhs,
71+
rhs
72+
);
73+
tr.e(bin_expression)
74+
})
75+
76+
// Parse unary expressions
77+
.map_prefix(|op, arg| {
78+
let op = match op.as_rule() {
79+
Rule::not => UnaryOp::Not,
80+
rule => unreachable!("Expr::parse expected prefix operation, found {:?}", rule),
81+
};
82+
let unary_expression = Expr::Unary(op, arg);
83+
tr.e(unary_expression)
84+
})
85+
.parse(pairs)
86+
}
87+
88+
6789
// fn build_ir(pair: pest::iterators::Pair<Rule>) -> (Transaction, SymbolTable) {
6890
// match pair.as_rule() {
6991
// Rule::file => {
@@ -93,25 +115,138 @@ lazy_static::lazy_static! {
93115
// }
94116
// }
95117

96-
fn build_transaction(pair: pest::iterators::Pair<Rule>, sym : &mut SymbolTable) -> Transaction {
118+
fn build_struct(pair : pest::iterators::Pair<Rule>, st : &mut SymbolTable) -> StructId {
119+
let mut inner_rules = pair.into_inner();
120+
let struct_id = inner_rules.next().unwrap().as_str();
121+
122+
let pins = build_fields(inner_rules.next().unwrap(), st);
123+
124+
st.add_struct(struct_id.to_string(), pins)
125+
}
126+
127+
fn build_transaction(pair: pest::iterators::Pair<Rule>, st : &mut SymbolTable) -> Transaction {
97128
match pair.as_rule() {
98129
Rule::fun => {
99130
let mut inner_rules = pair.into_inner();
100131
let id_pair = inner_rules.next().unwrap();
101132
let id = id_pair.as_str();
102-
let mut trans = Transaction::new(id.to_string());
103-
trans.args = build_arglist(inner_rules.next().unwrap(), sym);
104-
// Process the rest of the inner rules if needed
105-
for inner_pair in inner_rules {
106-
// Handle other inner pairs
133+
let mut tr = Transaction::new(id.to_string());
134+
tr.args = build_arglist(inner_rules.next().unwrap(), st);
135+
136+
// Process the body of statements, adding them to the block as we go
137+
while let Some(inner_pair) = inner_rules.next() {
138+
match inner_pair.as_rule() {
139+
Rule::assign => {
140+
let stmt = parse_assign(inner_pair, tr, st);
141+
tr.s(stmt);
142+
}
143+
Rule::cmd => {
144+
let stmt = parse_cmd(inner_pair, tr, st);
145+
tr.s(stmt);
146+
}
147+
Rule::while_loop => {
148+
let stmt = parse_while(inner_pair, tr, st);
149+
tr.s(stmt);
150+
}
151+
Rule::cond => {
152+
let stmt = parse_cond(inner_pair, tr, st);
153+
tr.s(stmt);
154+
}
155+
_ => panic!("Unexpected rule: {:?}", inner_pair.as_rule()),
156+
}
107157
}
108-
trans
158+
println!("Transaction: {:?}", tr);
159+
tr
109160
}
110161
_ => panic!("Unexpected rule: {:?}", pair.as_rule()),
111162
}
112163
}
113164

114-
fn build_arglist(pair : pest::iterators::Pair<Rule>, sym : &mut SymbolTable) -> Vec<Arg> {
165+
fn parse_assign(pair: pest::iterators::Pair<Rule>, tr: &mut Transaction, st: &mut SymbolTable) -> Stmt {
166+
let path_id_rule = pair.into_inner().next().unwrap();
167+
let expr_rule = pair.into_inner().next().unwrap();
168+
169+
let path_id = path_id_rule.as_str();
170+
// TODO: Error handling
171+
let symbol_id = match st.symbol_id_from_name(path_id) {
172+
Some(id) => id,
173+
None => panic!("Assigning to undeclared symbol: {}", path_id),
174+
};
175+
176+
let expr_id = parse_expr(expr_rule.into_inner(), tr, st);
177+
178+
// Dummy implementation
179+
Stmt::Assign(symbol_id, expr_id)
180+
}
181+
182+
fn parse_cmd(pair: pest::iterators::Pair<Rule>, st: &mut SymbolTable) -> Stmt {
183+
let cmd= pair.as_str();
184+
match cmd {
185+
"step" => Stmt::Step,
186+
"fork" => Stmt::Fork,
187+
_ => panic!("Unexpected command: {:?}", cmd),
188+
}
189+
}
190+
191+
fn parse_while(pair: pest::iterators::Pair<Rule>, tr: &mut Transaction, st: &mut SymbolTable) -> Stmt {
192+
// Parse Expression
193+
let mut inner_rules = pair.into_inner();
194+
let expr_rule = inner_rules.next().unwrap();
195+
let guard: ExprId = parse_expr(expr_rule.into_inner(), tr, st);
196+
197+
// Parse Statement Block
198+
let body = parse_stmt_block(inner_rules, tr, st);
199+
200+
Stmt::While(guard, body)
201+
}
202+
203+
fn parse_stmt_block(stmt_pairs: Pairs<Rule>, tr: &mut Transaction, st: &mut SymbolTable) -> StmtId {
204+
// Parse Statement Block. FIXME: Duplicate code.
205+
// Process the body of statements, adding them to the block as we go
206+
let stmts = Vec::new();
207+
while let Some(inner_pair) = stmt_pairs.next() {
208+
match inner_pair.as_rule() {
209+
Rule::assign => {
210+
let stmt = parse_assign(inner_pair, tr, st);
211+
stmts.push(tr.s(stmt));
212+
}
213+
Rule::cmd => {
214+
let stmt = parse_cmd(inner_pair,tr, st);
215+
stmts.push(tr.s(stmt));
216+
}
217+
Rule::while_loop => {
218+
let stmt = parse_while(inner_pair,tr, st);
219+
stmts.push(tr.s(stmt));
220+
}
221+
Rule::cond => {
222+
let stmt = parse_cond(inner_pair, tr, st);
223+
stmts.push(tr.s(stmt));
224+
}
225+
_ => panic!("Unexpected rule: {:?}", inner_pair.as_rule()),
226+
}
227+
}
228+
tr.s(Stmt::Block(stmts))
229+
}
230+
231+
fn parse_cond(pair: pest::iterators::Pair<Rule>, tr: &mut Transaction, st: &mut SymbolTable) -> Stmt {
232+
// Dummy implementation
233+
let mut inner_rules = pair.into_inner();
234+
235+
let if_rule = inner_rules.next().unwrap();
236+
let inner_if = if_rule.into_inner();
237+
let expr_rule = inner_if.next().unwrap();
238+
let expr_id = parse_expr(expr_rule.into_inner(), tr, st);
239+
let if_block = parse_stmt_block(inner_if, tr, st);
240+
241+
let else_rule = inner_rules.next().unwrap();
242+
let inner_else = else_rule.into_inner();
243+
let else_block = parse_stmt_block(inner_else, tr, st);
244+
245+
Stmt::IfElse(expr_id, if_block, else_block)
246+
247+
}
248+
249+
fn build_arglist(pair : pest::iterators::Pair<Rule>, st : &mut SymbolTable) -> Vec<Arg> {
115250
let mut args = Vec::new();
116251
for inner_pair in pair.into_inner() {
117252
match inner_pair.as_rule() {
@@ -125,12 +260,12 @@ fn build_arglist(pair : pest::iterators::Pair<Rule>, sym : &mut SymbolTable) ->
125260
let id = id_pair.as_str();
126261
let tpe = parse_type(tpe_pair);
127262

128-
let symbol_id = sym.add_without_parent(id.to_string(), tpe);
263+
let symbol_id = st.add_without_parent(id.to_string(), tpe);
129264
let arg = Arg::new(symbol_id, dir);
130265
args.push(arg);
131266
}
132267
Rule::arglist => {
133-
let mut nested_args = build_arglist(inner_pair, sym);
268+
let mut nested_args = build_arglist(inner_pair, st);
134269
args.append(&mut nested_args);
135270
}
136271
_ => panic!("Unexpected rule: {:?}", inner_pair.as_rule()),
@@ -139,6 +274,33 @@ fn build_arglist(pair : pest::iterators::Pair<Rule>, sym : &mut SymbolTable) ->
139274
args
140275
}
141276

277+
fn build_fields(pair : pest::iterators::Pair<Rule>, st : &mut SymbolTable) -> Vec<Field> {
278+
let mut fields = Vec::new();
279+
for inner_pair in pair.into_inner() {
280+
match inner_pair.as_rule() {
281+
Rule::arg => {
282+
let mut arg_inner = inner_pair.into_inner();
283+
let dir_pair = arg_inner.next().unwrap();
284+
let id_pair = arg_inner.next().unwrap();
285+
let tpe_pair = arg_inner.next().unwrap();
286+
287+
let dir = parse_dir(dir_pair);
288+
let id = id_pair.as_str();
289+
let tpe = parse_type(tpe_pair);
290+
291+
let field = Field::new(id.to_string(), dir, tpe);
292+
fields.push(field);
293+
}
294+
Rule::arglist => {
295+
let mut nested_fields = build_fields(inner_pair, st);
296+
fields.append(&mut nested_fields);
297+
}
298+
_ => panic!("Unexpected rule: {:?}", inner_pair.as_rule()),
299+
}
300+
}
301+
fields
302+
}
303+
142304
fn parse_dir(pair : pest::iterators::Pair<Rule>) -> Dir {
143305
match pair.as_rule() {
144306
Rule::dir => {
@@ -223,11 +385,15 @@ mod tests {
223385
}
224386
// println!("Length of pairs: {}", pairs.clone().count());
225387
let inner = pairs.clone().next().unwrap().into_inner();
388+
let mut st: &mut SymbolTable = &mut SymbolTable::default();
226389
for pair in inner {
227-
if pair.as_rule() == Rule::fun {
228-
let mut sym = &mut SymbolTable::default();
229-
let mut transaction = build_transaction(pair, sym);
230-
println!("Transaction: {:?}", transaction.name);
390+
if pair.as_rule() == Rule::struct_def {
391+
let _parsed_struct = build_struct(pair, st);
392+
// println!("Struct: {:?}", struct.name);
393+
}
394+
else if pair.as_rule() == Rule::fun {
395+
let _tr = build_transaction(pair, st);
396+
// println!("Transaction: {:?}", transaction.name);
231397
}
232398
}
233399
// let pair = pairs.into_inner();

src/protocols.pest

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ atom = _{primary | unary_op? ~ primary}
1919
unary_op = _ { not }
2020
// negate = { "-" }
2121
not = { "!" }
22-
bin_op = _{ leq | eq | log_and }
22+
bin_op = _{ eq | log_and }
2323
// bin_op = _{ neq | leq | eq | log_and | log_or | shift_left | shift_right | add | subtract | multiply | divide | mod }
2424
// neq = { "!=" }
25-
leq = { "<= "}
25+
// leq = { "<= "}
2626
eq = { "== "}
2727
// add = { "+" }
2828
log_and = { "&&" }
@@ -41,23 +41,22 @@ path_id = @{ id ~ ("." ~ id)* }
4141
tpe = { "u32" | "u1" }
4242
assign = {path_id ~ ":=" ~ (expr | path_id) ~ ";" }
4343
cmd = { path_id ~ "(" ~ ")" ~ ";"}
44-
stmt = _{ (assign | cmd | while | cond) }
45-
dir = {"in" | "out" }
44+
stmt = _{ (assign | cmd | while_loop | cond) }
45+
dir = { "in" | "out" }
4646
arg = { dir ~ id ~ ":" ~ tpe }
4747
arglist = { (arg ~ "," ~ arglist) | arg ~ ","? }
4848
type_param = { "<" ~ id ~ ":" ~ id ~ ">" }
4949

5050
// Loops
51-
while = { "while" ~ expr ~ "{" ~ stmt* ~ "}" }
51+
while_loop = { "while" ~ expr ~ "{" ~ stmt* ~ "}" }
5252

5353
// Conditionals
5454
if = { "if" ~ expr ~ "{" ~ stmt* ~ "}" }
55-
else_if = { "else" ~ "if" ~ expr ~ "{" ~ stmt* ~ "}"}
5655
else = { "else" ~ "{" ~ stmt* ~ "}" }
57-
cond = { if ~ else_if* ~ else? }
56+
cond = { if ~ else? }
5857

5958
// Structs
60-
struct = { "struct" ~ id ~ "{" ~ arglist? ~ "}" }
59+
struct_def = { "struct" ~ id ~ "{" ~ arglist? ~ "}" }
6160

6261
fun = { "fn" ~ id ~ type_param? ~ "(" ~ arglist ~ ")" ~ "{" ~ stmt* ~ "}" }
63-
file = { SOI ~ (fun | struct)* ~ EOI }
62+
file = { SOI ~ (fun | struct_def)* ~ EOI }

0 commit comments

Comments
 (0)