From 532c8c45b4162705ed2de121ade7afa1feb4d4bd Mon Sep 17 00:00:00 2001 From: greg Date: Sat, 12 May 2018 23:49:02 -0700 Subject: [PATCH] Parse while expressions Decided to add while expressions to the language to make for-parsing easier. Plus some other random notes --- schala-lang/src/parsing.rs | 55 ++++++++++++++++++-- schala-lang/src/tokenizing.rs | 3 +- source_files/schala/syntax_playground.schala | 51 ++++++++++-------- 3 files changed, 83 insertions(+), 26 deletions(-) diff --git a/schala-lang/src/parsing.rs b/schala-lang/src/parsing.rs index 8eee7a6..9f2f909 100644 --- a/schala-lang/src/parsing.rs +++ b/schala-lang/src/parsing.rs @@ -56,7 +56,7 @@ prefix_expr := prefix_op call_expr prefix_op := '+' | '-' | '!' | '~' call_expr := index_expr ( '(' expr_list ')' )* index_expr := primary ( '[' (expression (',' (expression)* | ε) ']' )* -primary := literal | paren_expr | if_expr | match_expr | for_expr | identifier_expr | curly_brace_expr | list_expr +primary := literal | paren_expr | if_expr | match_expr | for_expr | while_expr | identifier_expr | curly_brace_expr | list_expr curly_brace_expr := lambda_expr | anonymous_struct //TODO list_expr := '[' (expression, ',')* ']' lambda_expr := '{' '|' (formal_param ',')* '|' (type_anno)* (statement)* '}' @@ -83,7 +83,14 @@ block := '{' (statement)* '}' expr_list := expression (',' expression)* | ε -for_expr := 'for' ... ???? +while_expr := 'while' while_cond '{' (statement)* '}' +while_cond := ε | expression | expression 'is' pattern //TODO maybe is-expresions should be primary + +for_expr := 'for' (enumerator | '{' enumerators '}') for_expr_body +for_expr_body := expression | 'return' expression | '{' (expression)* '} +enumerators := enumerator (',' enumerators)* +enumerator := ??? //TODO flesh this out + // a float_literal can still be assigned to an int in type-checking number_literal := int_literal | float_literal @@ -253,7 +260,13 @@ pub enum ExpressionType { }, IfExpression(Box, Block, Option), MatchExpression(Box, Vec), - ForExpression, + WhileExpression { + condition: Option>, + body: Block, + }, + ForExpression { + + }, Lambda { params: Vec, body: Block, @@ -621,6 +634,7 @@ impl Parser { Keyword(Kw::If) => self.if_expr(), Keyword(Kw::Match) => self.match_expr(), Keyword(Kw::For) => self.for_expr(), + Keyword(Kw::While) => self.while_expr(), Identifier(_) => self.identifier_expr(), _ => self.literal(), } @@ -744,9 +758,29 @@ impl Parser { Ok(Pattern(identifier)) }); + parse_method!(while_expr(&mut self) -> ParseResult { + use self::ExpressionType::*; + expect!(self, Keyword(Kw::While), "'while'"); + let condition = { + self.restrictions.no_struct_literal = true; + let x = self.while_cond(); + self.restrictions.no_struct_literal = false; + x?.map(|expr| bx!(expr)) + }; + let body = self.block()?; + Ok(Expression(WhileExpression {condition, body}, None)) + }); + + parse_method!(while_cond(&mut self) -> ParseResult> { + Ok(match self.peek() { + LCurlyBrace => None, + _ => Some(self.expression()?), + }) + }); + parse_method!(for_expr(&mut self) -> ParseResult { expect!(self, Keyword(Kw::For), "'for'"); - Ok(Expression(ExpressionType::ForExpression, None)) + Ok(Expression(ExpressionType::ForExpression { }, None)) }); parse_method!(identifier(&mut self) -> ParseResult> { @@ -1236,4 +1270,17 @@ fn a(x) { exprstatement!(ListLiteral(vec![ex!(NatLiteral(1)), ex!(NatLiteral(2))]))]) }; } + + #[test] + fn while_expr() { + parse_test! { + "while { }", AST(vec![ + exprstatement!(WhileExpression { condition: None, body: vec![] })]) + } + + parse_test! { + "while a == b { }", AST(vec![ + exprstatement!(WhileExpression { condition: Some(bx![ex![binexp!("==", val!("a"), val!("b"))]]), body: vec![] })]) + } + } } diff --git a/schala-lang/src/tokenizing.rs b/schala-lang/src/tokenizing.rs index 52687e0..6eb6773 100644 --- a/schala-lang/src/tokenizing.rs +++ b/schala-lang/src/tokenizing.rs @@ -47,7 +47,7 @@ impl fmt::Display for TokenType { pub enum Kw { If, Else, Func, - For, + For, While, Match, Var, Const, Let, In, Return, @@ -64,6 +64,7 @@ lazy_static! { "else" => Kw::Else, "fn" => Kw::Func, "for" => Kw::For, + "while" => Kw::While, "match" => Kw::Match, "var" => Kw::Var, "const" => Kw::Const, diff --git a/source_files/schala/syntax_playground.schala b/source_files/schala/syntax_playground.schala index ed2817e..b65c4f2 100644 --- a/source_files/schala/syntax_playground.schala +++ b/source_files/schala/syntax_playground.schala @@ -35,19 +35,26 @@ fn main() { } - for { - //infinite loop - } +/* for/while loop topics */ + + //infinite loop + while { + if x() { break } + ... + } + + + //conditional loop + while conditionHolds() { + ... + } + //iteration over a variable for i <- [1..1000] { } //return type is return type of block - //while loop - for a != 3 || fuckTard() { - break - } //return type is return type of block //monadic decomposition for { @@ -57,23 +64,25 @@ fn main() { a + s } //return type is Monad - // let statements too!! - for (a = 20 - b = fuck) { - a + b +/* end of for loops */ + + + +/* conditionals/pattern matching */ + +// "is" operator for "does this pattern match" + +x is Some(t) // type bool + +if x { + is Some(t) => { + }, + is None => { + } +} - // pattern-matching - match { - Some(a) => { - - }, - None => { - - }, - } - //syntax is, I guess, for , where is a bool, or a // type level alises