addition/
addition.rs

1use noa_parser::bytes::matchers::match_number;
2use noa_parser::bytes::token::Token;
3use noa_parser::errors::ParseResult;
4use noa_parser::matcher::{Match, MatchSize};
5use noa_parser::recognizer::{Recognizable, recognize};
6use noa_parser::scanner::Scanner;
7use noa_parser::visitor::Visitor;
8
9/// The token number which recognizes numbers.
10struct TokenNumber;
11
12/// Implement the `Match` trait for the token number.
13impl Match<u8> for TokenNumber {
14    fn matcher(&self, data: &[u8]) -> (bool, usize) {
15        match_number(data)
16    }
17}
18
19/// Implement the `MatchSize` trait for the token number.
20impl MatchSize for TokenNumber {
21    fn size(&self) -> usize {
22        0
23    }
24}
25
26/// Define how to accept the token number.
27struct Number(usize);
28
29/// Implement the `Visitor` trait for the token number.
30impl Visitor<'_, u8> for Number {
31    fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
32        let raw_data = recognize(TokenNumber, scanner)?;
33        let str_data = std::str::from_utf8(raw_data)?;
34        let result = str_data.parse::<usize>()?;
35        Ok(Number(result))
36    }
37}
38
39/// Define the addition expression.
40#[derive(Debug)]
41#[allow(dead_code)]
42struct Addition {
43    rhs: usize,
44    lhs: usize,
45    result: usize,
46}
47
48/// Implement the `Visitor` trait for the addition expression.
49impl<'a> Visitor<'a, u8> for Addition {
50    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
51        // Parse the first number
52        let lhs = Number::accept(scanner)?.0;
53        // Expect a whitespace and a plus token then whitespace
54        Token::Whitespace.recognize(scanner)?;
55        Token::Plus.recognize(scanner)?;
56        Token::Whitespace.recognize(scanner)?;
57        // Parse the second number
58        let rhs = Number::accept(scanner)?.0;
59        // Expect a whitespace and an equal token then whitespace
60        Token::Whitespace.recognize(scanner)?;
61        Token::Equal.recognize(scanner)?;
62        Token::Whitespace.recognize(scanner)?;
63        // Parse the result number
64        let result = Number::accept(scanner)?.0;
65        // Return the addition
66        Ok(Addition { lhs, rhs, result })
67    }
68}
69
70fn main() {
71    let data = b"1 + 2 = 3";
72    let mut scanner = Scanner::new(data);
73    let result = Addition::accept(&mut scanner);
74    println!("{:?}", result);
75}