Handle negatives in patterns correctly

This commit is contained in:
greg 2018-08-21 19:57:45 -07:00
parent 5c9180efc2
commit fa7b6ce96b
3 changed files with 55 additions and 9 deletions

View File

@ -157,7 +157,10 @@ pub enum Pattern {
#[derive(Debug, PartialEq, Clone)]
pub enum PatternLiteral {
NumPattern(ExpressionType), //TODO fix
NumPattern {
neg: bool,
num: ExpressionType,
},
StringPattern(Rc<String>),
BoolPattern(bool),
VarPattern(Rc<String>)

View File

@ -235,7 +235,8 @@ digits := (DIGIT_GROUP underscore)+
/* Pattern syntax */
pattern := '(' (pattern, ',')* ')' | simple_pattern
simple_pattern := pattern_literal | record_pattern | tuple_struct_pattern
pattern_literal := 'true' | 'false' | number_literal | STR_LITERAL | IDENTIFIER
pattern_literal := 'true' | 'false' | signed_number_literal | STR_LITERAL | IDENTIFIER
signed_number_literal := '-'? number_literal
record_pattern := IDENTIFIER '{' (record_pattern_entry, ',')* '}'
record_pattern_entry := IDENTIFIER | IDENTIFIER ':' Pattern
tuple_struct_pattern := IDENTIFIER '(' (pattern, ',')* ')'
@ -735,14 +736,12 @@ impl Parser {
_ => Pattern::Literal(PatternLiteral::VarPattern(id))
}
},
//TODO I think these are buggy b/c they don't advance the parser
Keyword(Kw::True) => Pattern::Literal(PatternLiteral::BoolPattern(true)),
Keyword(Kw::False) => Pattern::Literal(PatternLiteral::BoolPattern(false)),
StrLiteral(s) => Pattern::Literal(PatternLiteral::StringPattern(s)),
DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => {
//TODO handle negatives
let Expression(expr_type, _) = self.number_literal()?;
Pattern::Literal(PatternLiteral::NumPattern(expr_type))
},
DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => self.signed_number_literal()?,
Operator(ref op) if **op == "-" => self.signed_number_literal()?,
Underscore => {
self.next();
Pattern::Ignored
@ -751,6 +750,18 @@ impl Parser {
})
});
parse_method!(signed_number_literal(&mut self) -> ParseResult<Pattern> {
let neg = match self.peek() {
Operator(ref op) if **op == "-" => {
self.next();
true
},
_ => false
};
let Expression(expr_type, _) = self.number_literal()?;
Ok(Pattern::Literal(PatternLiteral::NumPattern { neg, num: expr_type }))
});
parse_method!(record_pattern_entry(&mut self) -> ParseResult<(Rc<String>, Pattern)> {
let name = self.identifier()?;
Ok(match self.peek() {
@ -1439,5 +1450,37 @@ fn a(x) {
)
])
}
parse_test! {
"if x is -1 then 1 else 2", AST(vec![
exprstatement!(
IfExpression {
discriminator: bx!(Discriminator::Simple(ex!(Value(rc!(x))))),
body: bx!(IfExpressionBody::SimplePatternMatch(
Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: NatLiteral(1) }),
vec![exprstatement!(NatLiteral(1))],
Some(vec![exprstatement!(NatLiteral(2))]),
))
}
)
])
}
parse_test! {
"if x is 1 then 1 else 2", AST(vec![
exprstatement!(
IfExpression {
discriminator: bx!(Discriminator::Simple(ex!(Value(rc!(x))))),
body: bx!(IfExpressionBody::SimplePatternMatch(
Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1) }),
vec![exprstatement!(NatLiteral(1))],
Some(vec![exprstatement!(NatLiteral(2))]),
))
}
)
])
}
}
}

View File

@ -173,7 +173,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
item: then_clause,
}
},
_ => panic!()
e => { println!("SAW {:?}", e); panic!() }
};
let alternatives = vec![
@ -196,7 +196,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
Guard::Pat(ref p) => match p {
Pattern::Ignored => (None, vec![]),
Pattern::Literal(lit) => match lit {
PatternLiteral::NumPattern(_expr) => unimplemented!(),
PatternLiteral::NumPattern { neg, num } => unimplemented!(),
PatternLiteral::StringPattern(_s) => unimplemented!(),
PatternLiteral::BoolPattern(_b) => unimplemented!(),
PatternLiteral::VarPattern(_var) => unimplemented!(),