Compare commits
2 Commits
03b140189c
...
08cab74fb5
Author | SHA1 | Date | |
---|---|---|---|
08cab74fb5 | |||
c9295b5777 |
@ -78,13 +78,6 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) ->
|
|||||||
writeln!(w, "return;")?;
|
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) => {
|
parser::Stmt::Conditional(if_blocks, else_block) => {
|
||||||
let mut first_block = true;
|
let mut first_block = true;
|
||||||
for if_block in if_blocks {
|
for if_block in if_blocks {
|
||||||
|
120
src/parser.rs
120
src/parser.rs
@ -3,7 +3,6 @@ use std::fmt;
|
|||||||
#[derive(Debug,PartialEq,Clone)]
|
#[derive(Debug,PartialEq,Clone)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Assignment(String, Expr),
|
Assignment(String, Expr),
|
||||||
Funcall(Expr),
|
|
||||||
Conditional(Vec<GuardedBlock>, Option<Block>),
|
Conditional(Vec<GuardedBlock>, Option<Block>),
|
||||||
Loop(Loop),
|
Loop(Loop),
|
||||||
BareExpr(Expr),
|
BareExpr(Expr),
|
||||||
@ -34,16 +33,6 @@ pub enum Atom {
|
|||||||
Bool(bool),
|
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)]
|
#[derive(Debug,PartialEq,Clone)]
|
||||||
pub struct GuardedBlock {
|
pub struct GuardedBlock {
|
||||||
pub guard: Expr,
|
pub guard: Expr,
|
||||||
@ -63,7 +52,6 @@ peg::parser! {
|
|||||||
= __* s:stmt()* { s }
|
= __* s:stmt()* { s }
|
||||||
pub rule stmt() -> Stmt
|
pub rule stmt() -> Stmt
|
||||||
= a:assignment() { a } /
|
= a:assignment() { a } /
|
||||||
f:funcall() stop() { Stmt::Funcall(f) } /
|
|
||||||
c:conditional() { c } /
|
c:conditional() { c } /
|
||||||
l:_loop() { Stmt::Loop(l) } /
|
l:_loop() { Stmt::Loop(l) } /
|
||||||
e:expr() stop() { Stmt::BareExpr(e) }
|
e:expr() stop() { Stmt::BareExpr(e) }
|
||||||
@ -215,6 +203,86 @@ pub fn parse_stmt(stmt: &str) -> Stmt {
|
|||||||
deelang_parser::stmt(&stmt).unwrap()
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
@ -232,8 +300,8 @@ apple <- 1 ## This is too
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_funcall() {
|
fn test_funcall() {
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Stmt::Funcall(Expr::Funcall("pear".to_string(), vec![])),
|
Stmt::BareExpr(Expr::Funcall("pear".to_string(), vec![])),
|
||||||
Stmt::Funcall(Expr::Funcall("pear".to_string(),
|
Stmt::BareExpr(Expr::Funcall("pear".to_string(),
|
||||||
vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())],
|
vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())],
|
||||||
))
|
))
|
||||||
];
|
];
|
||||||
@ -326,8 +394,8 @@ foo <- x -> y -> x * y";
|
|||||||
Expr::Funcdef(
|
Expr::Funcdef(
|
||||||
None,
|
None,
|
||||||
vec![
|
vec![
|
||||||
Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])),
|
Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![])),
|
||||||
Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])),
|
Stmt::BareExpr(Expr::Funcall("baz".to_string(), vec![])),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -366,18 +434,30 @@ else
|
|||||||
vec![
|
vec![
|
||||||
GuardedBlock {
|
GuardedBlock {
|
||||||
guard: Expr::Id("foo".to_string()),
|
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 {
|
GuardedBlock {
|
||||||
guard: Expr::Id("baz".to_string()),
|
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);
|
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_loop() {
|
||||||
|
let prgm = r"loop until i > 100 a";
|
||||||
|
let expected = vec![Stmt::Loop(Loop::Until(GuardedBlock {
|
||||||
|
guard: Expr::Relop(
|
||||||
|
">".to_string(),
|
||||||
|
Box::new(Expr::Id("i".to_string())),
|
||||||
|
Box::new(Expr::Atom(Atom::Num(100.0))),
|
||||||
|
),
|
||||||
|
block: vec![Stmt::BareExpr(Expr::Id("a".to_string()))],
|
||||||
|
}))];
|
||||||
|
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
|
||||||
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_preprocess() {
|
fn test_preprocess() {
|
||||||
let prgm = r"
|
let prgm = r"
|
||||||
|
Loading…
Reference in New Issue
Block a user