nanvm_lib/parser/
any_state.rs

1use super::{
2    json_state::JsonState,
3    shared::{
4        to_js_string, DataType, JsonElement, JsonStackElement, JsonStackObject, ParseError,
5        ParseResult, ParsingStatus,
6    },
7};
8use crate::{
9    common::{cast::Cast, default::default},
10    js::{any::Any, js_array::new_array, js_object::new_object},
11    mem::manager::Manager,
12    tokenizer::JsonToken,
13};
14use std::collections::BTreeMap;
15
16pub struct AnySuccess<M: Manager> {
17    pub state: AnyState<M>,
18    pub value: Any<M::Dealloc>,
19}
20
21pub enum AnyResult<M: Manager> {
22    Continue(AnyState<M>),
23    Success(AnySuccess<M>),
24    Error(ParseError),
25}
26
27pub struct AnyState<M: Manager> {
28    pub data_type: DataType,
29    pub status: ParsingStatus,
30    pub current: JsonElement<M::Dealloc>,
31    pub stack: Vec<JsonStackElement<M::Dealloc>>,
32    pub consts: BTreeMap<String, Any<M::Dealloc>>,
33}
34
35impl<M: Manager> Default for AnyState<M> {
36    fn default() -> Self {
37        AnyState {
38            data_type: default(),
39            status: ParsingStatus::Initial,
40            current: JsonElement::None,
41            stack: [].cast(),
42            consts: default(),
43        }
44    }
45}
46
47// AnyState methods that use Dealloc only - methods that use Manager are in AnyStateExtension.
48impl<M: Manager> AnyState<M> {
49    pub fn set_djs(self) -> Self {
50        AnyState {
51            data_type: DataType::Djs,
52            ..self
53        }
54    }
55
56    pub fn set_mjs(self) -> Self {
57        AnyState {
58            data_type: DataType::Mjs,
59            ..self
60        }
61    }
62
63    pub fn set_cjs(self) -> Self {
64        AnyState {
65            data_type: DataType::Cjs,
66            ..self
67        }
68    }
69
70    pub fn parse(
71        self,
72        manager: M,
73        token: JsonToken<M::Dealloc>,
74    ) -> (
75        /*any_result:*/ AnyResult<M>,
76        /*module_name:*/ Option<String>,
77    ) {
78        match self.status {
79            ParsingStatus::Initial | ParsingStatus::ObjectColon => {
80                (self.parse_value(manager, token), None)
81            }
82            ParsingStatus::ArrayBegin => (self.parse_array_begin(manager, token), None),
83            ParsingStatus::ArrayValue => (self.parse_array_value(manager, token), None),
84            ParsingStatus::ArrayComma => (self.parse_array_comma(manager, token), None),
85            ParsingStatus::ObjectBegin => (self.parse_object_begin(manager, token), None),
86            ParsingStatus::ObjectKey => (self.parse_object_key(token), None),
87            ParsingStatus::ObjectValue => (self.parse_object_next(manager, token), None),
88            ParsingStatus::ObjectComma => (self.parse_object_comma(manager, token), None),
89            ParsingStatus::ImportBegin => (self.parse_import_begin(token), None),
90            ParsingStatus::ImportValue => self.parse_import_value(token),
91            ParsingStatus::ImportEnd => (self.parse_import_end(token), None),
92        }
93    }
94
95    pub fn parse_for_module(
96        self,
97        manager: M,
98        token: JsonToken<M::Dealloc>,
99    ) -> (
100        /*json_state:*/ JsonState<M>,
101        /*module_name:*/ Option<String>,
102    ) {
103        let (any_result, module_name) = self.parse(manager, token);
104        match module_name {
105            Some(module_name) => {
106                if let AnyResult::Continue(state) = any_result {
107                    (JsonState::ParseModule(state), Some(module_name))
108                } else {
109                    panic!("Import path should be returned only with Continue result");
110                }
111            }
112            None => match any_result {
113                AnyResult::Continue(state) => (JsonState::ParseModule(state), None),
114                AnyResult::Success(success) => (
115                    JsonState::Result(ParseResult {
116                        data_type: success.state.data_type,
117                        any: success.value,
118                    }),
119                    None,
120                ),
121                AnyResult::Error(error) => (JsonState::Error(error), None),
122            },
123        }
124    }
125
126    pub fn parse_import_begin(self, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
127        match token {
128            JsonToken::OpeningParenthesis => AnyResult::Continue(AnyState {
129                status: ParsingStatus::ImportValue,
130                ..self
131            }),
132            _ => AnyResult::Error(ParseError::WrongRequireStatement),
133        }
134    }
135
136    pub fn parse_import_end(self, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
137        match token {
138            JsonToken::ClosingParenthesis => self.end_import(),
139            _ => AnyResult::Error(ParseError::WrongRequireStatement),
140        }
141    }
142
143    fn parse_import_value(
144        self,
145        token: JsonToken<M::Dealloc>,
146    ) -> (
147        /*any_result:*/ AnyResult<M>,
148        /*module_name:*/ Option<String>,
149    ) {
150        match token {
151            JsonToken::String(s) => (
152                AnyResult::Continue(AnyState {
153                    status: ParsingStatus::ImportEnd,
154                    ..self
155                }),
156                Some(s),
157            ),
158            _ => (AnyResult::Error(ParseError::WrongRequireStatement), None),
159        }
160    }
161
162    pub fn begin_import(mut self) -> AnyResult<M> {
163        if let JsonElement::Stack(top) = self.current {
164            self.stack.push(top);
165        }
166        AnyResult::Continue(AnyState {
167            data_type: DataType::Cjs,
168            status: ParsingStatus::ImportBegin,
169            current: JsonElement::None,
170            ..self
171        })
172    }
173
174    pub fn end_import(mut self) -> AnyResult<M> {
175        match self.current {
176            JsonElement::Any(any) => {
177                let current = match self.stack.pop() {
178                    Some(element) => JsonElement::Stack(element),
179                    None => JsonElement::None,
180                };
181                let new_state = AnyState {
182                    status: ParsingStatus::Initial,
183                    current,
184                    ..self
185                };
186                new_state.push_value(any)
187            }
188            _ => unreachable!(),
189        }
190    }
191
192    pub fn parse_value(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
193        match token {
194            JsonToken::ArrayBegin => self.begin_array(),
195            JsonToken::ObjectBegin => self.begin_object(),
196            JsonToken::Id(s) if self.data_type.is_cjs_compatible() && s == "require" => {
197                self.begin_import()
198            }
199            _ => {
200                let option_any = token.try_to_any(manager, &self.consts);
201                match option_any {
202                    Some(any) => self.push_value(any),
203                    None => AnyResult::Error(ParseError::UnexpectedToken),
204                }
205            }
206        }
207    }
208
209    pub fn push_value(self, value: Any<M::Dealloc>) -> AnyResult<M> {
210        match self.current {
211            JsonElement::None => AnyResult::Success(AnySuccess {
212                state: AnyState {
213                    status: ParsingStatus::Initial,
214                    ..self
215                },
216                value,
217            }),
218            JsonElement::Stack(top) => match top {
219                JsonStackElement::Array(mut arr) => {
220                    arr.push(value);
221                    AnyResult::Continue(AnyState {
222                        status: ParsingStatus::ArrayValue,
223                        current: JsonElement::Stack(JsonStackElement::Array(arr)),
224                        ..self
225                    })
226                }
227                JsonStackElement::Object(mut stack_obj) => {
228                    stack_obj.map.insert(stack_obj.key, value);
229                    let new_stack_obj = JsonStackObject {
230                        map: stack_obj.map,
231                        key: String::default(),
232                    };
233                    AnyResult::Continue(AnyState {
234                        status: ParsingStatus::ObjectValue,
235                        current: JsonElement::Stack(JsonStackElement::Object(new_stack_obj)),
236                        ..self
237                    })
238                }
239            },
240            _ => todo!(),
241        }
242    }
243
244    pub fn push_key(self, s: String) -> AnyResult<M> {
245        match self.current {
246            JsonElement::Stack(JsonStackElement::Object(stack_obj)) => {
247                let new_stack_obj = JsonStackObject {
248                    map: stack_obj.map,
249                    key: s,
250                };
251                AnyResult::Continue(AnyState {
252                    status: ParsingStatus::ObjectKey,
253                    current: JsonElement::Stack(JsonStackElement::Object(new_stack_obj)),
254                    ..self
255                })
256            }
257            _ => AnyResult::Error(ParseError::UnexpectedToken),
258        }
259    }
260
261    pub fn parse_array_comma(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
262        match token {
263            JsonToken::ArrayBegin => self.begin_array(),
264            JsonToken::ObjectBegin => self.begin_object(),
265            JsonToken::Id(s) if self.data_type == DataType::Cjs && s == "require" => {
266                self.begin_import()
267            }
268            JsonToken::ArrayEnd => self.end_array(manager),
269            _ => {
270                let option_any = token.try_to_any(manager, &self.consts);
271                match option_any {
272                    Some(any) => self.push_value(any),
273                    None => AnyResult::Error(ParseError::UnexpectedToken),
274                }
275            }
276        }
277    }
278
279    pub fn parse_array_begin(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
280        match token {
281            JsonToken::ArrayBegin => self.begin_array(),
282            JsonToken::ArrayEnd => self.end_array(manager),
283            JsonToken::ObjectBegin => self.begin_object(),
284            _ => {
285                let option_any = token.try_to_any(manager, &self.consts);
286                match option_any {
287                    Some(any) => self.push_value(any),
288                    None => AnyResult::Error(ParseError::UnexpectedToken),
289                }
290            }
291        }
292    }
293
294    pub fn parse_array_value(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
295        match token {
296            JsonToken::ArrayEnd => self.end_array(manager),
297            JsonToken::Comma => AnyResult::Continue(AnyState {
298                status: ParsingStatus::ArrayComma,
299                ..self
300            }),
301            _ => AnyResult::Error(ParseError::UnexpectedToken),
302        }
303    }
304
305    pub fn begin_array(mut self) -> AnyResult<M> {
306        let new_top = JsonStackElement::Array(Vec::default());
307        if let JsonElement::Stack(top) = self.current {
308            self.stack.push(top);
309        }
310        AnyResult::Continue(AnyState {
311            status: ParsingStatus::ArrayBegin,
312            current: JsonElement::Stack(new_top),
313            ..self
314        })
315    }
316
317    pub fn end_array(mut self, manager: M) -> AnyResult<M> {
318        match self.current {
319            JsonElement::Stack(JsonStackElement::Array(array)) => {
320                let js_array = new_array(manager, array).to_ref();
321                let current = match self.stack.pop() {
322                    Some(element) => JsonElement::Stack(element),
323                    None => JsonElement::None,
324                };
325                let new_state = AnyState { current, ..self };
326                new_state.push_value(Any::move_from(js_array))
327            }
328            _ => unreachable!(),
329        }
330    }
331
332    pub fn parse_object_begin(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
333        match token {
334            JsonToken::String(s) => self.push_key(s),
335            JsonToken::Id(s) if self.data_type.is_djs() => self.push_key(s),
336            JsonToken::ObjectEnd => self.end_object(manager),
337            _ => AnyResult::Error(ParseError::UnexpectedToken),
338        }
339    }
340
341    pub fn parse_object_next(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
342        match token {
343            JsonToken::ObjectEnd => self.end_object(manager),
344            JsonToken::Comma => AnyResult::Continue(AnyState {
345                status: ParsingStatus::ObjectComma,
346                ..self
347            }),
348            _ => AnyResult::Error(ParseError::UnexpectedToken),
349        }
350    }
351
352    pub fn parse_object_comma(self, manager: M, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
353        match token {
354            JsonToken::String(s) => self.push_key(s),
355            JsonToken::ObjectEnd => self.end_object(manager),
356            _ => AnyResult::Error(ParseError::UnexpectedToken),
357        }
358    }
359
360    pub fn parse_object_key(self, token: JsonToken<M::Dealloc>) -> AnyResult<M> {
361        match token {
362            JsonToken::Colon => AnyResult::Continue(AnyState {
363                status: ParsingStatus::ObjectColon,
364                ..self
365            }),
366            _ => AnyResult::Error(ParseError::UnexpectedToken),
367        }
368    }
369
370    pub fn begin_object(mut self) -> AnyResult<M> {
371        let new_top: JsonStackElement<M::Dealloc> = JsonStackElement::Object(JsonStackObject {
372            map: BTreeMap::default(),
373            key: String::default(),
374        });
375        if let JsonElement::Stack(top) = self.current {
376            self.stack.push(top)
377        }
378        AnyResult::Continue(AnyState {
379            status: ParsingStatus::ObjectBegin,
380            current: JsonElement::Stack(new_top),
381            ..self
382        })
383    }
384
385    pub fn end_object(mut self, manager: M) -> AnyResult<M> {
386        match self.current {
387            JsonElement::Stack(JsonStackElement::Object(object)) => {
388                let vec = object
389                    .map
390                    .into_iter()
391                    .map(|kv| (to_js_string(manager, kv.0), kv.1))
392                    .collect::<Vec<_>>();
393                let js_object = new_object(manager, vec).to_ref();
394                let current = match self.stack.pop() {
395                    Some(element) => JsonElement::Stack(element),
396                    None => JsonElement::None,
397                };
398                let new_state = AnyState { current, ..self };
399                new_state.push_value(Any::move_from(js_object))
400            }
401            _ => unreachable!(),
402        }
403    }
404}