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}