expression/
expression.rs

1use noa_parser::acceptor::Acceptor;
2use noa_parser::bytes::components::groups::GroupKind;
3use noa_parser::bytes::matchers::match_pattern;
4use noa_parser::bytes::primitives::number::Number;
5use noa_parser::bytes::primitives::whitespace::OptionalWhitespaces;
6use noa_parser::errors::{ParseError, ParseResult};
7use noa_parser::matcher::{Match, MatchSize};
8use noa_parser::peek::peek;
9use noa_parser::recognizer::{Recognizable, Recognizer};
10use noa_parser::scanner::Scanner;
11use noa_parser::visitor::Visitor;
12
13// ------------------------------------------------------------
14// ExpressionInternal
15// ------------------------------------------------------------
16
17#[allow(dead_code)]
18#[derive(Debug)]
19enum ExpressionInternal {
20    Reducted(Reducted),
21    RightExpression(RightExpression),
22}
23
24// ------------------------------------------------------------
25
26#[derive(Debug)]
27struct Reducted {
28    lhs: usize,
29    op: BinaryOperator,
30    rhs: usize,
31}
32
33impl<'a> Visitor<'a, u8> for Reducted {
34    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
35        OptionalWhitespaces::accept(scanner)?;
36        let lhs = Number::accept(scanner)?.0;
37        OptionalWhitespaces::accept(scanner)?;
38        let op = Recognizer::<u8, BinaryOperator>::new(scanner)
39            .try_or(BinaryOperator::Add)?
40            .try_or(BinaryOperator::Mul)?
41            .finish()
42            .ok_or(ParseError::UnexpectedToken)?;
43        OptionalWhitespaces::accept(scanner)?;
44        let rhs = Number::accept(scanner)?.0;
45        OptionalWhitespaces::accept(scanner)?;
46        Ok(Reducted { lhs, op, rhs })
47    }
48}
49
50// ------------------------------------------------------------
51//  +++ RightExpression
52// ------------------------------------------------------------
53
54#[derive(Debug)]
55struct RightExpression {
56    lhs: usize,
57    op: BinaryOperator,
58    rhs: Box<Expression>,
59}
60
61impl<'a> Visitor<'a, u8> for RightExpression {
62    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
63        OptionalWhitespaces::accept(scanner)?;
64        let lhs = Number::accept(scanner)?.0;
65        OptionalWhitespaces::accept(scanner)?;
66        let op = Recognizer::<u8, BinaryOperator>::new(scanner)
67            .try_or(BinaryOperator::Add)?
68            .try_or(BinaryOperator::Mul)?
69            .finish()
70            .ok_or(ParseError::UnexpectedToken)?;
71        OptionalWhitespaces::accept(scanner)?;
72        let rhs = Expression::accept(scanner)?;
73        OptionalWhitespaces::accept(scanner)?;
74        Ok(RightExpression {
75            lhs,
76            op,
77            rhs: Box::new(rhs),
78        })
79    }
80}
81
82// ------------------------------------------------------------
83// BinaryOperator
84// ------------------------------------------------------------
85
86#[derive(Debug)]
87enum BinaryOperator {
88    Add,
89    Mul,
90}
91
92impl Match<u8> for BinaryOperator {
93    fn matcher(&self, data: &[u8]) -> (bool, usize) {
94        match self {
95            BinaryOperator::Add => match_pattern(b"+", data),
96            BinaryOperator::Mul => match_pattern(b"*", data),
97        }
98    }
99}
100
101impl MatchSize for BinaryOperator {
102    fn size(&self) -> usize {
103        match self {
104            BinaryOperator::Add => 1,
105            BinaryOperator::Mul => 1,
106        }
107    }
108}
109
110impl<'a> Recognizable<'a, u8, BinaryOperator> for BinaryOperator {
111    fn recognize(self, scanner: &mut Scanner<'a, u8>) -> ParseResult<Option<BinaryOperator>> {
112        if scanner.is_empty() {
113            return Ok(None);
114        }
115        let (matched, size) = self.matcher(scanner.remaining());
116        if matched {
117            scanner.bump_by(size);
118            return Ok(Some(self));
119        }
120        Ok(None)
121    }
122}
123
124// ------------------------------------------------------------
125// Expression
126// ------------------------------------------------------------
127
128/// Final result of the expression.
129#[allow(dead_code)]
130#[derive(Debug)]
131enum Expression {
132    /// Both lhs and rhs are reduced.
133    Reduced {
134        lhs: usize,
135        op: BinaryOperator,
136        rhs: usize,
137    },
138    /// Only lhs is reduced.
139    RightExpression {
140        lhs: usize,
141        op: BinaryOperator,
142        rhs: Box<Expression>,
143    },
144}
145
146impl From<ExpressionInternal> for Expression {
147    fn from(value: ExpressionInternal) -> Self {
148        match value {
149            ExpressionInternal::Reducted(reduced) => Expression::Reduced {
150                lhs: reduced.lhs,
151                op: reduced.op,
152                rhs: reduced.rhs,
153            },
154            ExpressionInternal::RightExpression(right) => Expression::RightExpression {
155                lhs: right.lhs,
156                op: right.op,
157                rhs: right.rhs,
158            },
159        }
160    }
161}
162
163impl<'a> Visitor<'a, u8> for Expression {
164    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
165        OptionalWhitespaces::accept(scanner)?;
166        // Check if there is a parenthesis
167        let result = peek(GroupKind::Parenthesis, scanner)?;
168
169        match result {
170            Some(peeked) => {
171                // Parse the inner expression
172                let mut inner_scanner = Scanner::new(peeked.peeked_slice());
173                let inner_result = Expression::accept(&mut inner_scanner)?;
174                scanner.bump_by(peeked.end_slice);
175                Ok(inner_result)
176            }
177            None => {
178                // Parse the reduced expression or the right expression
179                let accepted = Acceptor::new(scanner)
180                    .try_or(ExpressionInternal::RightExpression)?
181                    .try_or(ExpressionInternal::Reducted)?
182                    .finish()
183                    .ok_or(ParseError::UnexpectedToken)?;
184
185                Ok(accepted.into())
186            }
187        }
188    }
189}
190
191fn main() {
192    let data = b"1 + 2";
193    let mut scanner = Scanner::new(data);
194    let result = Expression::accept(&mut scanner);
195    println!("{:?}", result); // Ok(Reduced { lhs: 1, op: Add, rhs: 2 })
196
197    let data = b"1 + (2 * 3)";
198    let mut scanner = Scanner::new(data);
199    let result = Expression::accept(&mut scanner);
200    println!("{:?}", result); // Ok(RightExpression { lhs: 1, op: Add, rhs: Reduced { lhs: 2, op: Mul, rhs: 3 } })
201
202    let data = b"1 + (2 * 3 * ( 7 + 8))";
203    let mut scanner = Scanner::new(data);
204    let result = Expression::accept(&mut scanner);
205    println!("{:?}", result); //Ok(RightExpression { lhs: 1, op: Add, rhs: RightExpression { lhs: 2, op: Mul, rhs: RightExpression { lhs: 3, op: Mul, rhs: Reduced { lhs: 7, op: Add, rhs: 8 } } } })
206
207    let data = b"1 + 2 + 3";
208    let mut scanner = Scanner::new(data);
209    let result = Expression::accept(&mut scanner);
210    println!("{:?}", result); // Ok(RightExpression { lhs: 1, op: Add, rhs: Reduced { lhs: 2, op: Add, rhs: 3 } })
211}