1use std::collections::{BTreeSet, HashMap};
2use std::hash::BuildHasherDefault;
3use std::rc::Rc;
4
5use crate::char_stream::{CharStream, TextInterval};
6use crate::int_stream::EOF;
7use crate::prediction::PredictionFxHasher;
8use crate::recognizer::{Recognizer, RecognizerData};
9use crate::token::{CommonToken, CommonTokenFactory, TokenFactory, TokenSourceError, TokenSpec};
10
11#[allow(clippy::disallowed_types)]
12type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<PredictionFxHasher>>;
13
14pub const SKIP: i32 = -3;
15pub const MORE: i32 = -2;
16pub const DEFAULT_MODE: i32 = 0;
17
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub struct LexerMode(pub i32);
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
28pub struct LexerCustomAction {
29 rule_index: i32,
30 action_index: i32,
31 position: usize,
32}
33
34impl LexerCustomAction {
35 pub const fn new(rule_index: i32, action_index: i32, position: usize) -> Self {
37 Self {
38 rule_index,
39 action_index,
40 position,
41 }
42 }
43
44 pub const fn rule_index(self) -> i32 {
46 self.rule_index
47 }
48
49 pub const fn action_index(self) -> i32 {
51 self.action_index
52 }
53
54 pub const fn position(self) -> usize {
56 self.position
57 }
58}
59
60#[derive(Clone, Copy, Debug, Eq, PartialEq)]
62pub struct LexerPredicate {
63 rule_index: usize,
64 pred_index: usize,
65 position: usize,
66}
67
68impl LexerPredicate {
69 pub const fn new(rule_index: usize, pred_index: usize, position: usize) -> Self {
71 Self {
72 rule_index,
73 pred_index,
74 position,
75 }
76 }
77
78 pub const fn rule_index(self) -> usize {
80 self.rule_index
81 }
82
83 pub const fn pred_index(self) -> usize {
85 self.pred_index
86 }
87
88 pub const fn position(self) -> usize {
90 self.position
91 }
92}
93
94pub trait Lexer: Recognizer {
95 fn mode(&self) -> i32;
96 fn set_mode(&mut self, mode: i32);
97 fn push_mode(&mut self, mode: i32);
98 fn pop_mode(&mut self) -> Option<i32>;
99}
100
101#[derive(Clone, Debug)]
102pub struct BaseLexer<I, F = CommonTokenFactory> {
103 input: I,
104 data: RecognizerData,
105 factory: F,
106 mode: i32,
107 mode_stack: Vec<i32>,
108 token_start: usize,
109 token_start_line: usize,
110 token_start_column: usize,
111 line: usize,
112 column: usize,
113 hit_eof: bool,
114 errors: Vec<TokenSourceError>,
115 lexer_dfa: LexerDfaTrace,
116}
117
118#[derive(Clone, Debug, Default)]
121struct LexerDfaTrace {
122 state_numbers: FxHashMap<LexerDfaKey, usize>,
123 accept_predictions: FxHashMap<usize, i32>,
124 edges: BTreeSet<LexerDfaEdge>,
125 cached_states: FxHashMap<usize, Rc<LexerDfaCachedState>>,
126 transitions: FxHashMap<(usize, i32), LexerDfaCachedTransition>,
127 mode_starts: FxHashMap<i32, usize>,
128}
129
130impl LexerDfaTrace {
131 fn new() -> Self {
132 Self {
133 state_numbers: FxHashMap::default(),
134 accept_predictions: FxHashMap::default(),
135 edges: BTreeSet::new(),
136 cached_states: FxHashMap::default(),
137 transitions: FxHashMap::default(),
138 mode_starts: FxHashMap::default(),
139 }
140 }
141}
142
143#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
145pub(crate) struct LexerDfaKey {
146 configs: Vec<LexerDfaConfigKey>,
147}
148
149impl LexerDfaKey {
150 pub(crate) fn new(mut configs: Vec<LexerDfaConfigKey>) -> Self {
151 configs.sort_unstable();
152 Self { configs }
153 }
154}
155
156#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
158pub(crate) struct LexerDfaConfigKey {
159 pub(crate) state: usize,
160 pub(crate) alt_rule_index: Option<usize>,
161 pub(crate) consumed_eof: bool,
162 pub(crate) passed_non_greedy: bool,
163 pub(crate) stack: Vec<usize>,
164 pub(crate) actions: Vec<LexerDfaActionKey>,
165}
166
167#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
168pub(crate) struct LexerDfaActionKey {
169 pub(crate) action_index: usize,
170 pub(crate) position_delta: usize,
171 pub(crate) rule_index: usize,
172}
173
174impl LexerDfaConfigKey {
175 pub(crate) const fn new(
176 state: usize,
177 alt_rule_index: Option<usize>,
178 consumed_eof: bool,
179 passed_non_greedy: bool,
180 stack: Vec<usize>,
181 actions: Vec<LexerDfaActionKey>,
182 ) -> Self {
183 Self {
184 state,
185 alt_rule_index,
186 consumed_eof,
187 passed_non_greedy,
188 stack,
189 actions,
190 }
191 }
192}
193
194#[derive(Clone, Debug)]
195pub(crate) struct LexerDfaCachedTransition {
196 pub(crate) target_state: usize,
197 pub(crate) position_delta: usize,
198}
199
200#[derive(Clone, Debug)]
201pub(crate) struct LexerDfaCachedAccept {
202 pub(crate) position_delta: usize,
203 pub(crate) rule_index: usize,
204 pub(crate) consumed_eof: bool,
205 pub(crate) actions: Vec<LexerDfaActionKey>,
206}
207
208#[derive(Clone, Debug)]
209pub(crate) struct LexerDfaCachedState {
210 pub(crate) has_semantic_context: bool,
211 pub(crate) configs: Vec<LexerDfaConfigKey>,
212 pub(crate) accept: Option<LexerDfaCachedAccept>,
213}
214
215#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
218struct LexerDfaEdge {
219 from: usize,
220 symbol: i32,
221 to: usize,
222}
223
224impl<I> BaseLexer<I>
225where
226 I: CharStream,
227{
228 pub fn new(input: I, data: RecognizerData) -> Self {
230 Self::with_factory(input, data, CommonTokenFactory)
231 }
232}
233
234impl<I, F> BaseLexer<I, F>
235where
236 I: CharStream,
237 F: TokenFactory,
238{
239 pub fn with_factory(input: I, data: RecognizerData, factory: F) -> Self {
241 Self {
242 input,
243 data,
244 factory,
245 mode: DEFAULT_MODE,
246 mode_stack: Vec::new(),
247 token_start: 0,
248 token_start_line: 1,
249 token_start_column: 0,
250 line: 1,
251 column: 0,
252 hit_eof: false,
253 errors: Vec::new(),
254 lexer_dfa: LexerDfaTrace::new(),
255 }
256 }
257
258 pub const fn input(&self) -> &I {
259 &self.input
260 }
261
262 pub const fn input_mut(&mut self) -> &mut I {
263 &mut self.input
264 }
265
266 pub fn begin_token(&mut self) {
269 self.token_start = self.input.index();
270 self.token_start_line = self.line;
271 self.token_start_column = self.column;
272 }
273
274 pub const fn token_start(&self) -> usize {
276 self.token_start
277 }
278
279 pub const fn token_start_line(&self) -> usize {
281 self.token_start_line
282 }
283
284 pub const fn token_start_column(&self) -> usize {
286 self.token_start_column
287 }
288
289 pub fn consume_char(&mut self) {
296 let la = self.input.la(1);
297 if la == EOF {
298 return;
299 }
300 self.input.consume();
301 if char::from_u32(la.cast_unsigned()) == Some('\n') {
302 self.line += 1;
303 self.column = 0;
304 } else {
305 self.column += 1;
306 }
307 }
308
309 pub fn reset_accept_position(&mut self, index: usize) {
316 let target = index.max(self.token_start);
317 self.input.seek(self.token_start);
318 self.line = self.token_start_line;
319 self.column = self.token_start_column;
320 while self.input.index() < target && self.input.la(1) != EOF {
321 self.consume_char();
322 }
323 }
324
325 pub fn emit(&self, token_type: i32, channel: i32, text: Option<String>) -> CommonToken {
333 let stop = self.input.index().checked_sub(1).unwrap_or(usize::MAX);
334 self.emit_with_stop(token_type, channel, stop, text)
335 }
336
337 pub fn emit_with_stop(
343 &self,
344 token_type: i32,
345 channel: i32,
346 stop: usize,
347 text: Option<String>,
348 ) -> CommonToken {
349 let text = text.or_else(|| {
350 if stop == usize::MAX {
351 Some("<EOF>".to_owned())
352 } else {
353 None
354 }
355 });
356 let source_text = if text.is_none() && stop != usize::MAX {
357 self.input
358 .text_source_interval(TextInterval::new(self.token_start, stop))
359 .and_then(|(input, start_byte, stop_byte)| {
360 Some(crate::token::TokenSourceText {
361 input,
362 start_byte: u32::try_from(start_byte).ok()?,
363 stop_byte: u32::try_from(stop_byte).ok()?,
364 })
365 })
366 } else {
367 None
368 };
369 let text = text.or_else(|| {
370 source_text
371 .is_none()
372 .then(|| self.input.text(TextInterval::new(self.token_start, stop)))
373 });
374 self.factory.create(TokenSpec {
375 token_type,
376 channel,
377 start: self.token_start,
378 stop,
379 line: self.token_start_line,
380 column: self.token_start_column,
381 text,
382 source_text,
383 source_name: self.input.source_name(),
384 })
385 }
386
387 pub fn token_text(&self) -> String {
390 self.token_text_until(self.input.index())
391 }
392
393 pub fn token_text_until(&self, stop_exclusive: usize) -> String {
401 if stop_exclusive <= self.token_start {
402 return String::new();
403 }
404 self.input
405 .text(TextInterval::new(self.token_start, stop_exclusive - 1))
406 }
407
408 pub fn column_at(&self, position: usize) -> usize {
411 let mut column = self.token_start_column;
412 if position <= self.token_start {
413 return column;
414 }
415 for ch in self
416 .input
417 .text(TextInterval::new(self.token_start, position - 1))
418 .chars()
419 {
420 if ch == '\n' {
421 column = 0;
422 } else {
423 column += 1;
424 }
425 }
426 column
427 }
428
429 pub fn eof_token(&self) -> CommonToken {
431 CommonToken::eof(
432 self.input.source_name(),
433 self.input.index(),
434 self.line,
435 self.column,
436 )
437 }
438}
439
440impl<I, F> Recognizer for BaseLexer<I, F>
441where
442 I: CharStream,
443 F: TokenFactory,
444{
445 fn data(&self) -> &RecognizerData {
446 &self.data
447 }
448
449 fn data_mut(&mut self) -> &mut RecognizerData {
450 &mut self.data
451 }
452}
453
454impl<I, F> Lexer for BaseLexer<I, F>
455where
456 I: CharStream,
457 F: TokenFactory,
458{
459 fn mode(&self) -> i32 {
460 self.mode
461 }
462
463 fn set_mode(&mut self, mode: i32) {
464 self.mode = mode;
465 }
466
467 fn push_mode(&mut self, mode: i32) {
468 self.mode_stack.push(self.mode);
469 self.mode = mode;
470 }
471
472 fn pop_mode(&mut self) -> Option<i32> {
473 let mode = self.mode_stack.pop()?;
474 self.mode = mode;
475 Some(mode)
476 }
477}
478
479impl<I, F> BaseLexer<I, F>
480where
481 I: CharStream,
482 F: TokenFactory,
483{
484 pub const fn line(&self) -> usize {
485 self.line
486 }
487
488 pub const fn column(&self) -> usize {
489 self.column
490 }
491
492 pub fn source_name(&self) -> &str {
493 self.input.source_name()
494 }
495
496 pub const fn hit_eof(&self) -> bool {
497 self.hit_eof
498 }
499
500 pub const fn set_hit_eof(&mut self, hit_eof: bool) {
501 self.hit_eof = hit_eof;
502 }
503
504 pub fn record_error(&mut self, line: usize, column: usize, message: impl Into<String>) {
507 self.errors
508 .push(TokenSourceError::new(line, column, message));
509 }
510
511 pub fn drain_errors(&mut self) -> Vec<TokenSourceError> {
513 std::mem::take(&mut self.errors)
514 }
515
516 pub(crate) fn lexer_dfa_state(
519 &mut self,
520 key: LexerDfaKey,
521 accept_prediction: Option<i32>,
522 ) -> usize {
523 let next = self.lexer_dfa.state_numbers.len();
524 let state = *self.lexer_dfa.state_numbers.entry(key).or_insert(next);
525 if let Some(prediction) = accept_prediction {
526 self.lexer_dfa.accept_predictions.insert(state, prediction);
527 }
528 state
529 }
530
531 pub fn record_lexer_dfa_edge(&mut self, from: usize, symbol: i32, to: usize) {
533 self.lexer_dfa
534 .edges
535 .insert(LexerDfaEdge { from, symbol, to });
536 }
537
538 pub(crate) fn cached_lexer_dfa_transition(
539 &self,
540 state: usize,
541 symbol: i32,
542 ) -> Option<LexerDfaCachedTransition> {
543 self.lexer_dfa.transitions.get(&(state, symbol)).cloned()
544 }
545
546 pub(crate) fn cache_lexer_dfa_transition(
547 &mut self,
548 state: usize,
549 symbol: i32,
550 transition: LexerDfaCachedTransition,
551 ) {
552 self.lexer_dfa
553 .transitions
554 .entry((state, symbol))
555 .or_insert(transition);
556 }
557
558 pub(crate) fn cached_lexer_dfa_state(&self, state: usize) -> Option<Rc<LexerDfaCachedState>> {
559 self.lexer_dfa.cached_states.get(&state).cloned()
560 }
561
562 pub(crate) fn cache_lexer_dfa_state(
563 &mut self,
564 state: usize,
565 cached_state: LexerDfaCachedState,
566 ) {
567 self.lexer_dfa
568 .cached_states
569 .entry(state)
570 .or_insert_with(|| Rc::new(cached_state));
571 }
572
573 pub(crate) fn cached_lexer_mode_start(&self, mode: i32) -> Option<usize> {
574 self.lexer_dfa.mode_starts.get(&mode).copied()
575 }
576
577 pub(crate) fn cache_lexer_mode_start(&mut self, mode: i32, state: usize) {
578 self.lexer_dfa.mode_starts.entry(mode).or_insert(state);
579 }
580
581 pub fn lexer_dfa_string(&self) -> String {
583 let mut out = String::new();
584 for edge in &self.lexer_dfa.edges {
585 let Some(label) = lexer_dfa_edge_label(edge.symbol) else {
586 continue;
587 };
588 out.push_str(&self.lexer_dfa_state_string(edge.from));
589 out.push('-');
590 out.push_str(&label);
591 out.push_str("->");
592 out.push_str(&self.lexer_dfa_state_string(edge.to));
593 out.push('\n');
594 }
595 out
596 }
597
598 fn lexer_dfa_state_string(&self, state: usize) -> String {
599 self.lexer_dfa.accept_predictions.get(&state).map_or_else(
600 || format!("s{state}"),
601 |prediction| format!(":s{state}=>{prediction}"),
602 )
603 }
604}
605
606fn lexer_dfa_edge_label(symbol: i32) -> Option<String> {
607 char::from_u32(symbol.cast_unsigned()).map(|ch| format!("'{ch}'"))
608}