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 # TODO items
## General code cleanup ## 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 ) 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 and test open/use statements
-implement field access -implement field access

View File

@ -189,8 +189,8 @@ pub enum ExpressionKind {
indexers: Vec<Expression>, indexers: Vec<Expression>,
}, },
IfExpression { IfExpression {
discriminator: Box<Discriminator>, discriminator: Option<Box<Expression>>,
body: Box<IfExpressionBody>, body: IfExpressionBody,
}, },
WhileExpression { WhileExpression {
condition: Option<Box<Expression>>, condition: Option<Box<Expression>>,
@ -218,36 +218,33 @@ pub enum InvocationArgument {
Ignored Ignored
} }
#[derive(Debug, PartialEq, Clone)]
pub enum Discriminator {
Simple(Expression),
BinOp(Expression, BinOp)
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum IfExpressionBody { pub enum IfExpressionBody {
SimpleConditional(Block, Option<Block>), SimpleConditional {
SimplePatternMatch(Pattern, Block, Option<Block>), then_case: Block,
GuardList(Vec<GuardArm>) else_case: Option<Block>
},
SimplePatternMatch {
pattern: Pattern,
then_case: Block,
else_case: Option<Block>
},
CondList(Vec<ConditionArm>)
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct GuardArm { pub struct ConditionArm {
pub guard: Guard, pub condition: Condition,
pub guard: Option<Expression>,
pub body: Block, pub body: Block,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Guard { pub enum Condition {
None, Pattern(Pattern),
Pat(Pattern), TruncatedOp(BinOp, Box<Expression>),
HalfExpr(HalfExpr) Expression(Box<Expression>),
} Else,
#[derive(Debug, PartialEq, Clone)]
pub struct HalfExpr {
pub op: Option<BinOp>,
pub expr: ExpressionKind,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]

View File

@ -119,13 +119,14 @@
//! discriminator //! discriminator
//! //!
//! ```text //! ```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 //! discriminator := ε | expression
//! simple_conditional := expr_or_block else_clause //! simple_conditional := expr_or_block else_case
//! simple_pattern_match := pattern "then" simple_conditional //! 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 //! cond_arm := condition guard "then" expr_or_block
//! condition := "is" pattern | operator precedence_expr | expression //! condition := "is" pattern | operator precedence_expr | expression
//! guard := "if" expression //! guard := "if" expression
@ -811,54 +812,44 @@ impl Parser {
#[recursive_descent_method] #[recursive_descent_method]
fn if_expr(&mut self) -> ParseResult<Expression> { fn if_expr(&mut self) -> ParseResult<Expression> {
expect!(self, Keyword(Kw::If)); expect!(self, Keyword(Kw::If));
let discriminator = Box::new({ let discriminator = if let LCurlyBrace = self.token_handler.peek_kind() {
self.restrictions.no_struct_literal = true; Some(Box::new(self.expression()?))
let x = self.discriminator(); } else {
self.restrictions.no_struct_literal = false; None
x? };
}); let body = if_expr_body()?;
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()?
});
Ok(Expression::new(self.id_store.fresh(), ExpressionKind::IfExpression { discriminator, body })) Ok(Expression::new(self.id_store.fresh(), ExpressionKind::IfExpression { discriminator, body }))
} }
#[recursive_descent_method] #[recursive_descent_method]
fn discriminator(&mut self) -> ParseResult<Discriminator> { fn if_expr_body(&mut self) -> ParseResult<IfExpressionBody> {
let lhs = self.prefix_expr()?; match self.token_handler.peek_kind() {
let ref next = self.token_handler.peek_kind(); Keyword(Kw::Then) => self.simple_conditional()?,
Ok(if let Some(op) = BinOp::from_sigil_token(next) { Keyword(Kw::Is) => self.simple_pattern_match()? ,
self.token_handler.next(); _ => self.cond_block()?
Discriminator::BinOp(lhs, op) }
} else {
Discriminator::Simple(lhs)
})
} }
#[recursive_descent_method] #[recursive_descent_method]
fn conditional(&mut self) -> ParseResult<IfExpressionBody> { fn simple_conditional(&mut self) -> ParseResult<IfExpressionBody> {
expect!(self, Keyword(Kw::Then)); expect!(self, Keyword(Kw::Then));
let then_clause = self.expr_or_block()?; let then_case = self.expr_or_block()?;
let else_clause = self.else_clause()?; let else_case = self.else_case()?;
Ok(IfExpressionBody::SimpleConditional(then_clause, else_clause)) Ok(IfExpressionBody::SimpleConditional {then_case, else_case })
} }
#[recursive_descent_method] #[recursive_descent_method]
fn simple_pattern_match(&mut self) -> ParseResult<IfExpressionBody> { fn simple_pattern_match(&mut self) -> ParseResult<IfExpressionBody> {
expect!(self, Keyword(Kw::Is)); expect!(self, Keyword(Kw::Is));
let pat = self.pattern()?; let pattern = self.pattern()?;
expect!(self, Keyword(Kw::Then)); expect!(self, Keyword(Kw::Then));
let then_clause = self.expr_or_block()?; let then_case = self.expr_or_block()?;
let else_clause = self.else_clause()?; let else_case = self.else_case()?;
Ok(IfExpressionBody::SimplePatternMatch(pat, then_clause, else_clause)) Ok(IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case })
} }
#[recursive_descent_method] #[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() { Ok(if let Keyword(Kw::Else) = self.token_handler.peek_kind() {
self.token_handler.next(); self.token_handler.next();
Some(self.expr_or_block()?) Some(self.expr_or_block()?)
@ -868,7 +859,7 @@ impl Parser {
} }
#[recursive_descent_method] #[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 //TODO - delimited! isn't sophisticated enough to do thisa
//let guards = delimited!(self, LCurlyBrace, guard_arm, Comma, RCurlyBrace); //let guards = delimited!(self, LCurlyBrace, guard_arm, Comma, RCurlyBrace);
expect!(self, LCurlyBrace); expect!(self, LCurlyBrace);