1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
extern crate peg;
use peg::parser;
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Expression {
Number(i64),
Sum(Box<Expression>, Box<Expression>),
Product(Box<Expression>, Box<Expression>),
}
parser!{
/// Doc comment
grammar arithmetic() for str {
/// Top level parser rule
/// This doc comment has multiple lines to test support for that as well
pub rule expression() -> Expression
= sum()
rule _ = [' ' | '\n']*
rule sum() -> Expression
= l:product() _ "+" _ r:product() { Expression::Sum(Box::new(l), Box::new(r)) }
/ product()
rule product() -> Expression
= l:atom() _ "*" _ r:atom() { Expression::Product(Box::new(l), Box::new(r)) }
/ atom()
rule atom() -> Expression
= number()
/ "(" _ v:sum() _ ")" { v }
rule number() -> Expression
= n:$(['0'..='9']+) { Expression::Number(n.parse().unwrap()) }
}}
fn main() {
assert_eq!(arithmetic::expression("1+1"), Ok(Expression::Sum(
Box::new(Expression::Number(1)),
Box::new(Expression::Number(1)))
));
assert_eq!(arithmetic::expression("5*5"), Ok(Expression::Product(
Box::new(Expression::Number(5)),
Box::new(Expression::Number(5)))
));
assert_eq!(arithmetic::expression("2+3*4"), Ok(Expression::Sum(
Box::new(Expression::Number(2)),
Box::new(Expression::Product(
Box::new(Expression::Number(3)),
Box::new(Expression::Number(4))
)),
)));
assert_eq!(arithmetic::expression("(2+3) * 4"), Ok(Expression::Product(
Box::new(Expression::Sum(
Box::new(Expression::Number(2)),
Box::new(Expression::Number(3)),
)),
Box::new(Expression::Number(4))
)));
assert!(arithmetic::expression("(22+)+1").is_err());
assert!(arithmetic::expression("1++1").is_err());
assert!(arithmetic::expression("3)+1").is_err());
}
|