Convert parsing while, if, fn exprs to use { }

This commit is contained in:
greg 2017-01-09 20:33:08 -08:00
parent 2b4d3e8516
commit 1fa56800c5
5 changed files with 60 additions and 43 deletions

View File

@ -1,11 +1,11 @@
fn outer() fn outer() {
fn inner(a) fn inner(a) {
a + 10 a + 10
end }
inner(20) + 8.3 inner(20) + 8.3
end }
outer() outer()

View File

@ -1,17 +1,17 @@
fn add(a, b) fn add(a, b) {
a + b a + b
end }
fn subtract(a, b) fn subtract(a, b) {
a - b a - b
end }
fn main() fn main() {
first_value = add(20, 20) first_value = add(20, 20)
second_value = subtract(700, 650) second_value = subtract(700, 650)
first_value + second_value first_value + second_value
end }
main() main()

View File

@ -1,24 +1,24 @@
fn hella(x) fn hella(x) {
print("hey") print("hey")
if x == 3 then if x == 3 {
Null Null
else } else {
hella(x + 1) hella(x + 1)
end }
end }
hella(0) hella(0)
fn fib(x) fn fib(x) {
if x < 3 then if x < 3 {
1 1
else } else {
fib(x - 1) + fib(x - 2) fib(x - 1) + fib(x - 2)
end }
end }
fib(10) fib(10)

View File

