nanvm_lib/parser/
analyzer.rs

1use super::shared::DataType;
2use crate::ast::Module;
3use crate::common::default::default;
4use crate::mem::manager::{Dealloc, Manager};
5use crate::tokenizer::{create_transition_maps, JsonToken, TokenizerState, TransitionMaps};
6
7#[derive(Default)]
8pub struct AnalyzerParameters {
9    data_type: DataType,
10}
11
12#[derive(Default)]
13pub enum AnalyzerDiagnostic {
14    #[default]
15    OK,
16    // TODO: add error, warning diagnostics.
17}
18
19pub struct AnalyzerResults<D: Dealloc> {
20    pub module: Module<D>,
21    pub diagnostics: Vec<AnalyzerDiagnostic>,
22}
23
24pub struct AnalyzerState<M: Manager> {
25    parameters: AnalyzerParameters,
26    tokenizer_state: TokenizerState<M::Dealloc>,
27    tokenizer_maps: TransitionMaps<M>,
28    diagnostics_len: usize,
29    // TODO: add line number, column number tracking fields (needed for diagnostics).
30    module: Module<M::Dealloc>,
31    diagnostics: Vec<AnalyzerDiagnostic>,
32}
33
34impl<M: Manager + 'static> AnalyzerState<M> {
35    /// Creates a new analyzer staring state. The caller should check `diagnostics` for errors
36    /// immediately after creation (since `parameters` value can be inconsistent).
37    pub fn new(parameters: AnalyzerParameters) -> Self {
38        Self {
39            parameters,
40            tokenizer_state: default(),
41            tokenizer_maps: create_transition_maps(),
42            module: default(),
43            diagnostics: default(),
44            diagnostics_len: 0,
45        }
46    }
47
48    /// Updates analyzer state with a next input character; the result is the increment in the count
49    /// of `diagnostics`. It's up to the caller to check what was added at the end of `diagnostics`
50    ///  - are there any fatal errors, from the point of view of the current parsing session?
51    pub fn push_mut(&mut self, manager: M, c: char) -> usize {
52        for token in self
53            .tokenizer_state
54            .push_mut(manager, c, &self.tokenizer_maps)
55        {
56            self.process_token(token);
57        }
58        let prior_diagnostics_len = self.diagnostics_len;
59        self.diagnostics_len = self.diagnostics.len();
60        self.diagnostics_len - prior_diagnostics_len
61    }
62
63    /// Completes the analysis.
64    pub fn end(self) -> AnalyzerResults<M::Dealloc> {
65        // TODO: in case the current state is not a valid end state, add an error to self.diagnostics.
66        AnalyzerResults {
67            module: self.module,
68            diagnostics: self.diagnostics,
69        }
70    }
71
72    fn process_token(&mut self, _token: JsonToken<M::Dealloc>) {}
73}