1use std::{
2 collections::{HashMap, HashSet},
3 fmt::Debug,
4 hash::Hash,
5 marker::PhantomData,
6 slice::Iter,
7 str::FromStr,
8};
9
10use cfgrammar::{
11 NewlineCache, Span,
12 header::{GrmtoolsSectionParser, Header, HeaderError, HeaderErrorKind, HeaderValue, Value},
13 span::Location,
14};
15use num_traits::{AsPrimitive, PrimInt, Unsigned};
16use regex::{Regex, RegexBuilder};
17
18use lrpar::{Lexeme, Lexer, LexerTypes, NonStreamingLexer};
19
20use crate::{
21 LRLexError, LexBuildError, LexBuildResult, StartStateId,
22 parser::{LexParser, StartState, StartStateOperation},
23};
24
25#[doc(hidden)]
26#[derive(Clone, Debug)]
28#[non_exhaustive]
29pub struct LexFlags {
30 pub dot_matches_new_line: Option<bool>,
32 pub multi_line: Option<bool>,
33 pub octal: Option<bool>,
34 pub posix_escapes: Option<bool>,
35 pub allow_wholeline_comments: Option<bool>,
36
37 pub case_insensitive: Option<bool>,
39 pub swap_greed: Option<bool>,
40 pub ignore_whitespace: Option<bool>,
41 pub unicode: Option<bool>,
42 pub size_limit: Option<usize>,
43 pub dfa_size_limit: Option<usize>,
44 pub nest_limit: Option<u32>,
45}
46
47impl<T: Clone> TryFrom<&mut Header<T>> for LexFlags {
48 type Error = HeaderError<T>;
49 fn try_from(header: &mut Header<T>) -> Result<LexFlags, HeaderError<T>> {
50 let mut lex_flags = UNSPECIFIED_LEX_FLAGS;
51 let LexFlags {
52 dot_matches_new_line,
53 multi_line,
54 octal,
55 posix_escapes,
56 allow_wholeline_comments,
57 case_insensitive,
58 swap_greed,
59 ignore_whitespace,
60 unicode,
61 size_limit,
62 dfa_size_limit,
63 nest_limit,
64 } = &mut lex_flags;
65 macro_rules! cvt_flag {
66 ($prefix:ident, $it:ident) => {
67 header.mark_used(&stringify!($prefix.$it).to_string());
68 *$it = match header.get(stringify!($prefix.$it)) {
69 Some(HeaderValue(_, Value::Bool(flag, _))) => Some(*flag),
70 Some(HeaderValue(_, val)) => Err(HeaderError {
71 kind: HeaderErrorKind::ConversionError("LexFlags", "Expected boolean"),
72 locations: vec![val.primary_location().clone()],
73 })?,
74 None => None,
75 }
76 };
77 }
78 cvt_flag!(regex, dot_matches_new_line);
79 cvt_flag!(regex, multi_line);
80 cvt_flag!(regex, octal);
81 cvt_flag!(lrlex, posix_escapes);
82 cvt_flag!(lrlex, allow_wholeline_comments);
83 cvt_flag!(regex, case_insensitive);
84 cvt_flag!(regex, swap_greed);
85 cvt_flag!(regex, ignore_whitespace);
86 cvt_flag!(regex, unicode);
87 macro_rules! cvt_num {
88 ($prefix:ident, $it:ident, $num_ty: ty) => {
89 header.mark_used(&stringify!($prefix.$it).to_string());
90 *$it = match header.get(stringify!($prefix.$it)) {
91 Some(HeaderValue(_, Value::Num(n, _))) => Some(*n as $num_ty),
92 Some(HeaderValue(_, val)) => Err(HeaderError {
93 kind: HeaderErrorKind::ConversionError("LexFlags", "Expected numeric"),
94 locations: vec![val.primary_location().clone()],
95 })?,
96 None => None,
97 }
98 };
99 }
100 cvt_num!(regex, size_limit, usize);
101 cvt_num!(regex, dfa_size_limit, usize);
102 cvt_num!(regex, nest_limit, u32);
103 Ok(lex_flags)
104 }
105}
106
107impl From<&LexFlags> for Header<Location> {
108 fn from(flags: &LexFlags) -> Header<Location> {
109 let mut header = Header::new();
110 let LexFlags {
111 dot_matches_new_line,
112 multi_line,
113 octal,
114 posix_escapes,
115 allow_wholeline_comments,
116 case_insensitive,
117 swap_greed,
118 ignore_whitespace,
119 unicode,
120 size_limit,
121 dfa_size_limit,
122 nest_limit,
123 } = flags;
124 macro_rules! cvt_flag {
125 ($it: ident) => {
126 $it.map(|x| {
127 header.insert(
128 stringify!($it).to_string(),
129 HeaderValue(
130 Location::Other("From<&LexFlags>".to_string()),
131 Value::Bool(x, Location::Other("From<&LexFlags>".to_string())),
132 ),
133 )
134 });
135 };
136 }
137 cvt_flag!(dot_matches_new_line);
138 cvt_flag!(multi_line);
139 cvt_flag!(octal);
140 cvt_flag!(posix_escapes);
141 cvt_flag!(allow_wholeline_comments);
142 cvt_flag!(case_insensitive);
143 cvt_flag!(swap_greed);
144 cvt_flag!(ignore_whitespace);
145 cvt_flag!(unicode);
146
147 macro_rules! cvt_num {
148 ($it: ident) => {
149 $it.map(|x| {
150 header.insert(
151 stringify!($it).to_string(),
152 HeaderValue(
153 Location::Other("From<&LexFlags>".to_string()),
154 Value::Num(x as u64, Location::Other("From<&LexFlags>".to_string())),
155 ),
156 )
157 });
158 };
159 }
160 cvt_num!(size_limit);
161 cvt_num!(dfa_size_limit);
162 cvt_num!(nest_limit);
163
164 header
165 }
166}
167
168#[doc(hidden)]
170pub const DEFAULT_LEX_FLAGS: LexFlags = LexFlags {
171 allow_wholeline_comments: Some(false),
172 dot_matches_new_line: Some(true),
173 multi_line: Some(true),
174 octal: Some(true),
175 posix_escapes: Some(false),
176 case_insensitive: None,
177 ignore_whitespace: None,
178 swap_greed: None,
179 unicode: None,
180 size_limit: None,
181 dfa_size_limit: None,
182 nest_limit: None,
183};
184
185#[doc(hidden)]
186pub const UNSPECIFIED_LEX_FLAGS: LexFlags = LexFlags {
188 allow_wholeline_comments: None,
189 dot_matches_new_line: None,
190 multi_line: None,
191 octal: None,
192 posix_escapes: None,
193 case_insensitive: None,
194 ignore_whitespace: None,
195 swap_greed: None,
196 unicode: None,
197 size_limit: None,
198 dfa_size_limit: None,
199 nest_limit: None,
200};
201
202#[derive(Debug, Clone)]
203#[doc(hidden)]
204pub struct Rule<StorageT> {
205 pub(super) tok_id: Option<StorageT>,
211 #[deprecated(note = "Use the name() function")]
214 pub name: Option<String>,
215 #[deprecated(note = "Use the name_span() function")]
216 pub name_span: Span,
217 pub(super) re_str: String,
218 re: Regex,
219 #[deprecated(note = "Use the start_states() function")]
221 pub start_states: Vec<usize>,
222 #[deprecated(note = "Use the target_state() function")]
227 pub target_state: Option<(usize, StartStateOperation)>,
228}
229
230impl<StorageT: PrimInt> Rule<StorageT> {
231 #[doc(hidden)]
234 #[allow(private_interfaces)]
235 #[allow(clippy::too_many_arguments)]
236 pub fn new(
237 _: crate::unstable_api::InternalPublicApi,
238 tok_id: Option<StorageT>,
239 name: Option<String>,
240 name_span: Span,
241 re_str: String,
242 start_states: Vec<usize>,
243 target_state: Option<(usize, StartStateOperation)>,
244 lex_flags: &LexFlags,
245 ) -> Result<Rule<StorageT>, regex::Error> {
246 let mut re = RegexBuilder::new(&format!("\\A(?:{})", re_str));
247 let mut re = re
248 .octal(lex_flags.octal.unwrap())
249 .multi_line(lex_flags.multi_line.unwrap())
250 .dot_matches_new_line(lex_flags.dot_matches_new_line.unwrap());
251
252 if let Some(flag) = lex_flags.ignore_whitespace {
253 re = re.ignore_whitespace(flag)
254 }
255 if let Some(flag) = lex_flags.unicode {
256 re = re.unicode(flag)
257 }
258 if let Some(flag) = lex_flags.case_insensitive {
259 re = re.case_insensitive(flag)
260 }
261 if let Some(flag) = lex_flags.swap_greed {
262 re = re.swap_greed(flag)
263 }
264 if let Some(sz) = lex_flags.size_limit {
265 re = re.size_limit(sz)
266 }
267 if let Some(sz) = lex_flags.dfa_size_limit {
268 re = re.dfa_size_limit(sz)
269 }
270 if let Some(lim) = lex_flags.nest_limit {
271 re = re.nest_limit(lim)
272 }
273
274 let re = re.build()?;
275 #[allow(deprecated)]
276 Ok(Rule {
277 tok_id,
278 name,
279 name_span,
280 re_str,
281 re,
282 start_states,
283 target_state,
284 })
285 }
286
287 pub fn tok_id(&self) -> Option<StorageT> {
292 self.tok_id
293 }
294
295 pub fn name(&self) -> Option<&str> {
298 #[allow(deprecated)]
299 self.name.as_deref()
300 }
301
302 pub fn name_span(&self) -> Span {
304 #[allow(deprecated)]
305 self.name_span
306 }
307
308 pub fn re_str(&self) -> &str {
310 &self.re_str
311 }
312
313 pub fn start_states(&self) -> &[usize] {
315 #[allow(deprecated)]
316 self.start_states.as_slice()
317 }
318
319 pub fn target_state(&self) -> Option<(usize, StartStateOperation)> {
321 #[allow(deprecated)]
322 self.target_state.clone()
323 }
324}
325
326pub trait LexerDef<LexerTypesT: LexerTypes>
328where
329 usize: AsPrimitive<LexerTypesT::StorageT>,
330{
331 #[doc(hidden)]
332 fn from_rules(start_states: Vec<StartState>, rules: Vec<Rule<LexerTypesT::StorageT>>) -> Self
335 where
336 Self: Sized;
337
338 fn from_str(s: &str) -> LexBuildResult<Self>
340 where
341 Self: Sized;
342
343 fn get_rule(&self, idx: usize) -> Option<&Rule<LexerTypesT::StorageT>>;
345
346 fn get_rule_by_id(&self, tok_id: LexerTypesT::StorageT) -> &Rule<LexerTypesT::StorageT>;
349
350 fn get_rule_by_name(&self, n: &str) -> Option<&Rule<LexerTypesT::StorageT>>;
352
353 fn set_rule_ids<'a>(
370 &'a mut self,
371 rule_ids_map: &HashMap<&'a str, LexerTypesT::StorageT>,
372 ) -> (Option<HashSet<&'a str>>, Option<HashSet<&'a str>>);
373
374 fn set_rule_ids_spanned<'a>(
375 &'a mut self,
376 rule_ids_map: &HashMap<&'a str, LexerTypesT::StorageT>,
377 ) -> (Option<HashSet<&'a str>>, Option<HashSet<(&'a str, Span)>>);
378
379 fn iter_rules(&self) -> Iter<'_, Rule<LexerTypesT::StorageT>>;
381
382 fn iter_start_states(&self) -> Iter<'_, StartState>;
384}
385
386#[derive(Debug, Clone)]
389pub struct LRNonStreamingLexerDef<LexerTypesT: LexerTypes>
390where
391 usize: AsPrimitive<LexerTypesT::StorageT>,
392{
393 rules: Vec<Rule<LexerTypesT::StorageT>>,
394 start_states: Vec<StartState>,
395 lex_flags: LexFlags,
396 pub(crate) expected_missing_tokens: Vec<String>,
397 phantom: PhantomData<LexerTypesT>,
398}
399
400impl<LexerTypesT: LexerTypes> LexerDef<LexerTypesT> for LRNonStreamingLexerDef<LexerTypesT>
401where
402 usize: AsPrimitive<LexerTypesT::StorageT>,
403 LexerTypesT::StorageT: TryFrom<usize>,
404{
405 fn from_rules(
406 start_states: Vec<StartState>,
407 rules: Vec<Rule<LexerTypesT::StorageT>>,
408 ) -> LRNonStreamingLexerDef<LexerTypesT> {
409 LRNonStreamingLexerDef {
410 rules,
411 start_states,
412 lex_flags: DEFAULT_LEX_FLAGS,
413 expected_missing_tokens: vec![],
414 phantom: PhantomData,
415 }
416 }
417
418 fn from_str(s: &str) -> LexBuildResult<LRNonStreamingLexerDef<LexerTypesT>> {
421 let (mut header, pos) = GrmtoolsSectionParser::new(s, false)
422 .parse()
423 .map_err(|mut errs| errs.drain(..).map(LexBuildError::from).collect::<Vec<_>>())?;
424 let flags = LexFlags::try_from(&mut header).map_err(|e| vec![e.into()])?;
425 LexParser::<LexerTypesT>::new_with_lex_flags(s[pos..].to_string(), flags.clone()).map(|p| {
426 LRNonStreamingLexerDef {
427 rules: p.rules,
428 start_states: p.start_states,
429 lex_flags: flags,
430 expected_missing_tokens: p.expected_missing_tokens,
431 phantom: PhantomData,
432 }
433 })
434 }
435
436 fn get_rule(&self, idx: usize) -> Option<&Rule<LexerTypesT::StorageT>> {
437 self.rules.get(idx)
438 }
439
440 fn get_rule_by_id(&self, tok_id: LexerTypesT::StorageT) -> &Rule<LexerTypesT::StorageT> {
441 self.rules
442 .iter()
443 .find(|r| r.tok_id == Some(tok_id))
444 .unwrap()
445 }
446
447 fn get_rule_by_name(&self, n: &str) -> Option<&Rule<LexerTypesT::StorageT>> {
448 self.rules.iter().find(|r| r.name() == Some(n))
449 }
450
451 fn set_rule_ids<'a>(
452 &'a mut self,
453 rule_ids_map: &HashMap<&'a str, LexerTypesT::StorageT>,
454 ) -> (Option<HashSet<&'a str>>, Option<HashSet<&'a str>>) {
455 let (missing_from_parser, missing_from_lexer) = self.set_rule_ids_spanned(rule_ids_map);
456 let missing_from_lexer =
457 missing_from_lexer.map(|missing| missing.iter().map(|(name, _)| *name).collect());
458 (missing_from_parser, missing_from_lexer)
459 }
460
461 fn set_rule_ids_spanned<'a>(
462 &'a mut self,
463 rule_ids_map: &HashMap<&'a str, LexerTypesT::StorageT>,
464 ) -> (Option<HashSet<&'a str>>, Option<HashSet<(&'a str, Span)>>) {
465 let mut missing_from_parser_idxs = Vec::new();
472 let mut rules_with_names = 0;
473 for (i, r) in self.rules.iter_mut().enumerate() {
474 if let Some(n) = r.name() {
475 match rule_ids_map.get(n) {
476 Some(tok_id) => r.tok_id = Some(*tok_id),
477 None => {
478 r.tok_id = None;
479 missing_from_parser_idxs.push(i);
480 }
481 }
482 rules_with_names += 1;
483 }
484 }
485
486 let missing_from_parser = if missing_from_parser_idxs.is_empty() {
487 None
488 } else {
489 let mut mfp = HashSet::with_capacity(missing_from_parser_idxs.len());
490 for i in &missing_from_parser_idxs {
491 mfp.insert((self.rules[*i].name().unwrap(), self.rules[*i].name_span()));
492 }
493 Some(mfp)
494 };
495
496 let missing_from_lexer =
497 if rules_with_names - missing_from_parser_idxs.len() == rule_ids_map.len() {
498 None
499 } else {
500 Some(
501 rule_ids_map
502 .keys()
503 .cloned()
504 .collect::<HashSet<&str>>()
505 .difference(
506 &self
507 .rules
508 .iter()
509 .filter_map(|x| x.name())
510 .collect::<HashSet<&str>>(),
511 )
512 .cloned()
513 .collect::<HashSet<&str>>(),
514 )
515 };
516
517 (missing_from_lexer, missing_from_parser)
518 }
519
520 fn iter_rules(&self) -> Iter<'_, Rule<LexerTypesT::StorageT>> {
521 self.rules.iter()
522 }
523
524 fn iter_start_states(&self) -> Iter<'_, StartState> {
525 self.start_states.iter()
526 }
527}
528
529impl<
530 StorageT: 'static + Debug + Hash + PrimInt + Unsigned,
531 LexerTypesT: LexerTypes<StorageT = StorageT>,
532> LRNonStreamingLexerDef<LexerTypesT>
533where
534 usize: AsPrimitive<StorageT>,
535 LexerTypesT::StorageT: TryFrom<usize>,
536{
537 pub fn new_with_options(
539 s: &str,
540 lex_flags: LexFlags,
541 ) -> LexBuildResult<LRNonStreamingLexerDef<LexerTypesT>> {
542 let (_, pos) = GrmtoolsSectionParser::new(s, false).parse().unwrap();
543 LexParser::<LexerTypesT>::new_with_lex_flags(s[pos..].to_string(), lex_flags.clone()).map(
544 |p| LRNonStreamingLexerDef {
545 rules: p.rules,
546 start_states: p.start_states,
547 lex_flags,
548 expected_missing_tokens: p.expected_missing_tokens,
549 phantom: PhantomData,
550 },
551 )
552 }
553
554 pub fn lexer<'lexer, 'input: 'lexer>(
557 &'lexer self,
558 s: &'input str,
559 ) -> LRNonStreamingLexer<'lexer, 'input, LexerTypesT> {
560 let mut lexemes = vec![];
561 let mut i = 0;
562 let mut state_stack: Vec<(usize, &StartState)> = Vec::new();
563 let initial_state = match self.get_start_state_by_id(0) {
564 None => {
565 lexemes.push(Err(LRLexError::new(Span::new(i, i))));
566 return LRNonStreamingLexer::new(s, lexemes, NewlineCache::from_str(s).unwrap());
567 }
568 Some(state) => state,
569 };
570 state_stack.push((1, initial_state));
571
572 while i < s.len() {
573 let old_i = i;
574 let mut longest = 0; let mut longest_ridx = 0; let current_state = match state_stack.last() {
577 None => {
578 lexemes.push(Err(LRLexError::new(Span::new(i, i))));
579 return LRNonStreamingLexer::new(
580 s,
581 lexemes,
582 NewlineCache::from_str(s).unwrap(),
583 );
584 }
585 Some((_, s)) => s,
586 };
587 for (ridx, r) in self.iter_rules().enumerate() {
588 if !Self::state_matches(current_state, r.start_states()) {
589 continue;
590 }
591 if let Some(m) = r.re.find(&s[old_i..]) {
592 let len = m.end();
593 if len > longest {
596 longest = len;
597 longest_ridx = ridx;
598 }
599 }
600 }
601 if longest > 0 {
602 let r = self.get_rule(longest_ridx).unwrap();
603 if r.name().is_some() {
604 match r.tok_id {
605 Some(tok_id) => {
606 lexemes.push(Ok(Lexeme::new(tok_id, old_i, longest)));
607 }
608 None => {
609 lexemes.push(Err(LRLexError::new(Span::new(old_i, old_i))));
610 break;
611 }
612 }
613 }
614 if let Some((target_state_id, op)) = &r.target_state() {
615 let state = match self.get_start_state_by_id(*target_state_id) {
616 None => {
617 lexemes.push(Err(LRLexError::new(Span::new(old_i, old_i))));
619 break;
620 }
621 Some(state) => state,
622 };
623 let head = state_stack.last_mut();
624 match op {
625 StartStateOperation::ReplaceStack => {
626 state_stack.clear();
627 state_stack.push((1, state));
628 }
629 StartStateOperation::Push => match head {
630 Some((count, s)) if s.id == state.id => *count += 1,
631 _ => state_stack.push((1, state)),
632 },
633 StartStateOperation::Pop => match head {
634 Some((count, _s)) if *count > 1 => {
635 *count -= 1;
636 }
637 Some(_) => {
638 state_stack.pop();
639 if state_stack.is_empty() {
640 state_stack.push((1, initial_state));
641 }
642 }
643 None => {
644 lexemes.push(Err(LRLexError::new(Span::new(old_i, old_i))));
645 break;
646 }
647 },
648 }
649 }
650 i += longest;
651 } else {
652 lexemes.push(Err(LRLexError::new_with_lexing_state(
653 Span::new(old_i, old_i),
654 StartStateId::new(current_state.id),
655 )));
656 break;
657 }
658 }
659 LRNonStreamingLexer::new(s, lexemes, NewlineCache::from_str(s).unwrap())
660 }
661
662 fn state_matches(state: &StartState, rule_states: &[usize]) -> bool {
663 if rule_states.is_empty() {
664 !state.exclusive
665 } else {
666 rule_states.contains(&state.id)
667 }
668 }
669
670 fn get_start_state_by_id(&self, id: usize) -> Option<&StartState> {
671 self.start_states.iter().find(|state| state.id == id)
672 }
673
674 pub(crate) fn lex_flags(&self) -> Option<&LexFlags> {
677 Some(&self.lex_flags)
678 }
679}
680
681pub struct LRNonStreamingLexer<'lexer, 'input: 'lexer, LexerTypesT: LexerTypes>
685where
686 usize: AsPrimitive<LexerTypesT::StorageT>,
687 LexerTypesT::StorageT: 'static + Debug + PrimInt,
688{
689 s: &'input str,
690 lexemes: Vec<Result<LexerTypesT::LexemeT, LRLexError>>,
691 newlines: NewlineCache,
692 phantom: PhantomData<(&'lexer (), LexerTypesT::StorageT)>,
693}
694
695impl<
696 'lexer,
697 'input: 'lexer,
698 StorageT: 'static + Debug + Hash + PrimInt + Unsigned,
699 LexerTypesT: LexerTypes<StorageT = StorageT>,
700> LRNonStreamingLexer<'lexer, 'input, LexerTypesT>
701where
702 usize: AsPrimitive<StorageT>,
703{
704 pub fn new(
710 s: &'input str,
711 lexemes: Vec<Result<LexerTypesT::LexemeT, LRLexError>>,
712 newlines: NewlineCache,
713 ) -> LRNonStreamingLexer<'lexer, 'input, LexerTypesT> {
714 LRNonStreamingLexer {
715 s,
716 lexemes,
717 newlines,
718 phantom: PhantomData,
719 }
720 }
721}
722
723impl<
724 'lexer,
725 'input: 'lexer,
726 StorageT: 'static + Debug + Hash + PrimInt + Unsigned,
727 LexerTypesT: LexerTypes<StorageT = StorageT, LexErrorT = LRLexError>,
728> Lexer<LexerTypesT> for LRNonStreamingLexer<'lexer, 'input, LexerTypesT>
729where
730 usize: AsPrimitive<StorageT>,
731{
732 fn iter<'a>(
733 &'a self,
734 ) -> Box<dyn Iterator<Item = Result<LexerTypesT::LexemeT, LexerTypesT::LexErrorT>> + 'a> {
735 Box::new(self.lexemes.iter().cloned())
736 }
737}
738
739impl<'lexer, 'input: 'lexer, LexerTypesT: LexerTypes<LexErrorT = LRLexError>>
740 NonStreamingLexer<'input, LexerTypesT> for LRNonStreamingLexer<'lexer, 'input, LexerTypesT>
741where
742 usize: AsPrimitive<LexerTypesT::StorageT>,
743{
744 fn span_str(&self, span: Span) -> &'input str {
745 if span.end() > self.s.len() {
746 panic!(
747 "Span {:?} exceeds known input length {}",
748 span,
749 self.s.len()
750 );
751 }
752 &self.s[span.start()..span.end()]
753 }
754
755 fn span_lines_str(&self, span: Span) -> &'input str {
756 debug_assert!(span.end() >= span.start());
757 if span.end() > self.s.len() {
758 panic!(
759 "Span {:?} exceeds known input length {}",
760 span,
761 self.s.len()
762 );
763 }
764
765 let (st, en) = self.newlines.span_line_bytes(span);
766 &self.s[st..en]
767 }
768
769 fn line_col(&self, span: Span) -> ((usize, usize), (usize, usize)) {
770 debug_assert!(span.end() >= span.start());
771 if span.end() > self.s.len() {
772 panic!(
773 "Span {:?} exceeds known input length {}",
774 span,
775 self.s.len()
776 );
777 }
778
779 (
780 self.newlines
781 .byte_to_line_num_and_col_num(self.s, span.start())
782 .unwrap(),
783 self.newlines
784 .byte_to_line_num_and_col_num(self.s, span.end())
785 .unwrap(),
786 )
787 }
788}
789
790#[cfg(test)]
791mod test {
792 use super::*;
793 use crate::{DefaultLexeme, DefaultLexerTypes};
794 use lrpar::LexError;
795 use std::collections::HashMap;
796
797 #[test]
798 fn test_basic() {
799 let src = r"
800%%
801[0-9]+ 'int'
802[a-zA-Z]+ 'id'
803[ \t] ;"
804 .to_string();
805 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
806 let mut map = HashMap::new();
807 map.insert("int", 0);
808 map.insert("id", 1);
809 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
810
811 let lexemes = lexerdef
812 .lexer("abc 123")
813 .iter()
814 .map(|x| x.unwrap())
815 .collect::<Vec<_>>();
816 assert_eq!(lexemes.len(), 2);
817 let lex1 = lexemes[0];
818 assert_eq!(lex1.tok_id(), 1u8);
819 assert_eq!(lex1.span().start(), 0);
820 assert_eq!(lex1.span().len(), 3);
821 let lex2 = lexemes[1];
822 assert_eq!(lex2.tok_id(), 0);
823 assert_eq!(lex2.span().start(), 4);
824 assert_eq!(lex2.span().len(), 3);
825 }
826
827 #[test]
828 fn test_posix_escapes() {
829 let src = r#"%%
830\\ 'slash'
831\a 'alert'
832\b 'backspace'
833\f 'feed'
834\n 'newline'
835\r 'return'
836\t 'tab'
837\v 'vtab'
838\q 'normal_char'
839"#
840 .to_string();
841 let mut options = DEFAULT_LEX_FLAGS;
842 options.posix_escapes = Some(true);
843 let lexerdef =
844 LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::new_with_options(&src, options)
845 .unwrap();
846 let lexemes = lexerdef
847 .lexer("\\\x07\x08\x0c\n\r\t\x0bq")
848 .iter()
849 .map(|x| x.unwrap())
850 .collect::<Vec<_>>();
851 assert_eq!(lexemes.len(), 9);
852 for i in 0..9u8 {
853 let lexeme = lexemes[i as usize];
854 assert_eq!(lexeme.tok_id(), i);
855 }
856 }
857
858 #[test]
859 fn test_non_posix_escapes() {
860 let src = r#"%%
861\\ 'slash'
862\a 'alert'
863a\b a 'work_break'
864\f 'feed'
865\n 'newline'
866\r 'return'
867\t 'tab'
868\v 'vtab'
869\q 'normal_char'
870"#
871 .to_string();
872 let mut options = DEFAULT_LEX_FLAGS;
873 options.posix_escapes = Some(false);
874 let lexerdef =
875 LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::new_with_options(&src, options)
876 .unwrap();
877 let lexemes = lexerdef
878 .lexer("\\\x07a a\x0c\n\r\t\x0bq")
879 .iter()
880 .map(|x| x.unwrap())
881 .collect::<Vec<_>>();
882 assert_eq!(lexemes.len(), 9);
883 for i in 0..9u8 {
884 let lexeme = lexemes[i as usize];
885 assert_eq!(lexeme.tok_id(), i);
886 }
887 }
888
889 #[test]
890 fn test_basic_error() {
891 let src = "
892%%
893[0-9]+ 'int'"
894 .to_string();
895 let lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
896 match lexerdef.lexer("abc").iter().next().unwrap() {
897 Ok(_) => panic!("Invalid input lexed"),
898 Err(e) => {
899 if e.span().start() != 0 || e.span().end() != 0 {
900 panic!("Incorrect span returned {:?}", e.span());
901 }
902 }
903 };
904 }
905
906 #[test]
907 fn test_longest_match() {
908 let src = "%%
909if 'IF'
910[a-z]+ 'ID'
911[ ] ;"
912 .to_string();
913 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
914 let mut map = HashMap::new();
915 map.insert("IF", 0);
916 map.insert("ID", 1);
917 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
918
919 let lexemes = lexerdef
920 .lexer("iff if")
921 .iter()
922 .map(|x| x.unwrap())
923 .collect::<Vec<DefaultLexeme<u8>>>();
924 assert_eq!(lexemes.len(), 2);
925 let lex1 = lexemes[0];
926 assert_eq!(lex1.tok_id(), 1u8);
927 assert_eq!(lex1.span().start(), 0);
928 assert_eq!(lex1.span().len(), 3);
929 let lex2 = lexemes[1];
930 assert_eq!(lex2.tok_id(), 0);
931 assert_eq!(lex2.span().start(), 4);
932 assert_eq!(lex2.span().len(), 2);
933 }
934
935 #[test]
936 fn test_multibyte() {
937 let src = "%%
938[a❤]+ 'ID'
939[ ] ;"
940 .to_string();
941 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
942 let mut map = HashMap::new();
943 map.insert("ID", 0u8);
944 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
945
946 let lexer = lexerdef.lexer("a ❤ a");
947 let lexemes = lexer
948 .iter()
949 .map(|x| x.unwrap())
950 .collect::<Vec<DefaultLexeme<u8>>>();
951 assert_eq!(lexemes.len(), 3);
952 let lex1 = lexemes[0];
953 assert_eq!(lex1.span().start(), 0);
954 assert_eq!(lex1.span().len(), 1);
955 assert_eq!(lexer.span_str(lex1.span()), "a");
956 let lex2 = lexemes[1];
957 assert_eq!(lex2.span().start(), 2);
958 assert_eq!(lex2.span().len(), 3);
959 assert_eq!(lexer.span_str(lex2.span()), "❤");
960 let lex3 = lexemes[2];
961 assert_eq!(lex3.span().start(), 6);
962 assert_eq!(lex3.span().len(), 1);
963 assert_eq!(lexer.span_str(lex3.span()), "a");
964 }
965
966 #[test]
967 fn test_line_col() {
968 let src = "%%
969[a-z]+ 'ID'
970[ \\n] ;"
971 .to_string();
972 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
973 let mut map = HashMap::new();
974 map.insert("ID", 0u8);
975 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
976
977 let lexer = lexerdef.lexer("a b c");
978 let lexemes = lexer
979 .iter()
980 .map(|x| x.unwrap())
981 .collect::<Vec<DefaultLexeme<u8>>>();
982 assert_eq!(lexemes.len(), 3);
983 assert_eq!(lexer.line_col(lexemes[1].span()), ((1, 3), (1, 4)));
984 assert_eq!(lexer.span_lines_str(lexemes[1].span()), "a b c");
985 assert_eq!(lexer.span_lines_str(lexemes[2].span()), "a b c");
986
987 let lexer = lexerdef.lexer("a b c\n");
988 let lexemes = lexer.iter().map(|x| x.unwrap()).collect::<Vec<_>>();
989 assert_eq!(lexemes.len(), 3);
990 assert_eq!(lexer.line_col(lexemes[1].span()), ((1, 3), (1, 4)));
991 assert_eq!(lexer.span_lines_str(lexemes[1].span()), "a b c");
992 assert_eq!(lexer.span_lines_str(lexemes[2].span()), "a b c");
993
994 let lexer = lexerdef.lexer(" a\nb\n c d");
995 let lexemes = lexer.iter().map(|x| x.unwrap()).collect::<Vec<_>>();
996 assert_eq!(lexemes.len(), 4);
997 assert_eq!(lexer.line_col(lexemes[0].span()), ((1, 2), (1, 3)));
998 assert_eq!(lexer.line_col(lexemes[1].span()), ((2, 1), (2, 2)));
999 assert_eq!(lexer.line_col(lexemes[2].span()), ((3, 3), (3, 4)));
1000 assert_eq!(lexer.line_col(lexemes[3].span()), ((3, 5), (3, 6)));
1001 assert_eq!(lexer.span_lines_str(lexemes[0].span()), " a");
1002 assert_eq!(lexer.span_lines_str(lexemes[1].span()), "b");
1003 assert_eq!(lexer.span_lines_str(lexemes[2].span()), " c d");
1004 assert_eq!(lexer.span_lines_str(lexemes[3].span()), " c d");
1005
1006 let mut s = Vec::new();
1007 let mut offs = vec![0];
1008 for i in 0..71 {
1009 offs.push(offs[i] + i + 1);
1010 s.push(vec!["a"; i].join(" "));
1011 }
1012 let s = s.join("\n");
1013 let lexer = lexerdef.lexer(&s);
1014 let lexemes = lexer.iter().map(|x| x.unwrap()).collect::<Vec<_>>();
1015 assert_eq!(lexemes.len(), offs[70]);
1016 assert_eq!(lexer.span_lines_str(Span::new(0, 0)), "");
1017 assert_eq!(lexer.span_lines_str(Span::new(0, 2)), "\na");
1018 assert_eq!(lexer.span_lines_str(Span::new(0, 4)), "\na\na a");
1019 assert_eq!(lexer.span_lines_str(Span::new(0, 7)), "\na\na a\na a a");
1020 assert_eq!(lexer.span_lines_str(Span::new(4, 7)), "a a\na a a");
1021 assert_eq!(lexer.span_lines_str(lexemes[0].span()), "a");
1022 assert_eq!(lexer.span_lines_str(lexemes[1].span()), "a a");
1023 assert_eq!(lexer.span_lines_str(lexemes[3].span()), "a a a");
1024 for i in 0..70 {
1025 assert_eq!(
1026 lexer.span_lines_str(lexemes[offs[i]].span()),
1027 vec!["a"; i + 1].join(" ")
1028 );
1029 }
1030 }
1031
1032 #[test]
1033 fn test_line_col_multibyte() {
1034 let src = "%%
1035[a-z❤]+ 'ID'
1036[ \\n] ;"
1037 .to_string();
1038 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1039 let mut map = HashMap::new();
1040 map.insert("ID", 0u8);
1041 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
1042
1043 let lexer = lexerdef.lexer(" a\n❤ b");
1044 let lexemes = lexer
1045 .iter()
1046 .map(|x| x.unwrap())
1047 .collect::<Vec<DefaultLexeme<u8>>>();
1048 assert_eq!(lexemes.len(), 3);
1049 assert_eq!(lexer.line_col(lexemes[0].span()), ((1, 2), (1, 3)));
1050 assert_eq!(lexer.line_col(lexemes[1].span()), ((2, 1), (2, 2)));
1051 assert_eq!(lexer.line_col(lexemes[2].span()), ((2, 3), (2, 4)));
1052 assert_eq!(lexer.span_lines_str(lexemes[0].span()), " a");
1053 assert_eq!(lexer.span_lines_str(lexemes[1].span()), "❤ b");
1054 assert_eq!(lexer.span_lines_str(lexemes[2].span()), "❤ b");
1055 }
1056
1057 #[test]
1058 #[should_panic]
1059 fn test_bad_line_col() {
1060 let src = "%%
1061[a-z]+ 'ID'
1062[ \\n] ;"
1063 .to_string();
1064 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1065 let mut map = HashMap::new();
1066 map.insert("ID", 0u8);
1067 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
1068
1069 let lexer = lexerdef.lexer("a b c");
1070
1071 lexer.line_col(Span::new(100, 100));
1072 }
1073
1074 #[test]
1075 fn test_missing_from_lexer_and_parser() {
1076 let src = "%%
1077[a-z]+ 'ID'
1078[ \\n] ;"
1079 .to_string();
1080 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1081 let mut map = HashMap::new();
1082 map.insert("INT", 0u8);
1083 let mut missing_from_lexer = HashSet::new();
1084 missing_from_lexer.insert("INT");
1085 let mut missing_from_parser = HashSet::new();
1086 missing_from_parser.insert("ID");
1087 assert_eq!(
1088 lexerdef.set_rule_ids(&map),
1089 (Some(missing_from_lexer), Some(missing_from_parser))
1090 );
1091
1092 match lexerdef.lexer(" a ").iter().next().unwrap() {
1093 Ok(_) => panic!("Invalid input lexed"),
1094 Err(e) => {
1095 if e.span().start() != 1 || e.span().end() != 1 {
1096 panic!("Incorrect span returned {:?}", e.span());
1097 }
1098 }
1099 };
1100 }
1101
1102 #[test]
1103 fn test_multiline_lexeme() {
1104 let src = "%%
1105'.*' 'STR'
1106[ \\n] ;"
1107 .to_string();
1108 let mut lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1109 let mut map = HashMap::new();
1110 map.insert("STR", 0u8);
1111 assert_eq!(lexerdef.set_rule_ids(&map), (None, None));
1112
1113 let lexer = lexerdef.lexer("'a\nb'\n");
1114 let lexemes = lexer
1115 .iter()
1116 .map(|x| x.unwrap())
1117 .collect::<Vec<DefaultLexeme<u8>>>();
1118 assert_eq!(lexemes.len(), 1);
1119 assert_eq!(lexer.line_col(lexemes[0].span()), ((1, 1), (2, 3)));
1120 assert_eq!(lexer.span_lines_str(lexemes[0].span()), "'a\nb'");
1121 }
1122
1123 #[test]
1124 fn test_token_span() {
1125 let src = "%%
1126a 'A'
1127b 'B'
1128[ \\n] ;"
1129 .to_string();
1130 let lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1131 assert_eq!(
1132 lexerdef.get_rule_by_name("A").unwrap().name_span(),
1133 Span::new(6, 7)
1134 );
1135 assert_eq!(
1136 lexerdef.get_rule_by_name("B").unwrap().name_span(),
1137 Span::new(12, 13)
1138 );
1139 let anonymous_rules = lexerdef
1140 .iter_rules()
1141 .filter(|rule| rule.name().is_none())
1142 .collect::<Vec<_>>();
1143 assert_eq!(anonymous_rules[0].name_span(), Span::new(21, 21));
1144 }
1145
1146 #[test]
1147 fn test_token_start_states() {
1148 let src = "%x EXCLUSIVE_START
1149%s INCLUSIVE_START
1150%%
1151a 'A'
1152b 'B'
1153[ \\n] ;"
1154 .to_string();
1155 let lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1156 assert_eq!(
1157 lexerdef.get_rule_by_name("A").unwrap().name_span(),
1158 Span::new(44, 45)
1159 );
1160 assert_eq!(
1161 lexerdef.get_rule_by_name("B").unwrap().name_span(),
1162 Span::new(50, 51)
1163 );
1164 }
1165
1166 #[test]
1167 fn test_rule_start_states() {
1168 let src = "%x EXCLUSIVE_START
1169%s INCLUSIVE_START
1170%%
1171<EXCLUSIVE_START>a 'A'
1172<INCLUSIVE_START>b 'B'
1173[ \\n] ;"
1174 .to_string();
1175 let lexerdef = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::from_str(&src).unwrap();
1176 let a_rule = lexerdef.get_rule_by_name("A").unwrap();
1177 assert_eq!(a_rule.name_span(), Span::new(61, 62));
1178 assert_eq!(a_rule.re_str, "a");
1179
1180 let b_rule = lexerdef.get_rule_by_name("B").unwrap();
1181 assert_eq!(b_rule.name_span(), Span::new(84, 85));
1182 assert_eq!(b_rule.re_str, "b");
1183 }
1184
1185 #[test]
1186 fn test_state_matches_regular_no_rule_states() {
1187 let all_states = &[
1188 StartState::new(0, "INITIAL", false, Span::new(0, 0)),
1189 StartState::new(1, "EXCLUSIVE", true, Span::new(0, 0)),
1190 ];
1191 let rule_states = vec![];
1192 let current_state = &all_states[0];
1193 let m = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::state_matches(
1194 current_state,
1195 &rule_states,
1196 );
1197 assert!(m);
1198 }
1199
1200 #[test]
1201 fn test_state_matches_exclusive_no_rule_states() {
1202 let all_states = &[
1203 StartState::new(0, "INITIAL", false, Span::new(0, 0)),
1204 StartState::new(1, "EXCLUSIVE", true, Span::new(0, 0)),
1205 ];
1206 let rule_states = vec![];
1207 let current_state = &all_states[1];
1208 let m = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::state_matches(
1209 current_state,
1210 &rule_states,
1211 );
1212 assert!(!m);
1213 }
1214
1215 #[test]
1216 fn test_state_matches_regular_matching_rule_states() {
1217 let all_states = &[
1218 StartState::new(0, "INITIAL", false, Span::new(0, 0)),
1219 StartState::new(1, "EXCLUSIVE", true, Span::new(0, 0)),
1220 ];
1221 let rule_states = vec![0];
1222 let current_state = &all_states[0];
1223 let m = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::state_matches(
1224 current_state,
1225 &rule_states,
1226 );
1227 assert!(m);
1228 }
1229
1230 #[test]
1231 fn test_state_matches_exclusive_matching_rule_states() {
1232 let all_states = &[
1233 StartState::new(0, "INITIAL", false, Span::new(0, 0)),
1234 StartState::new(1, "EXCLUSIVE", true, Span::new(0, 0)),
1235 ];
1236 let rule_states = vec![1];
1237 let current_state = &all_states[1];
1238 let m = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::state_matches(
1239 current_state,
1240 &rule_states,
1241 );
1242 assert!(m);
1243 }
1244
1245 #[test]
1246 fn test_state_matches_regular_other_rule_states() {
1247 let all_states = &[
1248 StartState::new(0, "INITIAL", false, Span::new(0, 0)),
1249 StartState::new(1, "EXCLUSIVE", true, Span::new(0, 0)),
1250 ];
1251 let rule_states = vec![1];
1252 let current_state = &all_states[0];
1253 let m = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::state_matches(
1254 current_state,
1255 &rule_states,
1256 );
1257 assert!(!m);
1258 }
1259
1260 #[test]
1261 fn test_state_matches_exclusive_other_rule_states() {
1262 let all_states = &[
1263 StartState::new(0, "INITIAL", false, Span::new(0, 0)),
1264 StartState::new(1, "EXCLUSIVE", true, Span::new(0, 0)),
1265 ];
1266 let rule_states = vec![0];
1267 let current_state = &all_states[1];
1268 let m = LRNonStreamingLexerDef::<DefaultLexerTypes<u8>>::state_matches(
1269 current_state,
1270 &rule_states,
1271 );
1272 assert!(!m);
1273 }
1274}