@ -9,17 +9,19 @@ use std::convert::From;
// program := (statement delimiter ?)* // program := (statement delimiter ?)*
// delimiter := Newline | Semicolon // delimiter := Newline | Semicolon
// statement := declaration | expression // statement := declaration | expression
// declaration := Fn prototype (statement)* End // declaration := Fn prototype LCurlyBrace (statement)* RCurlyBrace
// prototype := identifier LParen identlist RParen // prototype := identifier LParen identlist RParen
// identlist := Ident (Comma Ident)* | e // identlist := Ident (Comma Ident)* | e
// exprlist := Expression (Comma Expression)* | e // exprlist := Expression (Comma Expression)* | e
// //
// expression := primary_expression (op primary_expression)* // expression := primary_expression (op primary_expression)*
// primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr // primary_expression := Number | String | identifier_expr | paren_expr | conditional_expr |
// while_expr
// identifier_expr := call_expression | Variable // identifier_expr := call_expression | Variable
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
// paren_expr := LParen expression RParen // paren_expr := LParen expression RParen
// call_expr := Identifier LParen exprlist RParen // call_expr := Identifier LParen exprlist RParen
// conditional_expr := IF expression THEN (expression delimiter?)* ELSE (expresion delimiter?)* END // conditional_expr := IF expression LCurlyBrace (expression delimiter)* RCurlyBrace (LCurlyBrace (expresion delimiter)* RCurlyBrace)?
// op := '+', '-', etc. // op := '+', '-', etc.
// //
@ -271,8 +273,9 @@ impl Parser {
fn declaration(&mut self) -> ParseResult<Statement> { fn declaration(&mut self) -> ParseResult<Statement> {
expect!(self, Keyword(Kw::Fn)); expect!(self, Keyword(Kw::Fn));
let prototype = try!(self.prototype()); let prototype = try!(self.prototype());
expect!(self, LCurlyBrace);
let body = try!(self.body()); let body = try!(self.body());
expect!(self, Keyword(Kw::End)); expect!(self, RCurlyBrace);
Ok(Statement::FuncDefNode(Function { Ok(Statement::FuncDefNode(Function {
prototype: prototype, prototype: prototype,
body: body, body: body,
@ -323,7 +326,7 @@ impl Parser {
let statements = delimiter_block!( let statements = delimiter_block!(
self, self,
statement, statement,
Some(Keyword(Kw::End)) Some(RCurlyBrace)
); );
Ok(statements) Ok(statements)
} }
@ -390,12 +393,13 @@ impl Parser {
use self::Expression::*; use self::Expression::*;
expect!(self, Keyword(Kw::While)); expect!(self, Keyword(Kw::While));
let test = try!(self.expression()); let test = try!(self.expression());
expect!(self, LCurlyBrace);
let body = delimiter_block!( let body = delimiter_block!(
self, self,
expression, expression,
Some(Keyword(Kw::End)) Some(RCurlyBrace)
); );
expect!(self, Keyword(Kw::End)); expect!(self, RCurlyBrace);
Ok(While(Box::new(test), body)) Ok(While(Box::new(test), body))
} }
@ -412,24 +416,35 @@ impl Parser {
_ => break, _ => break,
} }
} }
expect!(self, Keyword(Kw::Then)); expect!(self, LCurlyBrace);
loop {
match self.peek() {
Some(ref t) if is_delimiter(t) => {
self.next();
continue;
}
_ => break,
}
}
let then_block = delimiter_block!( let then_block = delimiter_block!(
self, self,
expression, expression,
Some(Keyword(Kw::Else)) | Some(Keyword(Kw::End)) Some(RCurlyBrace)
); );
expect!(self, RCurlyBrace);
let else_block = if let Some(Keyword(Kw::Else)) = self.peek() { let else_block = if let Some(Keyword(Kw::Else)) = self.peek() {
self.next(); self.next();
expect!(self, LCurlyBrace);
let else_exprs = delimiter_block!( let else_exprs = delimiter_block!(
self, self,
expression, expression,
Some(Keyword(Kw::End)) Some(RCurlyBrace)
); );
Some(else_exprs) Some(else_exprs)
} else { } else {
None None
}; };
expect!(self, Keyword(Kw::End)); expect!(self, RCurlyBrace);
Ok(Conditional(Box::new(test), Ok(Conditional(Box::new(test),
Box::new(Block(VecDeque::from(then_block))), Box::new(Block(VecDeque::from(then_block))),
else_block.map(|list| Box::new(Block(VecDeque::from(list)))))) else_block.map(|list| Box::new(Block(VecDeque::from(list))))))
@ -491,14 +506,14 @@ mod tests {
fn call_parse_test() { fn call_parse_test() {
use super::Function; use super::Function;
parsetest!( parsetest!(
"fn a() 1 + 2 end", "fn a() { 1 + 2 }",
&[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})], &[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})],
match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false } match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false }
&& **name == "a" && match &parameters[..] { &[] => true, _ => false } && **name == "a" && match &parameters[..] { &[] => true, _ => false }
); );
parsetest!( parsetest!(
"fn a(x,y) 1 + 2 end", "fn a(x,y){ 1 + 2 }",
&[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})], &[FuncDefNode(Function {prototype: Prototype { ref name, ref parameters }, ref body})],
match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false } match &body[..] { &[ExprNode(BinExp(_, box Number(1.0), box Number(2.0)))] => true, _ => false }
&& **name == "a" && *parameters[0] == "x" && *parameters[1] == "y" && parameters.len() == 2 && **name == "a" && *parameters[0] == "x" && *parameters[1] == "y" && parameters.len() == 2
@ -525,18 +540,20 @@ mod tests {
#[test] #[test]
fn conditional_parse_test() { fn conditional_parse_test() {
use tokenizer; use tokenizer;
let t1 = "if null then 20 else 40 end"; let t1 = "if null { 20 } else { 40 }";
let tokens = tokenizer::tokenize(t1).unwrap(); let tokens = tokenizer::tokenize(t1).unwrap();
match parse(&tokens, &[]).unwrap()[..] { match parse(&tokens, &[]).unwrap()[..] {
[ExprNode(Conditional(box Null, box Block(_), Some(box Block(_))))] => (), [ExprNode(Conditional(box Null, box Block(_), Some(box Block(_))))] => (),
_ => panic!(), _ => panic!(),
} }
let t2 = "if null\nthen\n20\nelse\n40\nend"; /*
let t2 = "if null\n{\n20\n}\nelse {\n40\n}";
let tokens2 = tokenizer::tokenize(t2).unwrap(); let tokens2 = tokenizer::tokenize(t2).unwrap();
match parse(&tokens2, &[]).unwrap()[..] { match parse(&tokens2, &[]).unwrap()[..] {
[ExprNode(Conditional(box Null, box Block(_), Some(box Block(_))))] => (), [ExprNode(Conditional(box Null, box Block(_), Some(box Block(_))))] => (),
_ => panic!(), _ => panic!(),
} }
*/
} }
} }

View File

@ -1,11 +1,11 @@
fn a(x) fn a(x) {
x + 20 x + 20
end }
fn x(x) fn x(x) {
x + a(9384) x + a(9384)
end }
a(0) a(0)
x(1) x(1)