Chunk of work on if-expr AST

don't expect this to compile yet
This commit is contained in:
greg 2019-10-10 03:29:28 -07:00
parent 61b757313d
commit 95e278d1b5
3 changed files with 48 additions and 59 deletions

View File

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

View File

@ -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)]

View File

@ -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);