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 := '+' | '-' | '!' | '~'
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<Expression>, Block, Option<Block>),
MatchExpression(Box<Expression>, Vec<MatchArm>),
ForExpression,
WhileExpression {
condition: Option<Box<Expression>>,
body: Block,
},
ForExpression {
},
Lambda {
params: Vec<FormalParam>,
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<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> {
expect!(self, Keyword(Kw::For), "'for'");
Ok(Expression(ExpressionType::ForExpression, None))
Ok(Expression(ExpressionType::ForExpression { }, None))
});
parse_method!(identifier(&mut self) -> ParseResult<Rc<String>> {
@ -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![] })])
}
}
}

View File

@ -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,

View File

@ -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<return type of block>
// 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 <expr> {
Some(a) => {
},
None => {
},
}
//syntax is, I guess, for <expr> <brace-block>, where <expr> is a bool, or a <arrow-expr>
// type level alises