1pub(crate) mod ascii_range;
11mod bypass;
12pub mod lexer;
13pub mod lexer_dfa;
14pub mod parser;
15pub mod parser_atn;
16pub mod serialized;
17
18#[derive(Clone, Copy)]
19struct TailCallSite {
20 start: usize,
21 stop: usize,
22 rule_index: usize,
23 state_count: usize,
24}
25
26#[derive(Default)]
27struct TailCallScratch {
28 marks: Vec<u8>,
29 work: Vec<(usize, bool)>,
30 successors: Vec<usize>,
31}
32
33fn plain_epsilon_tail_call<StateKind, StateRule, PushSuccessors>(
34 site: TailCallSite,
35 scratch: &mut TailCallScratch,
36 state_kind: StateKind,
37 state_rule_index: StateRule,
38 push_successors: PushSuccessors,
39) -> bool
40where
41 StateKind: Fn(usize) -> AtnStateKind,
42 StateRule: Fn(usize) -> Option<usize>,
43 PushSuccessors: Fn(usize, &mut Vec<usize>) -> bool,
44{
45 let TailCallSite {
46 start,
47 stop,
48 rule_index,
49 state_count,
50 } = site;
51 if start >= state_count
52 || stop >= state_count
53 || state_kind(stop) != AtnStateKind::RuleStop
54 || state_rule_index(stop) != Some(rule_index)
55 {
56 return false;
57 }
58
59 let TailCallScratch {
63 marks,
64 work,
65 successors,
66 } = scratch;
67 marks.clear();
68 marks.resize(state_count, 0);
69 work.clear();
70 work.push((start, false));
71 successors.clear();
72 while let Some((state, exiting)) = work.pop() {
73 if state == stop {
74 continue;
75 }
76 if state >= state_count {
77 return false;
78 }
79 if exiting {
80 marks[state] = 2;
81 continue;
82 }
83 match marks[state] {
84 1 => return false,
85 2 => continue,
86 _ => {}
87 }
88 if state_kind(state) == AtnStateKind::RuleStop
89 || state_rule_index(state) != Some(rule_index)
90 {
91 return false;
92 }
93 successors.clear();
94 if !push_successors(state, successors) || successors.is_empty() {
95 return false;
96 }
97 marks[state] = 1;
98 work.push((state, true));
99 work.extend(successors.iter().copied().map(|target| (target, false)));
100 }
101 true
102}
103
104#[derive(Clone, Debug, Eq, PartialEq)]
110pub struct LexerAtn {
111 max_token_type: i32,
112 states: Vec<LexerAtnState>,
113 rule_to_start_state: Vec<usize>,
114 rule_to_stop_state: Vec<usize>,
115 rule_to_token_type: Vec<i32>,
116 mode_to_start_state: Vec<usize>,
117 decision_to_state: Vec<usize>,
118 lexer_actions: Vec<LexerAction>,
119}
120
121impl LexerAtn {
122 pub const fn new(max_token_type: i32) -> Self {
125 Self {
126 max_token_type,
127 states: Vec::new(),
128 rule_to_start_state: Vec::new(),
129 rule_to_stop_state: Vec::new(),
130 rule_to_token_type: Vec::new(),
131 mode_to_start_state: Vec::new(),
132 decision_to_state: Vec::new(),
133 lexer_actions: Vec::new(),
134 }
135 }
136
137 pub const fn max_token_type(&self) -> i32 {
138 self.max_token_type
139 }
140
141 pub fn states(&self) -> &[LexerAtnState] {
142 &self.states
143 }
144
145 pub fn state(&self, state_number: usize) -> Option<&LexerAtnState> {
146 self.states.get(state_number)
147 }
148
149 pub fn state_mut(&mut self, state_number: usize) -> Option<&mut LexerAtnState> {
150 self.states.get_mut(state_number)
151 }
152
153 pub fn add_state(&mut self, state: LexerAtnState) -> usize {
156 let index = self.states.len();
157 self.states.push(state);
158 index
159 }
160
161 pub fn decision_to_state(&self) -> &[usize] {
162 &self.decision_to_state
163 }
164
165 pub fn add_decision_state(&mut self, state_number: usize) {
166 self.decision_to_state.push(state_number);
167 }
168
169 pub fn rule_to_start_state(&self) -> &[usize] {
170 &self.rule_to_start_state
171 }
172
173 pub fn set_rule_to_start_state(&mut self, rule_to_start_state: Vec<usize>) {
174 self.rule_to_start_state = rule_to_start_state;
175 }
176
177 pub fn rule_to_stop_state(&self) -> &[usize] {
178 &self.rule_to_stop_state
179 }
180
181 pub fn set_rule_to_stop_state(&mut self, rule_to_stop_state: Vec<usize>) {
182 self.rule_to_stop_state = rule_to_stop_state;
183 }
184
185 pub fn rule_to_token_type(&self) -> &[i32] {
186 &self.rule_to_token_type
187 }
188
189 pub fn set_rule_to_token_type(&mut self, rule_to_token_type: Vec<i32>) {
190 self.rule_to_token_type = rule_to_token_type;
191 }
192
193 pub fn mode_to_start_state(&self) -> &[usize] {
194 &self.mode_to_start_state
195 }
196
197 pub fn add_mode_start_state(&mut self, state_number: usize) {
198 self.mode_to_start_state.push(state_number);
199 }
200
201 pub fn lexer_actions(&self) -> &[LexerAction] {
202 &self.lexer_actions
203 }
204
205 pub fn set_lexer_actions(&mut self, lexer_actions: Vec<LexerAction>) {
206 self.lexer_actions = lexer_actions;
207 }
208
209 #[doc(hidden)]
216 pub fn identify_tail_calls(&mut self) {
217 let mut tail_calls = Vec::new();
218 let mut scratch = TailCallScratch::default();
219 for source in 0..self.states.len() {
220 for index in 0..self.states[source].transitions.len() {
221 let follow_state = match &self.states[source].transitions[index] {
222 LexerTransition::Rule { follow_state, .. } => *follow_state,
223 _ => continue,
224 };
225 tail_calls.push((
226 source,
227 index,
228 self.tail_call_follow_is_safe(source, follow_state, &mut scratch),
229 ));
230 }
231 }
232 for (source, index, tail_call) in tail_calls {
233 if let Some(LexerTransition::Rule {
234 tail_call: marker, ..
235 }) = self
236 .states
237 .get_mut(source)
238 .and_then(|state| state.transitions.get_mut(index))
239 {
240 *marker = tail_call;
241 }
242 }
243 }
244
245 fn tail_call_follow_is_safe(
246 &self,
247 source: usize,
248 start: usize,
249 scratch: &mut TailCallScratch,
250 ) -> bool {
251 let Some(rule_index) = self.states.get(source).and_then(|state| state.rule_index) else {
252 return false;
253 };
254 let Some(&stop) = self.rule_to_stop_state.get(rule_index) else {
255 return false;
256 };
257 plain_epsilon_tail_call(
258 TailCallSite {
259 start,
260 stop,
261 rule_index,
262 state_count: self.states.len(),
263 },
264 scratch,
265 |state| self.states[state].kind,
266 |state| self.states[state].rule_index,
267 |state, successors| {
268 for transition in &self.states[state].transitions {
269 let LexerTransition::Epsilon { target } = transition else {
270 return false;
271 };
272 successors.push(*target);
273 }
274 true
275 },
276 )
277 }
278}
279
280#[derive(Clone, Debug, Eq, PartialEq)]
287pub struct LexerAtnState {
288 pub state_number: usize,
289 pub rule_index: Option<usize>,
290 pub kind: AtnStateKind,
291 pub end_state: Option<usize>,
292 pub loop_back_state: Option<usize>,
293 pub non_greedy: bool,
294 pub precedence_rule_decision: bool,
295 pub left_recursive_rule: bool,
296 pub transitions: Vec<LexerTransition>,
297}
298
299impl LexerAtnState {
300 pub const fn new(state_number: usize, kind: AtnStateKind) -> Self {
302 Self {
303 state_number,
304 rule_index: None,
305 kind,
306 end_state: None,
307 loop_back_state: None,
308 non_greedy: false,
309 precedence_rule_decision: false,
310 left_recursive_rule: false,
311 transitions: Vec::new(),
312 }
313 }
314
315 #[must_use]
316 pub const fn with_rule_index(mut self, rule_index: usize) -> Self {
317 self.rule_index = Some(rule_index);
318 self
319 }
320
321 pub fn add_transition(&mut self, transition: LexerTransition) {
326 self.transitions.push(transition);
327 }
328
329 pub fn is_rule_stop(&self) -> bool {
330 self.kind == AtnStateKind::RuleStop
331 }
332}
333
334#[derive(Clone, Copy, Debug, Eq, PartialEq)]
336pub enum AtnStateKind {
337 Invalid,
338 Basic,
339 RuleStart,
340 BlockStart,
341 PlusBlockStart,
342 StarBlockStart,
343 TokenStart,
344 RuleStop,
345 BlockEnd,
346 StarLoopBack,
347 StarLoopEntry,
348 PlusLoopBack,
349 LoopEnd,
350}
351
352#[derive(Clone, Debug, Eq, PartialEq)]
358pub enum LexerTransition {
359 Epsilon {
360 target: usize,
361 },
362 Atom {
363 target: usize,
364 label: i32,
365 },
366 Range {
367 target: usize,
368 start: i32,
369 stop: i32,
370 },
371 Set {
372 target: usize,
373 set: IntervalSet,
374 },
375 NotSet {
376 target: usize,
377 set: IntervalSet,
378 },
379 Wildcard {
380 target: usize,
381 },
382 Rule {
383 target: usize,
384 rule_index: usize,
385 follow_state: usize,
386 precedence: i32,
387 tail_call: bool,
388 },
389 Predicate {
390 target: usize,
391 rule_index: usize,
392 pred_index: usize,
393 context_dependent: bool,
394 },
395 Action {
396 target: usize,
397 rule_index: usize,
398 action_index: Option<usize>,
399 context_dependent: bool,
400 },
401 Precedence {
402 target: usize,
403 precedence: i32,
404 },
405}
406
407impl LexerTransition {
408 pub const fn target(&self) -> usize {
410 match self {
411 Self::Epsilon { target }
412 | Self::Atom { target, .. }
413 | Self::Range { target, .. }
414 | Self::Set { target, .. }
415 | Self::NotSet { target, .. }
416 | Self::Wildcard { target }
417 | Self::Rule { target, .. }
418 | Self::Predicate { target, .. }
419 | Self::Action { target, .. }
420 | Self::Precedence { target, .. } => *target,
421 }
422 }
423
424 pub const fn is_epsilon(&self) -> bool {
426 matches!(
427 self,
428 Self::Epsilon { .. }
429 | Self::Rule { .. }
430 | Self::Predicate { .. }
431 | Self::Action { .. }
432 | Self::Precedence { .. }
433 )
434 }
435
436 pub const fn is_tail_call(&self) -> bool {
439 matches!(
440 self,
441 Self::Rule {
442 tail_call: true,
443 ..
444 }
445 )
446 }
447
448 pub fn matches(&self, symbol: i32, min_vocabulary: i32, max_vocabulary: i32) -> bool {
453 match self {
454 Self::Atom { label, .. } => *label == symbol,
455 Self::Range { start, stop, .. } => (*start..=*stop).contains(&symbol),
456 Self::Set { set, .. } => set.contains(symbol),
457 Self::NotSet { set, .. } => {
458 (min_vocabulary..=max_vocabulary).contains(&symbol) && !set.contains(symbol)
459 }
460 Self::Wildcard { .. } => (min_vocabulary..=max_vocabulary).contains(&symbol),
461 Self::Epsilon { .. }
462 | Self::Rule { .. }
463 | Self::Predicate { .. }
464 | Self::Action { .. }
465 | Self::Precedence { .. } => false,
466 }
467 }
468}
469
470#[derive(Clone, Debug, Default, Eq, PartialEq)]
475pub struct IntervalSet {
476 ranges: Vec<(i32, i32)>,
477}
478
479impl IntervalSet {
480 pub fn new() -> Self {
481 Self::default()
482 }
483
484 pub fn from_range(start: i32, stop: i32) -> Self {
485 let mut set = Self::new();
486 set.add_range(start, stop);
487 set
488 }
489
490 pub fn add(&mut self, value: i32) {
491 self.add_range(value, value);
492 }
493
494 pub fn add_range(&mut self, start: i32, stop: i32) {
497 let (start, stop) = if start <= stop {
498 (start, stop)
499 } else {
500 (stop, start)
501 };
502 self.ranges.push((start, stop));
503 self.normalize();
504 }
505
506 fn normalize(&mut self) {
508 self.ranges.sort_unstable();
509 let mut merged: Vec<(i32, i32)> = Vec::with_capacity(self.ranges.len());
510 for (start, stop) in self.ranges.drain(..) {
511 if let Some((_, last_stop)) = merged.last_mut() {
512 if start <= last_stop.saturating_add(1) {
513 *last_stop = (*last_stop).max(stop);
514 continue;
515 }
516 }
517 merged.push((start, stop));
518 }
519 self.ranges = merged;
520 }
521
522 pub fn contains(&self, value: i32) -> bool {
524 match self.ranges.binary_search_by(|(start, _)| start.cmp(&value)) {
531 Ok(_) => true,
532 Err(pos) => pos > 0 && self.ranges[pos - 1].1 >= value,
533 }
534 }
535
536 pub fn ranges(&self) -> &[(i32, i32)] {
537 &self.ranges
538 }
539
540 pub const fn is_empty(&self) -> bool {
541 self.ranges.is_empty()
542 }
543}
544
545#[derive(Clone, Debug, Eq, PartialEq)]
552pub enum LexerAction {
553 Channel(i32),
554 Custom { rule_index: i32, action_index: i32 },
555 Mode(i32),
556 More,
557 PopMode,
558 PushMode(i32),
559 Skip,
560 Type(i32),
561}
562
563#[cfg(test)]
564mod tests {
565 use super::*;
566
567 fn classified_lexer_rule(continuations: Vec<(usize, LexerTransition)>) -> LexerAtn {
568 let mut atn = LexerAtn::new(4);
569 for (kind, rule_index) in [
570 (AtnStateKind::RuleStart, 0),
571 (AtnStateKind::Basic, 0),
572 (AtnStateKind::Basic, 0),
573 (AtnStateKind::RuleStop, 0),
574 (AtnStateKind::RuleStart, 1),
575 (AtnStateKind::RuleStop, 1),
576 (AtnStateKind::RuleStart, 2),
577 (AtnStateKind::RuleStop, 2),
578 (AtnStateKind::Basic, 0),
579 (AtnStateKind::Basic, 0),
580 ] {
581 let state_number = atn.states.len();
582 atn.add_state(LexerAtnState::new(state_number, kind).with_rule_index(rule_index));
583 }
584 atn.set_rule_to_start_state(vec![0, 4, 6]);
585 atn.set_rule_to_stop_state(vec![3, 5, 7]);
586 atn.state_mut(0)
587 .expect("caller start")
588 .add_transition(LexerTransition::Epsilon { target: 1 });
589 atn.state_mut(1)
590 .expect("call source")
591 .add_transition(LexerTransition::Rule {
592 target: 4,
593 rule_index: 1,
594 follow_state: 2,
595 precedence: 0,
596 tail_call: false,
597 });
598 atn.state_mut(4)
599 .expect("callee start")
600 .add_transition(LexerTransition::Epsilon { target: 5 });
601 atn.state_mut(6)
602 .expect("other rule start")
603 .add_transition(LexerTransition::Epsilon { target: 7 });
604 for (source, transition) in continuations {
605 atn.state_mut(source)
606 .expect("continuation source")
607 .add_transition(transition);
608 }
609 atn.identify_tail_calls();
610 atn
611 }
612
613 fn classified_lexer_call(atn: &LexerAtn) -> &LexerTransition {
614 &atn.state(1).expect("call source").transitions[0]
615 }
616
617 #[test]
618 fn lexer_tail_call_classifier_is_conservative() {
619 let positive = classified_lexer_rule(vec![
620 (2, LexerTransition::Epsilon { target: 8 }),
621 (8, LexerTransition::Epsilon { target: 3 }),
622 ]);
623 assert!(classified_lexer_call(&positive).is_tail_call());
624
625 let rejected = [
626 ("dead end", Vec::new()),
627 (
628 "consuming edge",
629 vec![(
630 2,
631 LexerTransition::Atom {
632 target: 3,
633 label: 1,
634 },
635 )],
636 ),
637 (
638 "predicate",
639 vec![(
640 2,
641 LexerTransition::Predicate {
642 target: 3,
643 rule_index: 0,
644 pred_index: 0,
645 context_dependent: false,
646 },
647 )],
648 ),
649 (
650 "action",
651 vec![(
652 2,
653 LexerTransition::Action {
654 target: 3,
655 rule_index: 0,
656 action_index: Some(0),
657 context_dependent: false,
658 },
659 )],
660 ),
661 (
662 "nested rule",
663 vec![(
664 2,
665 LexerTransition::Rule {
666 target: 4,
667 rule_index: 1,
668 follow_state: 3,
669 precedence: 0,
670 tail_call: false,
671 },
672 )],
673 ),
674 (
675 "epsilon cycle",
676 vec![(2, LexerTransition::Epsilon { target: 2 })],
677 ),
678 (
679 "other rule stop",
680 vec![(2, LexerTransition::Epsilon { target: 7 })],
681 ),
682 ];
683 for (label, continuations) in rejected {
684 let atn = classified_lexer_rule(continuations);
685 assert!(
686 !classified_lexer_call(&atn).is_tail_call(),
687 "{label} must not be classified as a lexer tail call"
688 );
689 }
690 }
691
692 #[test]
693 fn interval_set_handles_ranges() {
694 let set = IntervalSet::from_range(2, 4);
695 assert!(set.contains(2));
696 assert!(set.contains(3));
697 assert!(set.contains(4));
698 assert!(!set.contains(5));
699 assert_eq!(set.ranges(), &[(2, 4)]);
700 }
701}