Chunk of work on if-expr AST
don't expect this to compile yet
This commit is contained in:
parent
61b757313d
commit
95e278d1b5
1
TODO.md
1
TODO.md
@ -1,6 +1,7 @@
|
||||
# TODO items
|
||||
|
||||
## General code cleanup
|
||||
- I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule
|
||||
DONE -experiment with storing metadata via ItemIds on AST nodes (cf. https://rust-lang.github.io/rustc-guide/hir.html, https://github.com/rust-lang/rust/blob/master/src/librustc/hir/mod.rs )
|
||||
-implement and test open/use statements
|
||||
-implement field access
|
||||
|
@ -189,8 +189,8 @@ pub enum ExpressionKind {
|
||||
indexers: Vec<Expression>,
|
||||
},
|
||||
IfExpression {
|
||||
discriminator: Box<Discriminator>,
|
||||
body: Box<IfExpressionBody>,
|
||||
discriminator: Option<Box<Expression>>,
|
||||
body: IfExpressionBody,
|
||||
},
|
||||
WhileExpression {
|
||||
condition: Option<Box<Expression>>,
|
||||
@ -218,36 +218,33 @@ pub enum InvocationArgument {
|
||||
Ignored
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Discriminator {
|
||||
Simple(Expression),
|
||||
BinOp(Expression, BinOp)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum IfExpressionBody {
|
||||
SimpleConditional(Block, Option<Block>),
|
||||
SimplePatternMatch(Pattern, Block, Option<Block>),
|
||||
GuardList(Vec<GuardArm>)
|
||||
SimpleConditional {
|
||||
then_case: Block,
|
||||
else_case: Option<Block>
|
||||
},
|
||||
SimplePatternMatch {
|
||||
pattern: Pattern,
|
||||
then_case: Block,
|
||||
else_case: Option<Block>
|
||||
},
|
||||
CondList(Vec<ConditionArm>)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct GuardArm {
|
||||
pub guard: Guard,
|
||||
pub struct ConditionArm {
|
||||
pub condition: Condition,
|
||||
pub guard: Option<Expression>,
|
||||
pub body: Block,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Guard {
|
||||
None,
|
||||
Pat(Pattern),
|
||||
HalfExpr(HalfExpr)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct HalfExpr {
|
||||
pub op: Option<BinOp>,
|
||||
pub expr: ExpressionKind,
|
||||
pub enum Condition {
|
||||
Pattern(Pattern),
|
||||
TruncatedOp(BinOp, Box<Expression>),
|
||||
Expression(Box<Expression>),
|
||||
Else,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
|
@ -119,13 +119,14 @@
|
||||
//! discriminator
|
||||
//!
|
||||
//! ```text
|
||||
//! if_expr := "if" discriminator ("then" simple_conditional | "is" simple_pattern_match | cond_block)
|
||||
//! if_expr := "if" discriminator if_expr_body
|
||||
//! if_expr_body := ("then" simple_conditional | "is" simple_pattern_match | cond_block)
|
||||
//! discriminator := ε | expression
|
||||
//! simple_conditional := expr_or_block else_clause
|
||||
//! simple_conditional := expr_or_block else_case
|
||||
//! simple_pattern_match := pattern "then" simple_conditional
|
||||
//! else_clause := "else" expr_or_block
|
||||
//! else_case := "else" expr_or_block
|
||||
//!
|
||||
//! cond_block := "{" (cond_arm comma_or_delimiter)* "}"
|
||||
//! cond_block := "{" (cond_arm comma_or_delimiter)* ("else" expr_or_block) "}"
|
||||
//! cond_arm := condition guard "then" expr_or_block
|
||||
//! condition := "is" pattern | operator precedence_expr | expression
|
||||
//! guard := "if" expression
|
||||
@ -811,54 +812,44 @@ impl Parser {
|
||||
#[recursive_descent_method]
|
||||
fn if_expr(&mut self) -> ParseResult<Expression> {
|
||||
expect!(self, Keyword(Kw::If));
|
||||
let discriminator = Box::new({
|
||||
self.restrictions.no_struct_literal = true;
|
||||
let x = self.discriminator();
|
||||
self.restrictions.no_struct_literal = false;
|
||||
x?
|
||||
});
|
||||
|
||||
let body = Box::new(match self.token_handler.peek_kind() {
|
||||
Keyword(Kw::Then) => self.conditional()?,
|
||||
Keyword(Kw::Is) => self.simple_pattern_match()? ,
|
||||
_ => self.guard_block()?
|
||||
});
|
||||
|
||||
let discriminator = if let LCurlyBrace = self.token_handler.peek_kind() {
|
||||
Some(Box::new(self.expression()?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let body = if_expr_body()?;
|
||||
Ok(Expression::new(self.id_store.fresh(), ExpressionKind::IfExpression { discriminator, body }))
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn discriminator(&mut self) -> ParseResult<Discriminator> {
|
||||
let lhs = self.prefix_expr()?;
|
||||
let ref next = self.token_handler.peek_kind();
|
||||
Ok(if let Some(op) = BinOp::from_sigil_token(next) {
|
||||
self.token_handler.next();
|
||||
Discriminator::BinOp(lhs, op)
|
||||
} else {
|
||||
Discriminator::Simple(lhs)
|
||||
})
|
||||
fn if_expr_body(&mut self) -> ParseResult<IfExpressionBody> {
|
||||
match self.token_handler.peek_kind() {
|
||||
Keyword(Kw::Then) => self.simple_conditional()?,
|
||||
Keyword(Kw::Is) => self.simple_pattern_match()? ,
|
||||
_ => self.cond_block()?
|
||||
}
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn conditional(&mut self) -> ParseResult<IfExpressionBody> {
|
||||
fn simple_conditional(&mut self) -> ParseResult<IfExpressionBody> {
|
||||
expect!(self, Keyword(Kw::Then));
|
||||
let then_clause = self.expr_or_block()?;
|
||||
let else_clause = self.else_clause()?;
|
||||
Ok(IfExpressionBody::SimpleConditional(then_clause, else_clause))
|
||||
let then_case = self.expr_or_block()?;
|
||||
let else_case = self.else_case()?;
|
||||
Ok(IfExpressionBody::SimpleConditional {then_case, else_case })
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn simple_pattern_match(&mut self) -> ParseResult<IfExpressionBody> {
|
||||
expect!(self, Keyword(Kw::Is));
|
||||
let pat = self.pattern()?;
|
||||
let pattern = self.pattern()?;
|
||||
expect!(self, Keyword(Kw::Then));
|
||||
let then_clause = self.expr_or_block()?;
|
||||
let else_clause = self.else_clause()?;
|
||||
Ok(IfExpressionBody::SimplePatternMatch(pat, then_clause, else_clause))
|
||||
let then_case = self.expr_or_block()?;
|
||||
let else_case = self.else_case()?;
|
||||
Ok(IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case })
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn else_clause(&mut self) -> ParseResult<Option<Block>> {
|
||||
fn else_case(&mut self) -> ParseResult<Option<Block>> {
|
||||
Ok(if let Keyword(Kw::Else) = self.token_handler.peek_kind() {
|
||||
self.token_handler.next();
|
||||
Some(self.expr_or_block()?)
|
||||
@ -868,7 +859,7 @@ impl Parser {
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn guard_block(&mut self) -> ParseResult<IfExpressionBody> {
|
||||
fn cond_block(&mut self) -> ParseResult<IfExpressionBody> {
|
||||
//TODO - delimited! isn't sophisticated enough to do thisa
|
||||
//let guards = delimited!(self, LCurlyBrace, guard_arm, Comma, RCurlyBrace);
|
||||
expect!(self, LCurlyBrace);
|
||||
|
Loading…
Reference in New Issue
Block a user