oom/
state.rs

1use std::collections::{BTreeMap, VecDeque};
2use std::fmt::{Debug, Display};
3use std::ops::Range;
4
5use unique_pointer::UniquePointer;
6
7use crate::{
8    with_caller, Error, Match, Matcher, Position, Production, Result, Special, Stack, Token,
9    Traceback,
10};
11
12pub const DEFAULT_WHITESPACE: &'static str = " \t";
13pub const DEFAULT_NEWLINE: &'static str = "\n";
14
15#[derive(Debug)]
16pub struct State {
17    input: Vec<char>,
18    in_newline: bool,
19    tokens: VecDeque<Token>,
20    in_whitespace: bool,
21    buffer: String,
22    window: String,
23    length: usize,
24    line: usize,
25    column: usize,
26    stack: Stack,
27    index: usize,
28    production_index: usize,
29    whitespace: String,
30    newline: String,
31    productions: BTreeMap<String, Production>,
32}
33impl Default for State {
34    fn default() -> State {
35        State {
36            input: Vec::new(),
37            in_newline: false,
38            tokens: VecDeque::new(),
39            in_whitespace: false,
40            buffer: String::new(),
41            window: String::new(),
42            length: 0,
43            index: 0,
44            production_index: 0,
45            line: 1,
46            column: 1,
47            stack: Stack::new(),
48            whitespace: DEFAULT_WHITESPACE.to_string(),
49            newline: DEFAULT_NEWLINE.to_string(),
50            productions: BTreeMap::new(),
51        }
52    }
53}
54impl State {
55    pub fn with_length(length: usize) -> State {
56        let mut state = State::default();
57        state.length = length;
58        state
59    }
60
61    pub fn register_matcher<T: Display>(&mut self, name: T, matcher: Production) -> Result<()> {
62        let name = name.to_string();
63        if self.productions.contains_key(&name) {
64            return Err(with_caller!(Error::new(format!(
65                "matcher {:#?} already registered to {:#?}",
66                &name, &matcher
67            ))));
68        }
69        self.productions.insert(name, matcher);
70        Ok(())
71    }
72
73    pub fn index(&self) -> usize {
74        self.index
75    }
76
77    pub fn length(&self) -> usize {
78        self.length
79    }
80
81    pub fn stack(&mut self) -> &mut Stack {
82        self.stack.as_mut()
83    }
84
85    pub fn tokens(&self) -> VecDeque<Token> {
86        self.tokens.clone()
87    }
88
89    pub fn is_epsilon<T: Display + Debug>(&self, input: T) -> bool {
90        self.is_whitespace(input.to_string()) || self.is_newline(input.to_string())
91    }
92
93    pub fn has_epsilon<T: Display + Debug>(&self, input: T) -> bool {
94        self.has_whitespace(input.to_string()) || self.has_newline(input.to_string())
95    }
96
97    pub fn is_whitespace<T: Display + Debug>(&self, input: T) -> bool {
98        self.whitespace.to_string() == input.to_string()
99            || self.whitespace.contains(&input.to_string())
100    }
101
102    pub fn has_whitespace<T: Display + Debug>(&self, input: T) -> bool {
103        let input = input.to_string();
104        for wc in self.whitespace.chars() {
105            if input.contains(wc) {
106                return true;
107            }
108        }
109        false
110    }
111
112    pub fn is_newline<T: Display + Debug>(&self, input: T) -> bool {
113        self.newline.to_string() == input.to_string() || self.newline.contains(&input.to_string())
114    }
115
116    pub fn has_newline<T: Display + Debug>(&self, input: T) -> bool {
117        let input = input.to_string();
118        for wc in self.newline.chars() {
119            if input.contains(wc) {
120                return true;
121            }
122        }
123        false
124    }
125
126    pub fn as_mut<'c>(&self) -> &'c mut State {
127        UniquePointer::read_only(self).extend_lifetime_mut()
128    }
129
130    pub fn position(&self) -> Position {
131        Position::new(self.line, self.column)
132    }
133
134    pub fn matcher<T: Display>(&self, name: T) -> Result<Production> {
135        let name = name.to_string();
136        if let Some(matcher) = self.productions.get(&name) {
137            Ok(matcher.clone())
138        } else {
139            Err(with_caller!(Error::new(format!(
140                "no matcher registered with name {:#?}",
141                &name
142            ))))
143        }
144    }
145}