Add some display for each, order of operations won't be correct without context
This commit is contained in:
parent
c9295b5777
commit
08cab74fb5
@ -78,13 +78,6 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) ->
|
||||
writeln!(w, "return;")?;
|
||||
}
|
||||
}
|
||||
parser::Stmt::Funcall(call) => {
|
||||
if ctx.is_tail {
|
||||
write!(w, "return ")?;
|
||||
}
|
||||
emit_expr(w, call, ctx)?;
|
||||
writeln!(w, ";")?;
|
||||
}
|
||||
parser::Stmt::Conditional(if_blocks, else_block) => {
|
||||
let mut first_block = true;
|
||||
for if_block in if_blocks {
|
||||
|
106
src/parser.rs
106
src/parser.rs
@ -3,7 +3,6 @@ use std::fmt;
|
||||
#[derive(Debug,PartialEq,Clone)]
|
||||
pub enum Stmt {
|
||||
Assignment(String, Expr),
|
||||
Funcall(Expr),
|
||||
Conditional(Vec<GuardedBlock>, Option<Block>),
|
||||
Loop(Loop),
|
||||
BareExpr(Expr),
|
||||
@ -34,16 +33,6 @@ pub enum Atom {
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl fmt::Display for Atom {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Atom::String(a) => write!(f, "\"{}\"", a),
|
||||
Atom::Num(a) => write!(f, "{}", a),
|
||||
Atom::Bool(a) => write!(f, "{}", a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,PartialEq,Clone)]
|
||||
pub struct GuardedBlock {
|
||||
pub guard: Expr,
|
||||
@ -63,7 +52,6 @@ peg::parser! {
|
||||
= __* s:stmt()* { s }
|
||||
pub rule stmt() -> Stmt
|
||||
= a:assignment() { a } /
|
||||
f:funcall() stop() { Stmt::Funcall(f) } /
|
||||
c:conditional() { c } /
|
||||
l:_loop() { Stmt::Loop(l) } /
|
||||
e:expr() stop() { Stmt::BareExpr(e) }
|
||||
@ -215,6 +203,86 @@ pub fn parse_stmt(stmt: &str) -> Stmt {
|
||||
deelang_parser::stmt(&stmt).unwrap()
|
||||
}
|
||||
|
||||
impl fmt::Display for Stmt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Stmt::Assignment(id, expr) => writeln!(f, "{} <- {}", id, expr),
|
||||
Stmt::BareExpr(expr) => writeln!(f, "{}", expr),
|
||||
Stmt::Conditional(guarded_blocks, else_block) => {
|
||||
let (if_block, elif_blocks) = guarded_blocks.split_first().unwrap();
|
||||
write!(f, "if {}", if_block.guard)?;
|
||||
write_block(f, &if_block.block)?;
|
||||
for elif_block in elif_blocks {
|
||||
write!(f, "elif {}", elif_block.guard)?;
|
||||
write_block(f, &if_block.block)?;
|
||||
}
|
||||
if let Some(block) = else_block {
|
||||
write!(f, "else")?;
|
||||
write_block(f, &block)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Stmt::Loop(loop_inner) => match &loop_inner {
|
||||
Loop::Bare(block) => {
|
||||
write!(f, "loop")?;
|
||||
write_block(f, block)
|
||||
}
|
||||
Loop::Over(id, pred, block) => {
|
||||
write!(f, "loop over {} in {}", id, pred)?;
|
||||
write_block(f, block)
|
||||
}
|
||||
Loop::Until(guarded_block) => {
|
||||
write!(f, "loop until {}", guarded_block.guard)?;
|
||||
write_block(f, &guarded_block.block)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_block (f: &mut fmt::Formatter<'_>, block: &Block) -> fmt::Result {
|
||||
if block.len() == 1 {
|
||||
writeln!(f, " {}", block[0])
|
||||
} else {
|
||||
writeln!(f)?;
|
||||
writeln!(f, ">>>")?;
|
||||
for stmt in block {
|
||||
write!(f, "{}", stmt)?;
|
||||
}
|
||||
writeln!(f, "<<<")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Expr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Expr::Atom(a) => write!(f, "{}", a),
|
||||
Expr::Id(id) => write!(f, "{}", id),
|
||||
Expr::Equal(e1, e2) => write!(f, "{} = {}", e1, e2),
|
||||
Expr::Relop(op, e1, e2) => write!(f, "{} {} {}", e1, op, e2),
|
||||
Expr::Plus(e1, e2) => write!(f, "{} + {}", e1, e2),
|
||||
Expr::Minus(e1, e2) => write!(f, "{} - {}", e1, e2),
|
||||
Expr::Div(e1, e2) => write!(f, "{} / {}", e1, e2),
|
||||
Expr::Mult(e1, e2) => write!(f, "{} * {}", e1, e2),
|
||||
Expr::Mod(e1, e2) => write!(f, "{} % {}", e1, e2),
|
||||
Expr::UnaryMinus(e) => write!(f, "-{}", e),
|
||||
|
||||
Expr::Funcdef(_arg, _block) => todo!(),
|
||||
Expr::Funcall(_id, _args) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Atom {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Atom::String(a) => write!(f, "\"{}\"", a),
|
||||
Atom::Num(a) => write!(f, "{}", a),
|
||||
Atom::Bool(a) => write!(f, "{}", a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
@ -232,8 +300,8 @@ apple <- 1 ## This is too
|
||||
#[test]
|
||||
fn test_funcall() {
|
||||
let expected = vec![
|
||||
Stmt::Funcall(Expr::Funcall("pear".to_string(), vec![])),
|
||||
Stmt::Funcall(Expr::Funcall("pear".to_string(),
|
||||
Stmt::BareExpr(Expr::Funcall("pear".to_string(), vec![])),
|
||||
Stmt::BareExpr(Expr::Funcall("pear".to_string(),
|
||||
vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())],
|
||||
))
|
||||
];
|
||||
@ -326,8 +394,8 @@ foo <- x -> y -> x * y";
|
||||
Expr::Funcdef(
|
||||
None,
|
||||
vec![
|
||||
Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])),
|
||||
Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])),
|
||||
Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![])),
|
||||
Stmt::BareExpr(Expr::Funcall("baz".to_string(), vec![])),
|
||||
],
|
||||
)
|
||||
),
|
||||
@ -366,14 +434,14 @@ else
|
||||
vec![
|
||||
GuardedBlock {
|
||||
guard: Expr::Id("foo".to_string()),
|
||||
block: vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))]
|
||||
block: vec![Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![]))]
|
||||
},
|
||||
GuardedBlock {
|
||||
guard: Expr::Id("baz".to_string()),
|
||||
block: vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))],
|
||||
block: vec![Stmt::BareExpr(Expr::Funcall("foobar".to_string(), vec![]))],
|
||||
},
|
||||
],
|
||||
Some(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))]),
|
||||
Some(vec![Stmt::BareExpr(Expr::Funcall("quux".to_string(), vec![]))]),
|
||||
)];
|
||||
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user