zen_parser/parser/
iter.rs

1use std::cell::Cell;
2use std::fmt::Debug;
3
4use bumpalo::Bump;
5use rust_decimal::Decimal;
6
7use crate::ast::Node;
8use crate::lexer::token::{Token, TokenKind};
9use crate::parser::error::{ParserError, ParserResult};
10
11type TokenValues<'a> = Option<&'a [&'a str]>;
12
13#[derive(Debug)]
14pub(crate) struct ParserIterator<'a, 'b> {
15    tokens: &'a Vec<Token<'a>>,
16    current: Cell<&'a Token<'a>>,
17    position: Cell<usize>,
18    bump: &'b Bump,
19    is_done: Cell<bool>,
20}
21
22impl<'a, 'b> ParserIterator<'a, 'b> {
23    pub fn try_new(tokens: &'a Vec<Token<'a>>, bump: &'b Bump) -> Result<Self, ParserError> {
24        let current = tokens.get(0).ok_or(ParserError::TokenOutOfBounds)?;
25
26        Ok(Self {
27            tokens,
28            bump,
29            current: Cell::new(current),
30            position: Cell::new(0),
31            is_done: Cell::new(false),
32        })
33    }
34
35    pub fn current(&self) -> &'a Token<'a> {
36        self.current.get()
37    }
38
39    pub fn is_done(&self) -> bool {
40        self.is_done.get()
41    }
42
43    pub fn next(&self) -> ParserResult<()> {
44        self.position.set(self.position.get() + 1);
45
46        if let Some(token) = self.tokens.get(self.position.get()) {
47            self.current.set(token);
48            Ok(())
49        } else {
50            if self.is_done.get() {
51                return Err(ParserError::TokenOutOfBounds);
52            }
53
54            self.is_done.set(true);
55            Ok(())
56        }
57    }
58
59    pub fn str_value(&self, str: &str) -> &'b str {
60        self.bump.alloc_str(str)
61    }
62
63    pub fn expect(&self, kind: TokenKind, values: TokenValues<'a>) -> Result<(), ParserError> {
64        self.token_cmp(kind, values)?;
65        self.next()?;
66        Ok(())
67    }
68
69    pub fn lookup(&self, dx: usize, kind: TokenKind, values: TokenValues<'a>) -> bool {
70        self.token_cmp_at_bool(self.position.get() + dx, kind, values)
71    }
72
73    pub fn lookup_back(&self, dx: usize, kind: TokenKind, values: TokenValues<'a>) -> bool {
74        if self.position.get() < dx {
75            return false;
76        }
77
78        self.token_cmp_at_bool(self.position.get() - dx, kind, values)
79    }
80
81    pub fn number(&self, token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
82        self.next()?;
83
84        let decimal =
85            Decimal::from_str_exact(token.value).map_err(|_| ParserError::FailedToParse {
86                message: format!("unknown float value: {:?}", token.value),
87            })?;
88
89        self.node(Node::Number(decimal))
90    }
91
92    pub fn string(&self, token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
93        self.next()?;
94        self.node(Node::String(self.bump.alloc_str(token.value)))
95    }
96
97    pub fn bool(&self, token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
98        match token.value {
99            "true" => self.node(Node::Bool(true)),
100            "false" => self.node(Node::Bool(false)),
101            _ => Err(ParserError::FailedToParse {
102                message: format!("unknown bool value: {:?}", token.value),
103            }),
104        }
105    }
106
107    pub fn null(&self, _token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
108        self.node(Node::Null)
109    }
110
111    pub fn node(&self, node: Node<'b>) -> Result<&'b Node<'b>, ParserError> {
112        Ok(self.bump.alloc(node))
113    }
114
115    fn token_cmp_at_bool(&self, index: usize, kind: TokenKind, values: TokenValues<'a>) -> bool {
116        return if let Some(token) = self.tokens.get(index) {
117            if token.kind != kind {
118                return false;
119            }
120
121            if let Some(vals) = values {
122                return vals.iter().any(|&c| c == token.value);
123            }
124
125            true
126        } else {
127            false
128        };
129    }
130
131    fn token_cmp_at(
132        &self,
133        index: usize,
134        kind: TokenKind,
135        values: TokenValues<'a>,
136    ) -> Result<(), ParserError> {
137        let token: &'a Token = self
138            .tokens
139            .get(index)
140            .ok_or(ParserError::TokenOutOfBounds)?;
141
142        if token.kind != kind {
143            return Err(ParserError::UnexpectedToken {
144                expected: format!("{kind:?} {values:?}"),
145                received: format!("{token:?}"),
146            });
147        }
148
149        if let Some(vals) = values {
150            if !vals.iter().any(|&c| c == token.value) {
151                return Err(ParserError::UnexpectedToken {
152                    expected: format!("{kind:?} {values:?}"),
153                    received: format!("{token:?}"),
154                });
155            }
156        }
157
158        Ok(())
159    }
160
161    fn token_cmp(&self, kind: TokenKind, values: TokenValues<'a>) -> Result<(), ParserError> {
162        self.token_cmp_at(self.position.get(), kind, values)
163    }
164}