zen_parser/parser/
iter.rs1use 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}