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)] #[derive(Debug, PartialEq, Clone)]
pub enum PatternLiteral { pub enum PatternLiteral {
NumPattern(ExpressionType), //TODO fix NumPattern {
neg: bool,
num: ExpressionType,
},
StringPattern(Rc<String>), StringPattern(Rc<String>),
BoolPattern(bool), BoolPattern(bool),
VarPattern(Rc<String>) VarPattern(Rc<String>)

View File

@ -235,7 +235,8 @@ digits := (DIGIT_GROUP underscore)+
/* Pattern syntax */ /* Pattern syntax */
pattern := '(' (pattern, ',')* ')' | simple_pattern pattern := '(' (pattern, ',')* ')' | simple_pattern
simple_pattern := pattern_literal | record_pattern | tuple_struct_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 := IDENTIFIER '{' (record_pattern_entry, ',')* '}'
record_pattern_entry := IDENTIFIER | IDENTIFIER ':' Pattern record_pattern_entry := IDENTIFIER | IDENTIFIER ':' Pattern
tuple_struct_pattern := IDENTIFIER '(' (pattern, ',')* ')' tuple_struct_pattern := IDENTIFIER '(' (pattern, ',')* ')'
@ -735,14 +736,12 @@ impl Parser {
_ => Pattern::Literal(PatternLiteral::VarPattern(id)) _ => 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::True) => Pattern::Literal(PatternLiteral::BoolPattern(true)),
Keyword(Kw::False) => Pattern::Literal(PatternLiteral::BoolPattern(false)), Keyword(Kw::False) => Pattern::Literal(PatternLiteral::BoolPattern(false)),
StrLiteral(s) => Pattern::Literal(PatternLiteral::StringPattern(s)), StrLiteral(s) => Pattern::Literal(PatternLiteral::StringPattern(s)),
DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => { DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => self.signed_number_literal()?,
//TODO handle negatives Operator(ref op) if **op == "-" => self.signed_number_literal()?,
let Expression(expr_type, _) = self.number_literal()?;
Pattern::Literal(PatternLiteral::NumPattern(expr_type))
},
Underscore => { Underscore => {
self.next(); self.next();
Pattern::Ignored 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)> { parse_method!(record_pattern_entry(&mut self) -> ParseResult<(Rc<String>, Pattern)> {
let name = self.identifier()?; let name = self.identifier()?;
Ok(match self.peek() { 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, item: then_clause,
} }
}, },
_ => panic!() e => { println!("SAW {:?}", e); panic!() }
}; };
let alternatives = vec![ let alternatives = vec![
@ -196,7 +196,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
Guard::Pat(ref p) => match p { Guard::Pat(ref p) => match p {
Pattern::Ignored => (None, vec![]), Pattern::Ignored => (None, vec![]),
Pattern::Literal(lit) => match lit { Pattern::Literal(lit) => match lit {
PatternLiteral::NumPattern(_expr) => unimplemented!(), PatternLiteral::NumPattern { neg, num } => unimplemented!(),
PatternLiteral::StringPattern(_s) => unimplemented!(), PatternLiteral::StringPattern(_s) => unimplemented!(),
PatternLiteral::BoolPattern(_b) => unimplemented!(), PatternLiteral::BoolPattern(_b) => unimplemented!(),
PatternLiteral::VarPattern(_var) => unimplemented!(), PatternLiteral::VarPattern(_var) => unimplemented!(),