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:
parent
24b532df06
commit
532c8c45b4
@ -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![] })])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -35,19 +35,26 @@ fn main() {
|
||||
}
|
||||
|
||||
|
||||
for {
|
||||
/* 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,22 +64,24 @@ 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 */
|
||||
|
||||
|
||||
// pattern-matching
|
||||
match <expr> {
|
||||
Some(a) => {
|
||||
|
||||
/* conditionals/pattern matching */
|
||||
|
||||
// "is" operator for "does this pattern match"
|
||||
|
||||
x is Some(t) // type bool
|
||||
|
||||
if x {
|
||||
is Some(t) => {
|
||||
},
|
||||
None => {
|
||||
is None => {
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//syntax is, I guess, for <expr> <brace-block>, where <expr> is a bool, or a <arrow-expr>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user