Parse while expressions

Decided to add while expressions to the language to make for-parsing
easier. Plus some other random notes
This commit is contained in:
greg 2018-05-12 23:49:02 -07:00
parent 24b532df06
commit 532c8c45b4
3 changed files with 83 additions and 26 deletions

View File

@ -56,7 +56,7 @@ prefix_expr := prefix_op call_expr
prefix_op := '+' | '-' | '!' | '~' prefix_op := '+' | '-' | '!' | '~'
call_expr := index_expr ( '(' expr_list ')' )* call_expr := index_expr ( '(' expr_list ')' )*
index_expr := primary ( '[' (expression (',' (expression)* | ε) ']' )* 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 curly_brace_expr := lambda_expr | anonymous_struct //TODO
list_expr := '[' (expression, ',')* ']' list_expr := '[' (expression, ',')* ']'
lambda_expr := '{' '|' (formal_param ',')* '|' (type_anno)* (statement)* '}' lambda_expr := '{' '|' (formal_param ',')* '|' (type_anno)* (statement)* '}'
@ -83,7 +83,14 @@ block := '{' (statement)* '}'
expr_list := expression (',' expression)* | ε 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 // a float_literal can still be assigned to an int in type-checking
number_literal := int_literal | float_literal number_literal := int_literal | float_literal
@ -253,7 +260,13 @@ pub enum ExpressionType {
}, },
IfExpression(Box<Expression>, Block, Option<Block>), IfExpression(Box<Expression>, Block, Option<Block>),
MatchExpression(Box<Expression>, Vec<MatchArm>), MatchExpression(Box<Expression>, Vec<MatchArm>),
ForExpression, WhileExpression {
condition: Option<Box<Expression>>,
body: Block,
},
ForExpression {
},
Lambda { Lambda {
params: Vec<FormalParam>, params: Vec<FormalParam>,
body: Block, body: Block,
@ -621,6 +634,7 @@ impl Parser {
Keyword(Kw::If) => self.if_expr(), Keyword(Kw::If) => self.if_expr(),
Keyword(Kw::Match) => self.match_expr(), Keyword(Kw::Match) => self.match_expr(),
Keyword(Kw::For) => self.for_expr(), Keyword(Kw::For) => self.for_expr(),
Keyword(Kw::While) => self.while_expr(),
Identifier(_) => self.identifier_expr(), Identifier(_) => self.identifier_expr(),
_ => self.literal(), _ => self.literal(),
} }
@ -744,9 +758,29 @@ impl Parser {
Ok(Pattern(identifier)) Ok(Pattern(identifier))
}); });
parse_method!(while_expr(&mut self) -> ParseResult<Expression> {
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<Option<Expression>> {
Ok(match self.peek() {
LCurlyBrace => None,
_ => Some(self.expression()?),
})
});
parse_method!(for_expr(&mut self) -> ParseResult<Expression> { parse_method!(for_expr(&mut self) -> ParseResult<Expression> {
expect!(self, Keyword(Kw::For), "'for'"); expect!(self, Keyword(Kw::For), "'for'");
Ok(Expression(ExpressionType::ForExpression, None)) Ok(Expression(ExpressionType::ForExpression { }, None))
}); });
parse_method!(identifier(&mut self) -> ParseResult<Rc<String>> { parse_method!(identifier(&mut self) -> ParseResult<Rc<String>> {
@ -1236,4 +1270,17 @@ fn a(x) {
exprstatement!(ListLiteral(vec![ex!(NatLiteral(1)), ex!(NatLiteral(2))]))]) 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![] })])
}
}
} }

View File

@ -47,7 +47,7 @@ impl fmt::Display for TokenType {
pub enum Kw { pub enum Kw {
If, Else, If, Else,
Func, Func,
For, For, While,
Match, Match,
Var, Const, Let, In, Var, Const, Let, In,
Return, Return,
@ -64,6 +64,7 @@ lazy_static! {
"else" => Kw::Else, "else" => Kw::Else,
"fn" => Kw::Func, "fn" => Kw::Func,
"for" => Kw::For, "for" => Kw::For,
"while" => Kw::While,
"match" => Kw::Match, "match" => Kw::Match,
"var" => Kw::Var, "var" => Kw::Var,
"const" => Kw::Const, "const" => Kw::Const,

View File

@ -35,19 +35,26 @@ fn main() {
} }
for { /* for/while loop topics */
//infinite loop
} //infinite loop
while {
if x() { break }
...
}
//conditional loop
while conditionHolds() {
...
}
//iteration over a variable //iteration over a variable
for i <- [1..1000] { for i <- [1..1000] {
} //return type is return type of block } //return type is return type of block
//while loop
for a != 3 || fuckTard() {
break
} //return type is return type of block
//monadic decomposition //monadic decomposition
for { for {
@ -57,23 +64,25 @@ fn main() {
a + s a + s
} //return type is Monad<return type of block> } //return type is Monad<return type of block>
// let statements too!! /* end of for loops */
for (a = 20
b = fuck) {
a + b
/* 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 <expr> {
Some(a) => {
},
None => {
},
}
//syntax is, I guess, for <expr> <brace-block>, where <expr> is a bool, or a <arrow-expr> //syntax is, I guess, for <expr> <brace-block>, where <expr> is a bool, or a <arrow-expr>
// type level alises // type level alises