Convert parsing while, if, fn exprs to use { }
This commit is contained in:
parent
2b4d3e8516
commit
1fa56800c5
@ -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()
|
||||||
|
12
main.schala
12
main.schala
@ -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()
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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 ¶meters[..] { &[] => true, _ => false }
|
&& **name == "a" && match ¶meters[..] { &[] => 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!(),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
test.schala
12
test.schala
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user