From bb2c8418d02ff48e1803e92ec8183f1bee604d97 Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Sun, 20 Sep 2020 14:22:31 +0200 Subject: [PATCH] move to new syntax, wip1 --- examples/let_if.rs | 4 ++ src/ast.rs | 4 ++ src/check.rs | 4 ++ src/grammar.lalrpop | 127 +++++++++++++++++++++++++++++--------------- tests/test_check.rs | 5 ++ 5 files changed, 100 insertions(+), 44 deletions(-) create mode 100644 examples/let_if.rs diff --git a/examples/let_if.rs b/examples/let_if.rs new file mode 100644 index 0000000..2a5d802 --- /dev/null +++ b/examples/let_if.rs @@ -0,0 +1,4 @@ +fn main() { + //let a: i32 = if true { 1 } else { 2 }; + let a = 5; +} diff --git a/src/ast.rs b/src/ast.rs index e2ccc47..8ee7334 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -94,6 +94,8 @@ pub enum Expr { RefMut(Box<Expr>), DeRef(Box<Expr>), Call(Id, Exprs), + Block(Stmts), + Stmt(Stmt), } #[derive(Debug, PartialEq, Clone)] @@ -319,6 +321,8 @@ impl Display for Expr { RefMut(ref e) => write!(fmt, "&mut {}", e), DeRef(ref e) => write!(fmt, "*{}", e), Call(ref s, ref exprs) => write!(fmt, "{}{}", s, exprs), + Block(ref s) => write!(fmt, "{}", s), + Stmt(ref s) => write!(fmt, "{}", s), } } } diff --git a/src/check.rs b/src/check.rs index b8fb4a5..612b312 100644 --- a/src/check.rs +++ b/src/check.rs @@ -187,6 +187,10 @@ fn expr_type( _ => Err(format!("cannot deref {} of type {}", e, t)), } } + + Block(b) => panic!(), + + Stmt(s) => panic!(), } } diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop index 239904f..c5239ea 100644 --- a/src/grammar.lalrpop +++ b/src/grammar.lalrpop @@ -98,7 +98,7 @@ Variant : Variant = { } pub FnDecl : FnDecl = { - "fn" <id: Id> <params: Params> <result: ("->" <Type>)?> "{" <body: Stmts> "}" + "fn" <id: Id> <params: Params> <result: ("->" <Type>)?> <body: Block> => FnDecl { id, params, @@ -126,29 +126,6 @@ Param : Param = { }, } -pub Stmts: Stmts = { - <s: (<Stmt> ";")*> <e: Stmt?> => match e { - // stmts return () - None => Stmts { stmts: s, ret: true }, - // last statement is the return value - Some(e) => { - let mut s = s; - s.push(e); - Stmts { stmts: s, ret: false } - }, - } -} - -Stmt : Stmt = { - "let" <m: "mut"?> <id: Id> <t: (":" <Type>)?> <e: ("=" <Expr>)?> => Stmt::Let(id, m.is_some(), t, e), - <Expr> "=" <Expr> => Stmt::Assign(<>), - "while" <Expr> "{" <Stmts> "}" => Stmt::While(<>), - "if" <Expr> "{" <Stmts> "}" < ("else" "{" <Stmts> "}")?> => Stmt::If(<>), - <Expr> => Stmt::Expr(<>), - "{" <Stmts> "}" => Stmt::Block(<>), -} - - Type : Type = { "bool" => Type::Bool, "()" => Type::Unit, @@ -158,16 +135,79 @@ Type : Type = { "&" "mut" <Type> => Type::Ref(Box::new(Type::Mut(Box::new(<>)))), } +// pub Stmts: Stmts = { +// <s: (<Stmt> ";")*> <e: Stmt?> => match e { +// // stmts return () +// None => Stmts { stmts: s, ret: true }, +// // last statement is the return value +// Some(e) => { +// let mut s = s; +// s.push(e); +// Stmts { stmts: s, ret: false } +// }, +// } +// } + +pub Block: Stmts = { + "{" <Stmt*> "}" => Stmts { stmts: <>, ret: false }, +} + +// pub Stmt: () = { +// ";" => (), +// "let" "mut"? Id "=" Expr ";" => (), +// ExprNoBlock "=" Expr => (), +// "while" Expr Block => (), +// "if" Expr Block ("else" Block)? => (), +// ExprNoBlock => (), +// Block => (), +// } + + + + + +Stmt : Stmt = { + ";" => Stmt::Semi, + //"let" <m: "mut"?> <id: Id> <t: (":" <Type>)?> <e: ("=" <Expr>)?> => Stmt::Let(id, m.is_some(), t, e), + // <Expr> "=" <Expr> => Stmt::Assign(<>), + // "while" <Expr> "{" <Block> "}" => Stmt::While(<>), + // "if" <Expr> <Block> < ("else" <Block>)?> => Stmt::If(<>), + <ExprNoBlock> => Stmt::Expr(<>), + + // <Block> => Stmt::Block(<>), +} + + + + pub Exprs : Exprs = { - ParCNT<Expr> => Exprs( <> ), -}; + ParCNT<ExprNoBlock> => Exprs( <> ), +} + +pub Expr = { + ExprBlock, + ExprNoBlock, +} + +pub ExprBlock: Box<Expr> = { + "if" <e: Expr> <tb: Block> "else" <eb: Block> => { + let s = Stmt::If(e, tb, Some(eb)); + Box::new(Expr::Stmt(s)) + }, + Block => Box::new(Expr::Block(<>)), +} + +pub ExprNoBlock: Box<Expr> = { + // ExprNoBlock Cmp Expr1 => (), + Expr1, +} // Not sure about the precedence -pub Expr: Box<Expr> = { - Expr BoolOp Factor => Box::new(Expr::Infix(<>)), - Expr AddSubOp Factor => Box::new(Expr::Infix(<>)), - <Expr> "as" <Type> => Box::new(Expr::As(<>)), - Factor, +pub Expr1: Box<Expr> = { + Expr1 BoolOp Expr2 => Box::new(Expr::Infix(<>)), + Expr1 AddSubOp Expr2 => Box::new(Expr::Infix(<>)), + <Expr1> "as" <Type> => Box::new(Expr::As(<>)), + Expr2, }; AddSubOp: Op = { @@ -186,8 +226,8 @@ BoolOp: Op = { "&&" => Op::And, }; -Factor: Box<Expr> = { - Factor MulDivOp Term => Box::new(Expr::Infix(<>)), +Expr2: Box<Expr> = { + Expr2 MulDivOp Term => Box::new(Expr::Infix(<>)), Term, }; @@ -198,17 +238,16 @@ MulDivOp: Op = { Term: Box<Expr> = { Num => Box::new(Expr::Num(<>)), - "true" => Box::new(Expr::Bool(true)), - "false" => Box::new(Expr::Bool(false)), - <Id> <Exprs> => Box::new(Expr::Call(<>)), - Id => Box::new(Expr::Id(<>)), - AddSubOp Term => Box::new(Expr::Prefix(<>)), - "!" <Term> => Box::new(Expr::Prefix(Op::Not, <>)), - "&" <Term> => Box::new(Expr::Ref(<>)), - "&" "mut" <Term> => Box::new(Expr::RefMut(<>)), - "*" <Term> => Box::new(Expr::DeRef(<>)), - "(" <Expr> ")" - // "{{" <Stmt> "}} "=> Box::new(Expr::Stmt(<>)) + // "true" => Box::new(Expr::Bool(true)), + // "false" => Box::new(Expr::Bool(false)), + // <Id> <Exprs> => Box::new(Expr::Call(<>)), + // Id => Box::new(Expr::Id(<>)), + // AddSubOp Term => Box::new(Expr::Prefix(<>)), + // "!" <Term> => Box::new(Expr::Prefix(Op::Not, <>)), + // "&" <Term> => Box::new(Expr::Ref(<>)), + // "&" "mut" <Term> => Box::new(Expr::RefMut(<>)), + // "*" <Term> => Box::new(Expr::DeRef(<>)), + // "(" <Expr> ")" }; Num: i32 = { diff --git a/tests/test_check.rs b/tests/test_check.rs index 6334148..38dc8f2 100644 --- a/tests/test_check.rs +++ b/tests/test_check.rs @@ -169,3 +169,8 @@ fn check_scopes() { fn check_scopes_err() { assert!(check(&read_file::parse("examples/scopes_err.rs")).is_err()); } + +#[test] +fn check_let_if() { + assert!(check(&read_file::parse("examples/let_if.rs")).is_err()); +} -- GitLab