lwb_parser/parser/peg/
parser_core.rs

1use crate::parser::peg::parse_error::PEGParseError;
2use crate::parser::peg::parse_result::ParseResult;
3use crate::parser::peg::parser_core_ast::{CoreAst, ParsePairRaw};
4use crate::sources::source_file::SourceFile;
5use std::collections::{HashMap, VecDeque};
6
7/// This stores the immutable data that is used during the parsing process.
8pub struct ParserContext<'src> {
9    pub(crate) file: &'src SourceFile,
10    pub(crate) ast: &'src CoreAst<'src>,
11    pub errors: HashMap<usize, usize>,
12}
13
14/// This stores the mutable data that is used during the parsing process.
15/// It contains a cache of the results of each (source position, rule).
16/// It also has a stack which contains information about the order in which the keys were inserted, so they can be removed in order when needed.
17pub struct ParserState<'src> {
18    pub(crate) cache: HashMap<(usize, &'src str), ParserCacheEntry<'src>>,
19    pub(crate) cache_stack: VecDeque<(usize, &'src str)>,
20    pub best_error: Option<PEGParseError>,
21    // True if layout should be allowed at the moment
22    pub allow_layout: bool,
23    // How many times no layout has been nested
24    pub no_layout_nest_count: usize,
25    // How many times no errors has been nested
26    pub no_errors_nest_count: usize,
27}
28
29/// A single entry in the cache. Contains the value, and a flag whether it has been read.
30pub struct ParserCacheEntry<'src> {
31    read: bool,
32    value: ParseResult<'src, ParsePairRaw>,
33}
34
35impl<'src> ParserState<'src> {
36    /// Get a mutable reference to an entry
37    pub fn get_mut(
38        &mut self,
39        key: &(usize, &'src str),
40    ) -> Option<&mut ParseResult<'src, ParsePairRaw>> {
41        if let Some(v) = self.cache.get_mut(key) {
42            v.read = true;
43            Some(&mut v.value)
44        } else {
45            None
46        }
47    }
48
49    /// Check if an entry has been read
50    pub fn is_read(&self, key: &(usize, &'src str)) -> Option<bool> {
51        self.cache.get(key).map(|v| v.read)
52    }
53
54    /// Insert a new entry into the cache
55    pub fn insert(&mut self, key: (usize, &'src str), value: ParseResult<'src, ParsePairRaw>) {
56        self.cache
57            .insert(key, ParserCacheEntry { read: false, value });
58        self.cache_stack.push_back(key);
59    }
60
61    /// Check how many items are currently in the stack
62    pub fn state_current(&self) -> usize {
63        self.cache_stack.len()
64    }
65
66    /// Remove all the items that were inserted after the given stack marker
67    pub fn state_revert(&mut self, state: usize) {
68        self.cache_stack.drain(state..).for_each(|key| {
69            self.cache.remove(&key);
70        })
71    }
72
73    pub fn add_error(&mut self, error: PEGParseError) {
74        if self.no_errors_nest_count > 0 {
75            return;
76        }
77        match self.best_error.take() {
78            Some(old_error) => self.best_error = Some(PEGParseError::combine(old_error, error)),
79            None => self.best_error = Some(error),
80        }
81    }
82}