1use crate::token::{Tin, TIN_CM, TIN_LN, TIN_MAX, TIN_NR, TIN_SP, TIN_ST, TIN_TX, TIN_VL};
4use indexmap::IndexMap;
5use regex::Regex;
6use std::collections::HashMap;
7use std::fmt;
8use std::sync::Arc;
9
10use crate::context::Context;
11use crate::lexer::Lexer;
12use crate::rule::Rule;
13use crate::token::Token;
14
15type ConfigModifierCallback = dyn Fn(&mut Options, &Options) + Send + Sync;
16
17#[derive(Clone)]
18pub struct ConfigModifier {
19 callback: Arc<ConfigModifierCallback>,
20}
21
22impl ConfigModifier {
23 pub(crate) fn new(callback: impl Fn(&mut Options) + Send + Sync + 'static) -> Self {
24 Self {
25 callback: Arc::new(move |config, _options| callback(config)),
26 }
27 }
28
29 pub(crate) fn with_options(
30 callback: impl Fn(&mut Options, &Options) + Send + Sync + 'static,
31 ) -> Self {
32 Self {
33 callback: Arc::new(callback),
34 }
35 }
36
37 pub(crate) fn run(&self, config: &mut Options, options: &Options) {
38 (self.callback)(config, options);
39 }
40
41 pub(crate) fn same_callback(&self, other: &Self) -> bool {
42 Arc::ptr_eq(&self.callback, &other.callback)
43 }
44}
45
46impl fmt::Debug for ConfigModifier {
47 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48 formatter.write_str("ConfigModifier(<function>)")
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct ColorOptions {
54 pub active: bool,
55 pub reset: String,
56 pub hi: String,
57 pub lo: String,
58 pub line: String,
59}
60
61impl ColorOptions {
62 pub(crate) fn codes(&self) -> (&str, &str, &str, &str) {
63 if self.active {
64 (&self.hi, &self.lo, &self.line, &self.reset)
65 } else {
66 ("", "", "", "")
67 }
68 }
69}
70
71impl Default for ColorOptions {
72 fn default() -> Self {
73 Self {
74 active: true,
75 reset: "\x1b[0m".into(),
76 hi: "\x1b[91m".into(),
77 lo: "\x1b[2m".into(),
78 line: "\x1b[34m".into(),
79 }
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct ErrorSuffixContext {
85 pub code: String,
86 pub source: String,
87 pub message: String,
88 pub hint: String,
89 pub pos: usize,
90 pub row: usize,
91 pub col: usize,
92 pub name: String,
93 pub tag: String,
94 pub rule: String,
95 pub rule_state: String,
96 pub token: String,
97 pub why: String,
98 pub plugins: Vec<String>,
99 pub color: ColorOptions,
100}
101
102pub type ErrorSuffixCallback = Arc<dyn Fn(&ErrorSuffixContext) -> String + Send + Sync>;
103
104#[derive(Clone)]
105pub enum ErrorSuffix {
106 Standard,
107 Disabled,
108 Text(String),
109 Callback(ErrorSuffixCallback),
110}
111
112impl fmt::Debug for ErrorSuffix {
113 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
114 match self {
115 Self::Standard => formatter.write_str("Standard"),
116 Self::Disabled => formatter.write_str("Disabled"),
117 Self::Text(text) => formatter.debug_tuple("Text").field(text).finish(),
118 Self::Callback(_) => formatter.write_str("Callback(<function>)"),
119 }
120 }
121}
122
123impl PartialEq for ErrorSuffix {
124 fn eq(&self, other: &Self) -> bool {
125 match (self, other) {
126 (Self::Standard, Self::Standard) | (Self::Disabled, Self::Disabled) => true,
127 (Self::Text(left), Self::Text(right)) => left == right,
128 (Self::Callback(left), Self::Callback(right)) => Arc::ptr_eq(left, right),
129 _ => false,
130 }
131 }
132}
133
134impl Eq for ErrorSuffix {}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct ErrMsgOptions {
138 pub name: String,
139 pub suffix: ErrorSuffix,
140 pub link: String,
141}
142
143impl Default for ErrMsgOptions {
144 fn default() -> Self {
145 Self {
146 name: "tabnas".into(),
147 suffix: ErrorSuffix::Standard,
148 link: String::new(),
149 }
150 }
151}
152
153#[derive(Debug, Clone, PartialEq)]
154pub struct LexCheckToken {
155 pub name: String,
156 pub tin: Tin,
157 pub source: String,
158 pub value: crate::Value,
159}
160
161impl LexCheckToken {
162 pub fn new(
163 name: impl Into<String>,
164 tin: Tin,
165 source: impl Into<String>,
166 value: crate::Value,
167 ) -> Self {
168 Self {
169 name: name.into(),
170 tin,
171 source: source.into(),
172 value,
173 }
174 }
175
176 pub fn named(name: impl Into<String>, source: impl Into<String>, value: crate::Value) -> Self {
179 let name = name.into();
180 Self {
181 name: if name.starts_with('#') {
182 name
183 } else {
184 format!("#{name}")
185 },
186 tin: -1,
187 source: source.into(),
188 value,
189 }
190 }
191}
192
193#[derive(Debug, Clone, PartialEq)]
195pub enum LexCheckResult {
196 Continue,
198 Skip,
200 Token(Box<LexCheckToken>),
202 NativeToken(Box<Token>),
205}
206
207impl LexCheckResult {
208 pub fn token(token: LexCheckToken) -> Self {
209 Self::Token(Box::new(token))
210 }
211
212 pub fn native_token(token: Token) -> Self {
213 Self::NativeToken(Box::new(token))
214 }
215}
216
217pub type ImperativeLexCheck =
218 Arc<dyn for<'source> Fn(&mut Lexer<'source>) -> LexCheckResult + Send + Sync>;
219
220#[derive(Clone)]
221pub struct LexCheck {
222 callback: Option<Arc<LexCheckEffect>>,
223 imperative: Option<ImperativeLexCheck>,
224}
225
226type LexCheckEffect = dyn Fn(&str) -> LexCheckResult + Send + Sync;
227
228impl LexCheck {
229 pub(crate) fn new(callback: impl Fn(&str) -> LexCheckResult + Send + Sync + 'static) -> Self {
230 Self {
231 callback: Some(Arc::new(callback)),
232 imperative: None,
233 }
234 }
235
236 pub(crate) fn new_imperative(
237 callback: impl for<'source> Fn(&mut Lexer<'source>) -> LexCheckResult + Send + Sync + 'static,
238 ) -> Self {
239 Self {
240 callback: None,
241 imperative: Some(Arc::new(callback)),
242 }
243 }
244
245 pub(crate) fn run(&self, source: &str) -> Option<LexCheckResult> {
246 self.callback.as_ref().map(|callback| callback(source))
247 }
248
249 pub(crate) fn run_imperative(&self, lexer: &mut Lexer<'_>) -> Option<LexCheckResult> {
250 self.imperative.as_ref().map(|callback| callback(lexer))
251 }
252
253 pub(crate) fn same_callback(&self, other: &Self) -> bool {
254 match (
255 &self.callback,
256 &self.imperative,
257 &other.callback,
258 &other.imperative,
259 ) {
260 (Some(left), None, Some(right), None) => Arc::ptr_eq(left, right),
261 (None, Some(left), None, Some(right)) => Arc::ptr_eq(left, right),
262 _ => false,
263 }
264 }
265}
266
267impl fmt::Debug for LexCheck {
268 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
269 formatter.write_str(if self.imperative.is_some() {
270 "LexCheck(<live lexer function>)"
271 } else {
272 "LexCheck(<effect function>)"
273 })
274 }
275}
276
277#[derive(Debug, Clone)]
278pub struct FixedToken {
279 pub name: String,
280 pub tin: Tin,
281 pub source: String,
282}
283
284#[derive(Debug, Clone)]
285pub struct FixedOptions {
286 pub lex: bool,
287 pub tokens: IndexMap<String, FixedToken>,
288 pub check: Option<LexCheck>,
289}
290
291impl Default for FixedOptions {
292 fn default() -> Self {
293 let mut tokens = IndexMap::new();
294 for (name, tin, source) in [
295 ("#OB", crate::token::TIN_OB, "{"),
296 ("#CB", crate::token::TIN_CB, "}"),
297 ("#OS", crate::token::TIN_OS, "["),
298 ("#CS", crate::token::TIN_CS, "]"),
299 ("#CL", crate::token::TIN_CL, ":"),
300 ("#CA", crate::token::TIN_CA, ","),
301 ] {
302 tokens.insert(
303 name.to_string(),
304 FixedToken {
305 name: name.to_string(),
306 tin,
307 source: source.to_string(),
308 },
309 );
310 }
311 Self {
312 lex: true,
313 tokens,
314 check: None,
315 }
316 }
317}
318
319pub type ValueTextModifier = Arc<dyn Fn(crate::Value) -> crate::Value + Send + Sync>;
320pub type ImperativeTextModifier = Arc<
321 dyn for<'source> Fn(
322 crate::Value,
323 &mut Lexer<'source>,
324 &mut Rule,
325 &mut Context,
326 &Options,
327 ) -> crate::Value
328 + Send
329 + Sync,
330>;
331
332#[derive(Clone)]
338pub enum TextModifier {
339 Value(ValueTextModifier),
340 Imperative(ImperativeTextModifier),
341}
342
343impl TextModifier {
344 pub(crate) fn new(
345 modifier: impl Fn(crate::Value) -> crate::Value + Send + Sync + 'static,
346 ) -> Self {
347 Self::Value(Arc::new(modifier))
348 }
349
350 pub(crate) fn new_imperative(
351 modifier: impl for<'source> Fn(
352 crate::Value,
353 &mut Lexer<'source>,
354 &mut Rule,
355 &mut Context,
356 &Options,
357 ) -> crate::Value
358 + Send
359 + Sync
360 + 'static,
361 ) -> Self {
362 Self::Imperative(Arc::new(modifier))
363 }
364
365 pub(crate) fn run(
366 &self,
367 value: crate::Value,
368 lexer: &mut Lexer<'_>,
369 rule: &mut Rule,
370 context: &mut Context,
371 options: &Options,
372 ) -> crate::Value {
373 match self {
374 Self::Value(modifier) => modifier(value),
375 Self::Imperative(modifier) => modifier(value, lexer, rule, context, options),
376 }
377 }
378
379 pub(crate) fn same_callback(&self, other: &Self) -> bool {
380 match (self, other) {
381 (Self::Value(left), Self::Value(right)) => Arc::ptr_eq(left, right),
382 (Self::Imperative(left), Self::Imperative(right)) => Arc::ptr_eq(left, right),
383 _ => false,
384 }
385 }
386}
387
388impl fmt::Debug for TextModifier {
389 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
390 formatter.write_str(match self {
391 Self::Value(_) => "TextModifier::Value(<function>)",
392 Self::Imperative(_) => "TextModifier::Imperative(<function>)",
393 })
394 }
395}
396
397#[derive(Clone)]
398pub struct TextOptions {
399 pub lex: bool,
400 pub modify: Vec<TextModifier>,
401 pub check: Option<LexCheck>,
402}
403
404impl fmt::Debug for TextOptions {
405 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
406 formatter
407 .debug_struct("TextOptions")
408 .field("lex", &self.lex)
409 .field("modify", &self.modify.len())
410 .field("check", &self.check)
411 .finish()
412 }
413}
414
415impl Default for TextOptions {
416 fn default() -> Self {
417 TextOptions {
418 lex: true,
419 modify: Vec::new(),
420 check: None,
421 }
422 }
423}
424
425#[derive(Debug, Clone)]
426pub struct SpaceOptions {
427 pub lex: bool,
428 pub chars: String,
429 pub check: Option<LexCheck>,
430}
431
432impl Default for SpaceOptions {
433 fn default() -> Self {
434 Self {
435 lex: true,
436 chars: " \t".into(),
437 check: None,
438 }
439 }
440}
441
442#[derive(Debug, Clone)]
443pub struct NumberOptions {
444 pub lex: bool,
445 pub hex: bool,
446 pub oct: bool,
447 pub bin: bool,
448 pub sep: Option<String>,
449 pub exclude: Option<String>, pub check: Option<LexCheck>,
451}
452
453impl Default for NumberOptions {
454 fn default() -> Self {
455 NumberOptions {
456 lex: true,
457 hex: true,
458 oct: true,
459 bin: true,
460 sep: Some("_".to_string()),
461 exclude: None,
462 check: None,
463 }
464 }
465}
466
467#[derive(Debug, Clone)]
468pub struct StringOptions {
469 pub lex: bool,
470 pub chars: String,
471 pub multi_chars: String,
472 pub escape_char: char,
473 pub escape: HashMap<char, String>,
474 pub replace: HashMap<char, String>,
475 pub allow_unknown: bool,
476 pub escape_strict: bool,
477 pub allow_control: bool,
478 pub abandon: bool,
479 pub check: Option<LexCheck>,
480}
481
482impl Default for StringOptions {
483 fn default() -> Self {
484 let escape = [
485 ('b', "\u{0008}"),
486 ('f', "\u{000c}"),
487 ('n', "\n"),
488 ('r', "\r"),
489 ('t', "\t"),
490 ('v', "\u{000b}"),
491 ('"', "\""),
492 ('\'', "'"),
493 ('`', "`"),
494 ('\\', "\\"),
495 ('/', "/"),
496 ]
497 .into_iter()
498 .map(|(key, value)| (key, value.into()))
499 .collect();
500 StringOptions {
501 lex: true,
502 chars: "\"'`".to_string(),
503 multi_chars: "`".to_string(),
504 escape_char: '\\',
505 escape,
506 replace: HashMap::new(),
507 allow_unknown: true,
508 escape_strict: false,
509 allow_control: false,
510 abandon: false,
511 check: None,
512 }
513 }
514}
515
516#[derive(Debug, Clone)]
517pub struct LineOptions {
518 pub lex: bool,
519 pub chars: String,
520 pub row_chars: String,
521 pub single: bool,
522 pub fixed: Vec<char>,
525 pub check: Option<LexCheck>,
526}
527
528impl Default for LineOptions {
529 fn default() -> Self {
530 Self {
531 lex: true,
532 chars: "\r\n".into(),
533 row_chars: "\n".into(),
534 single: false,
535 fixed: Vec::new(),
536 check: None,
537 }
538 }
539}
540
541#[derive(Debug, Clone)]
542pub struct CommentDef {
543 pub line: bool,
544 pub start: String,
545 pub end: String,
546 pub lex: bool,
547 pub suffixes: Vec<String>,
548 pub suffix_matcher: Option<CommentSuffixMatcher>,
549 pub eat_line: bool,
550}
551
552#[derive(Clone)]
553pub struct CommentSuffixMatcher {
554 callback: Option<Arc<CommentSuffixCallback>>,
555 imperative: Option<ImperativeCommentSuffixMatcher>,
556}
557
558type CommentSuffixCallback = dyn Fn(&str) -> Option<String> + Send + Sync;
559pub type ImperativeCommentSuffixMatcher =
560 Arc<dyn for<'source> Fn(&mut Lexer<'source>) -> Option<Token> + Send + Sync>;
561
562impl CommentSuffixMatcher {
563 pub(crate) fn new(callback: impl Fn(&str) -> Option<String> + Send + Sync + 'static) -> Self {
564 Self {
565 callback: Some(Arc::new(callback)),
566 imperative: None,
567 }
568 }
569
570 pub(crate) fn new_imperative(
571 callback: impl for<'source> Fn(&mut Lexer<'source>) -> Option<Token> + Send + Sync + 'static,
572 ) -> Self {
573 Self {
574 callback: None,
575 imperative: Some(Arc::new(callback)),
576 }
577 }
578
579 pub(crate) fn run(&self, source: &str) -> Option<String> {
580 self.callback.as_ref().and_then(|callback| callback(source))
581 }
582
583 pub(crate) fn run_imperative(&self, lexer: &mut Lexer<'_>) -> Option<Token> {
584 self.imperative
585 .as_ref()
586 .and_then(|callback| callback(lexer))
587 }
588
589 pub(crate) fn same_callback(&self, other: &Self) -> bool {
590 match (
591 &self.callback,
592 &self.imperative,
593 &other.callback,
594 &other.imperative,
595 ) {
596 (Some(left), None, Some(right), None) => Arc::ptr_eq(left, right),
597 (None, Some(left), None, Some(right)) => Arc::ptr_eq(left, right),
598 _ => false,
599 }
600 }
601}
602
603impl fmt::Debug for CommentSuffixMatcher {
604 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
605 formatter.write_str(if self.imperative.is_some() {
606 "CommentSuffixMatcher(<live lexer function>)"
607 } else {
608 "CommentSuffixMatcher(<effect function>)"
609 })
610 }
611}
612
613#[derive(Debug, Clone)]
614pub struct CommentOptions {
615 pub lex: bool,
616 pub definitions: IndexMap<String, CommentDef>,
617 pub check: Option<LexCheck>,
618}
619
620#[derive(Clone)]
621pub struct ValueDef {
622 pub val: Option<crate::Value>,
623 pub matcher: Option<Regex>,
624 pub transform: Option<ValueTransform>,
625 pub consume: bool,
626}
627
628pub type ValueTransform = Arc<dyn Fn(&[String]) -> crate::Value + Send + Sync>;
629
630impl fmt::Debug for ValueDef {
631 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
632 formatter
633 .debug_struct("ValueDef")
634 .field("val", &self.val)
635 .field("matcher", &self.matcher)
636 .field("transform", &self.transform.as_ref().map(|_| "<function>"))
637 .field("consume", &self.consume)
638 .finish()
639 }
640}
641
642#[derive(Debug, Clone)]
643pub struct ValueOptions {
644 pub lex: bool,
645 pub definitions: IndexMap<String, ValueDef>,
646}
647
648impl Default for ValueOptions {
649 fn default() -> Self {
650 let mut definitions = IndexMap::new();
651 for (source, value) in [
652 ("true", crate::Value::Bool(true)),
653 ("false", crate::Value::Bool(false)),
654 ("null", crate::Value::Null),
655 ] {
656 definitions.insert(
657 source.into(),
658 ValueDef {
659 val: Some(value),
660 matcher: None,
661 transform: None,
662 consume: false,
663 },
664 );
665 }
666 Self {
667 lex: true,
668 definitions,
669 }
670 }
671}
672
673impl Default for CommentOptions {
674 fn default() -> Self {
675 let mut definitions = IndexMap::new();
676 for (name, line, start, end) in [
677 ("hash", true, "#", ""),
678 ("slash", true, "//", ""),
679 ("multi", false, "/*", "*/"),
680 ] {
681 definitions.insert(
682 name.into(),
683 CommentDef {
684 line,
685 start: start.into(),
686 end: end.into(),
687 lex: true,
688 suffixes: Vec::new(),
689 suffix_matcher: None,
690 eat_line: false,
691 },
692 );
693 }
694 CommentOptions {
695 lex: true,
696 definitions,
697 check: None,
698 }
699 }
700}
701
702#[derive(Debug, Clone)]
703pub struct SafeOptions {
704 pub key: bool,
705}
706
707impl Default for SafeOptions {
708 fn default() -> Self {
709 Self { key: true }
710 }
711}
712
713pub type MapMerge =
714 Arc<dyn Fn(crate::Value, crate::Value, &mut Rule, &mut Context) -> crate::Value + Send + Sync>;
715
716#[derive(Clone)]
717pub struct MapOptions {
718 pub extend: bool,
719 pub merge: Option<MapMerge>,
720 pub child: bool,
721 pub ordered: bool,
726}
727
728impl fmt::Debug for MapOptions {
729 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
730 formatter
731 .debug_struct("MapOptions")
732 .field("extend", &self.extend)
733 .field("merge", &self.merge.as_ref().map(|_| "<function>"))
734 .field("child", &self.child)
735 .field("ordered", &self.ordered)
736 .finish()
737 }
738}
739
740impl Default for MapOptions {
741 fn default() -> Self {
742 MapOptions {
743 extend: true,
744 merge: None,
745 child: false,
746 ordered: false,
747 }
748 }
749}
750
751#[derive(Debug, Clone)]
752pub struct ListOptions {
753 pub property: bool,
754 pub pair: bool,
755 pub child: bool,
756}
757
758impl Default for ListOptions {
759 fn default() -> Self {
760 Self {
761 property: true,
762 pair: false,
763 child: false,
764 }
765 }
766}
767
768#[derive(Debug, Clone)]
773pub struct InfoOptions {
774 pub map: bool,
775 pub list: bool,
776 pub text: bool,
777 pub marker: String,
778}
779
780impl Default for InfoOptions {
781 fn default() -> Self {
782 Self {
783 map: false,
784 list: false,
785 text: false,
786 marker: "__info__".into(),
787 }
788 }
789}
790
791#[derive(Debug, Clone)]
792pub struct LexOptions {
793 pub empty: bool,
794 pub empty_result: crate::Value,
795 pub relex: bool,
796 pub matchers: IndexMap<String, LexMatcher>,
797}
798
799#[derive(Debug, Clone)]
800pub struct RewindOptions {
801 pub history: Option<usize>,
807}
808
809impl Default for RewindOptions {
810 fn default() -> Self {
811 Self { history: Some(64) }
812 }
813}
814
815impl Default for LexOptions {
816 fn default() -> Self {
817 LexOptions {
818 empty: true,
819 empty_result: crate::Value::Undefined,
820 relex: false,
821 matchers: IndexMap::new(),
822 }
823 }
824}
825
826#[derive(Debug, Clone, Default)]
827pub struct ResultOptions {
828 pub fail: Vec<crate::Value>,
829}
830
831pub const MAX_RULE_HISTORY: usize = 16;
843
844pub(crate) fn effective_rule_history(history: Option<usize>) -> Option<usize> {
849 history.map(|history| history.clamp(1, MAX_RULE_HISTORY))
850}
851
852#[derive(Debug, Clone)]
853pub struct RuleOptions {
854 pub finish: bool,
855 pub maxmul: usize,
856 pub include: String,
857 pub exclude: String,
858 pub start: String,
859 pub history: Option<usize>,
867}
868
869#[derive(Debug, Clone)]
870pub struct MatchToken {
871 pub name: String,
872 pub tin: Tin,
873 pub matcher: MatchTokenMatcher,
874 pub eager: bool,
875}
876
877#[derive(Clone)]
878pub struct MatchValue {
879 pub name: String,
880 pub matcher: MatchTokenMatcher,
881 pub val: Option<crate::Value>,
882 pub transform: Option<ValueTransform>,
883}
884
885impl fmt::Debug for MatchValue {
886 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
887 formatter
888 .debug_struct("MatchValue")
889 .field("name", &self.name)
890 .field("matcher", &self.matcher)
891 .field("val", &self.val)
892 .field("transform", &self.transform.as_ref().map(|_| "<function>"))
893 .finish()
894 }
895}
896
897#[derive(Debug, Clone, PartialEq)]
898pub struct MatchTokenResult {
899 pub source: String,
901 pub value: crate::Value,
903}
904
905impl MatchTokenResult {
906 pub fn new(source: impl Into<String>, value: crate::Value) -> Self {
907 Self {
908 source: source.into(),
909 value,
910 }
911 }
912}
913
914pub type MatchTokenCallback = Arc<dyn Fn(&str) -> Option<MatchTokenResult> + Send + Sync>;
915
916pub type LexMatcherCallback = Arc<dyn Fn(&str) -> Option<LexCheckToken> + Send + Sync>;
920
921pub type ImperativeLexMatcher = Arc<
924 dyn for<'source> Fn(&mut Lexer<'source>, &mut Rule, &mut Context) -> Option<Token>
925 + Send
926 + Sync,
927>;
928
929pub type LexMatcherFactory = Arc<dyn Fn(&Options) -> Option<ImperativeLexMatcher> + Send + Sync>;
932
933#[derive(Clone)]
934pub struct LexMatcher {
935 pub name: String,
936 pub order: f64,
937 pub matcher: Option<LexMatcherCallback>,
938 pub imperative: Option<ImperativeLexMatcher>,
939 pub factory: Option<LexMatcherFactory>,
940}
941
942impl fmt::Debug for LexMatcher {
943 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
944 formatter
945 .debug_struct("LexMatcher")
946 .field("name", &self.name)
947 .field("order", &self.order)
948 .field("matcher", &self.matcher.as_ref().map(|_| "<function>"))
949 .field(
950 "imperative",
951 &self.imperative.as_ref().map(|_| "<function>"),
952 )
953 .field("factory", &self.factory.as_ref().map(|_| "<function>"))
954 .finish()
955 }
956}
957
958#[derive(Clone)]
959pub enum MatchTokenMatcher {
960 Regex(Regex),
961 Callback(MatchTokenCallback),
962}
963
964impl fmt::Debug for MatchTokenMatcher {
965 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
966 match self {
967 Self::Regex(regex) => formatter.debug_tuple("Regex").field(regex).finish(),
968 Self::Callback(_) => formatter.write_str("Callback(<function>)"),
969 }
970 }
971}
972
973impl Default for RuleOptions {
974 fn default() -> Self {
975 RuleOptions {
976 finish: true,
977 maxmul: 3,
978 include: String::new(),
979 exclude: String::new(),
980 start: "val".to_string(),
981 history: None,
982 }
983 }
984}
985
986pub type BudgetCheck = Arc<dyn Fn(&Context) -> bool + Send + Sync>;
987
988#[derive(Clone, Default)]
989pub struct BudgetOptions {
990 pub check_every_n: usize,
991 pub on_check: Option<BudgetCheck>,
992}
993
994impl fmt::Debug for BudgetOptions {
995 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
996 formatter
997 .debug_struct("BudgetOptions")
998 .field("check_every_n", &self.check_every_n)
999 .field("on_check", &self.on_check.as_ref().map(|_| "<callback>"))
1000 .finish()
1001 }
1002}
1003
1004#[derive(Debug, Clone)]
1005pub struct RecoverOptions {
1006 pub enabled: bool,
1007 pub sync_groups: Vec<String>,
1008 pub sync_tokens: Vec<String>,
1009 pub pop_until_valid: bool,
1010 pub max_skip: usize,
1011 pub max_recoveries: usize,
1012 pub suppress: usize,
1013}
1014
1015impl Default for RecoverOptions {
1016 fn default() -> Self {
1017 Self {
1018 enabled: false,
1019 sync_groups: vec!["close".into(), "comma".into(), "end".into()],
1020 sync_tokens: Vec::new(),
1021 pop_until_valid: true,
1022 max_skip: 64,
1023 max_recoveries: 32,
1024 suppress: 4,
1025 }
1026 }
1027}
1028
1029pub type ContextParsePrepare = Arc<dyn Fn(&mut Context) + Send + Sync>;
1030pub type ParsePrepareWithInstance =
1031 Arc<dyn Fn(&crate::Tabnas, &mut Context, &crate::Value) + Send + Sync>;
1032
1033#[derive(Clone)]
1037pub enum ParsePrepare {
1038 Context(ContextParsePrepare),
1039 WithInstance(ParsePrepareWithInstance),
1040}
1041
1042impl ParsePrepare {
1043 pub(crate) fn same_callback(&self, other: &Self) -> bool {
1044 match (self, other) {
1045 (Self::Context(left), Self::Context(right)) => Arc::ptr_eq(left, right),
1046 (Self::WithInstance(left), Self::WithInstance(right)) => Arc::ptr_eq(left, right),
1047 _ => false,
1048 }
1049 }
1050
1051 pub(crate) fn run(
1052 &self,
1053 owner: Option<&crate::Tabnas>,
1054 context: &mut Context,
1055 meta: &crate::Value,
1056 ) -> Result<(), &'static str> {
1057 match self {
1058 Self::Context(callback) => {
1059 callback(context);
1060 Ok(())
1061 }
1062 Self::WithInstance(callback) => {
1063 let owner = owner.ok_or(
1064 "parse.prepare requires an owning Tabnas instance; call Tabnas::parse",
1065 )?;
1066 callback(owner, context, meta);
1067 Ok(())
1068 }
1069 }
1070 }
1071}
1072
1073impl fmt::Debug for ParsePrepare {
1074 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1075 match self {
1076 Self::Context(_) => formatter.write_str("ParsePrepare::Context(<function>)"),
1077 Self::WithInstance(_) => formatter.write_str("ParsePrepare::WithInstance(<function>)"),
1078 }
1079 }
1080}
1081
1082pub type ParserStart =
1083 Arc<dyn Fn(&str) -> Result<crate::Value, Box<crate::TabnasError>> + Send + Sync>;
1084pub type ParserStartWithInstance = Arc<
1085 dyn Fn(&str, &crate::Tabnas, &crate::Value) -> Result<crate::Value, Box<crate::TabnasError>>
1086 + Send
1087 + Sync,
1088>;
1089pub type ParserStartWithContext = Arc<
1090 dyn Fn(
1091 &str,
1092 &crate::Tabnas,
1093 &crate::Value,
1094 Option<&crate::ContextSeed>,
1095 ) -> Result<crate::Value, Box<crate::TabnasError>>
1096 + Send
1097 + Sync,
1098>;
1099
1100pub type DebugOutput = Arc<dyn Fn(&str) + Send + Sync>;
1101pub type DebugSourceFormatter = Arc<dyn Fn(&crate::Value) -> String + Send + Sync>;
1102
1103#[derive(Clone, Default)]
1104pub struct DebugPrintOptions {
1105 pub config: bool,
1106 pub source: Option<DebugSourceFormatter>,
1107}
1108
1109impl fmt::Debug for DebugPrintOptions {
1110 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1111 formatter
1112 .debug_struct("DebugPrintOptions")
1113 .field("config", &self.config)
1114 .field("source", &self.source.as_ref().map(|_| "<callback>"))
1115 .finish()
1116 }
1117}
1118
1119#[derive(Clone)]
1120pub struct DebugOptions {
1121 pub maxlen: usize,
1124 pub print: DebugPrintOptions,
1125 pub output: Option<DebugOutput>,
1128}
1129
1130impl Default for DebugOptions {
1131 fn default() -> Self {
1132 Self {
1133 maxlen: 99,
1134 print: DebugPrintOptions::default(),
1135 output: None,
1136 }
1137 }
1138}
1139
1140impl fmt::Debug for DebugOptions {
1141 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1142 formatter
1143 .debug_struct("DebugOptions")
1144 .field("maxlen", &self.maxlen)
1145 .field("print", &self.print)
1146 .field("output", &self.output.as_ref().map(|_| "<callback>"))
1147 .finish()
1148 }
1149}
1150
1151impl DebugOptions {
1152 pub fn format_source(&self, value: &crate::Value) -> String {
1153 if let Some(formatter) = &self.print.source {
1154 return formatter(value);
1155 }
1156 let rendered = match value {
1157 crate::Value::Undefined | crate::Value::Null => String::new(),
1158 value => serde_json::to_string(&value.to_json()).unwrap_or_else(|_| value.to_string()),
1159 };
1160 let mut chars = rendered.chars();
1161 let prefix = chars.by_ref().take(self.maxlen).collect::<String>();
1162 if chars.next().is_some() {
1163 format!("{prefix}...")
1164 } else {
1165 prefix
1166 }
1167 }
1168
1169 pub fn write(&self, message: &str) {
1170 if let Some(output) = &self.output {
1171 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| output(message)));
1175 } else {
1176 eprintln!("{message}");
1177 }
1178 }
1179}
1180
1181#[derive(Clone, Default)]
1182pub struct ParserOptions {
1183 pub start: Option<ParserStart>,
1184 pub start_with_instance: Option<ParserStartWithInstance>,
1185 pub start_with_context: Option<ParserStartWithContext>,
1186}
1187
1188impl fmt::Debug for ParserOptions {
1189 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1190 formatter
1191 .debug_struct("ParserOptions")
1192 .field("start", &self.start.as_ref().map(|_| "<callback>"))
1193 .field(
1194 "start_with_instance",
1195 &self.start_with_instance.as_ref().map(|_| "<callback>"),
1196 )
1197 .field(
1198 "start_with_context",
1199 &self.start_with_context.as_ref().map(|_| "<callback>"),
1200 )
1201 .finish()
1202 }
1203}
1204
1205#[derive(Clone, Default)]
1206pub struct ParseOptions {
1207 pub prepare: Vec<ParsePrepare>,
1208 pub named_prepare: IndexMap<String, ParsePrepare>,
1209 pub budget: BudgetOptions,
1210 pub recover: RecoverOptions,
1211}
1212
1213impl fmt::Debug for ParseOptions {
1214 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1215 formatter
1216 .debug_struct("ParseOptions")
1217 .field("prepare", &self.prepare.len())
1218 .field("named_prepare", &self.named_prepare.len())
1219 .field("budget", &self.budget)
1220 .field("recover", &self.recover)
1221 .finish()
1222 }
1223}
1224
1225#[derive(Debug, Clone)]
1226pub struct Options {
1227 pub safe: SafeOptions,
1228 pub fixed: FixedOptions,
1229 pub space: SpaceOptions,
1230 pub text: TextOptions,
1231 pub number: NumberOptions,
1232 pub string: StringOptions,
1233 pub line: LineOptions,
1234 pub comment: CommentOptions,
1235 pub value: ValueOptions,
1236 pub ender: Vec<String>,
1237 pub map: MapOptions,
1238 pub list: ListOptions,
1239 pub info: InfoOptions,
1240 pub lex: LexOptions,
1241 pub rewind: RewindOptions,
1242 pub rule: RuleOptions,
1243 pub result: ResultOptions,
1244 pub parse: ParseOptions,
1245 pub parser: ParserOptions,
1246 pub debug: DebugOptions,
1247 pub plugin: IndexMap<String, crate::Value>,
1249 pub token_set: HashMap<String, Vec<Tin>>,
1250 pub tokens: IndexMap<String, Tin>,
1253 pub match_lex: bool,
1255 pub match_check: Option<LexCheck>,
1256 pub match_tokens: IndexMap<String, MatchToken>,
1257 pub match_values: IndexMap<String, MatchValue>,
1258 pub error: HashMap<String, String>,
1259 pub hint: HashMap<String, String>,
1260 pub errmsg: ErrMsgOptions,
1261 pub color: ColorOptions,
1262 pub config_modify: IndexMap<String, ConfigModifier>,
1263 pub tag: String,
1264}
1265
1266impl Default for Options {
1267 fn default() -> Self {
1268 let mut token_set = HashMap::new();
1269 token_set.insert("IGNORE".to_string(), vec![TIN_SP, TIN_LN, TIN_CM]);
1270 token_set.insert("VAL".to_string(), vec![TIN_TX, TIN_NR, TIN_ST, TIN_VL]);
1271 token_set.insert("KEY".to_string(), vec![TIN_TX, TIN_NR, TIN_ST, TIN_VL]);
1272
1273 Options {
1274 safe: SafeOptions::default(),
1275 fixed: FixedOptions::default(),
1276 space: SpaceOptions::default(),
1277 text: TextOptions::default(),
1278 number: NumberOptions::default(),
1279 string: StringOptions::default(),
1280 line: LineOptions::default(),
1281 comment: CommentOptions::default(),
1282 value: ValueOptions::default(),
1283 ender: Vec::new(),
1284 map: MapOptions::default(),
1285 list: ListOptions::default(),
1286 info: InfoOptions::default(),
1287 lex: LexOptions::default(),
1288 rewind: RewindOptions::default(),
1289 rule: RuleOptions::default(),
1290 result: ResultOptions::default(),
1291 parse: ParseOptions::default(),
1292 parser: ParserOptions::default(),
1293 debug: DebugOptions::default(),
1294 plugin: IndexMap::new(),
1295 token_set,
1296 tokens: IndexMap::new(),
1297 match_lex: true,
1298 match_check: None,
1299 match_tokens: IndexMap::new(),
1300 match_values: IndexMap::new(),
1301 error: crate::error::default_error_messages(),
1302 hint: crate::error::default_error_hints(),
1303 errmsg: ErrMsgOptions::default(),
1304 color: ColorOptions::default(),
1305 config_modify: IndexMap::new(),
1306 tag: "-".to_string(),
1307 }
1308 }
1309}
1310
1311impl Options {
1312 pub(crate) fn validate_comment_definitions(&self) -> Result<(), String> {
1318 for (name, definition) in &self.comment.definitions {
1319 if !definition.line && definition.end.is_empty() {
1320 return Err(format!(
1321 "options.comment.def.{name}.end: block comments require a non-empty end marker"
1322 ));
1323 }
1324 }
1325 Ok(())
1326 }
1327
1328 pub fn refresh_configuration(&mut self) -> Result<(), String> {
1332 let raw_options = self.clone();
1333 let modifiers: Vec<_> = self
1334 .config_modify
1335 .iter()
1336 .map(|(name, modifier)| (name.clone(), modifier.clone()))
1337 .collect();
1338 for (name, modifier) in modifiers {
1339 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1340 modifier.run(self, &raw_options)
1341 }))
1342 .map_err(|_| format!("config modifier {name} panicked"))?;
1343 }
1344 self.validate_comment_definitions()?;
1345 self.refresh_lex_matchers()
1346 }
1347
1348 pub fn refresh_lex_matchers(&mut self) -> Result<(), String> {
1351 let factories: Vec<_> = self
1352 .lex
1353 .matchers
1354 .iter()
1355 .filter_map(|(name, matcher)| {
1356 matcher
1357 .factory
1358 .as_ref()
1359 .map(|factory| (name.clone(), factory.clone()))
1360 })
1361 .collect();
1362 for (name, factory) in factories {
1363 let matcher = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| factory(self)))
1364 .map_err(|_| format!("lexer matcher factory {name} panicked"))?;
1365 if let Some(entry) = self.lex.matchers.get_mut(&name) {
1366 entry.imperative = matcher;
1367 }
1368 }
1369 Ok(())
1370 }
1371
1372 pub fn empty() -> Self {
1376 let mut options = Self::default();
1377 options.fixed.lex = false;
1378 options.fixed.tokens.clear();
1379 options.space.lex = false;
1380 options.text.lex = false;
1381 options.number.lex = false;
1382 options.string.lex = false;
1383 options.line.lex = false;
1384 options.comment.lex = false;
1385 options.comment.definitions.clear();
1386 options.value.lex = false;
1387 options.value.definitions.clear();
1388 options.match_lex = false;
1389 options.match_tokens.clear();
1390 options.match_values.clear();
1391 options.lex.matchers.clear();
1392 options.token_set.clear();
1393 options.tokens.clear();
1394 options
1395 }
1396
1397 pub(crate) fn sort_for_lexing(&mut self) {
1403 self.match_tokens
1404 .sort_by(|_, left, _, right| left.tin.cmp(&right.tin));
1405 self.match_values.sort_keys();
1406 self.lex.matchers.sort_by(|name_a, left, name_b, right| {
1407 left.order
1408 .total_cmp(&right.order)
1409 .then_with(|| name_a.cmp(name_b))
1410 });
1411 }
1412
1413 pub fn is_ignored(&self, tin: Tin) -> bool {
1414 self.token_set
1415 .get("IGNORE")
1416 .is_some_and(|ignored| ignored.contains(&tin))
1417 }
1418
1419 pub(crate) fn ignore_tins(&self) -> Vec<Tin> {
1424 self.token_set.get("IGNORE").cloned().unwrap_or_default()
1425 }
1426
1427 pub(crate) fn char_sets(&self) -> crate::text::CharSets {
1437 crate::text::CharSets {
1438 space: crate::text::CharSet::new(&self.space.chars),
1439 line_ends: crate::text::CharSet::with_extra(&self.line.chars, &self.line.fixed),
1440 line: crate::text::CharSet::new(&self.line.chars),
1441 row: crate::text::CharSet::new(&self.line.row_chars),
1442 string: crate::text::CharSet::new(&self.string.chars),
1443 }
1444 }
1445
1446 pub fn token(&self, name: &str) -> Option<Tin> {
1447 crate::token::name_to_tin(name).or_else(|| {
1448 let name = if name.starts_with('#') {
1449 name.to_string()
1450 } else {
1451 format!("#{name}")
1452 };
1453 self.tokens
1454 .get(&name)
1455 .copied()
1456 .or_else(|| self.match_tokens.get(&name).map(|matcher| matcher.tin))
1457 .or_else(|| self.fixed.tokens.get(&name).map(|token| token.tin))
1458 })
1459 }
1460
1461 pub fn register_token(&mut self, name: impl Into<String>) -> Tin {
1462 let name = name.into();
1463 let name = if name.starts_with('#') {
1464 name
1465 } else {
1466 format!("#{name}")
1467 };
1468 if let Some(tin) = self.token(&name) {
1469 return tin;
1470 }
1471 let tin = self.next_tin();
1472 self.tokens.insert(name, tin);
1473 tin
1474 }
1475
1476 pub fn next_tin(&self) -> Tin {
1477 self.match_tokens
1478 .values()
1479 .map(|matcher| matcher.tin)
1480 .chain(self.fixed.tokens.values().map(|token| token.tin))
1481 .chain(self.tokens.values().copied())
1482 .max()
1483 .unwrap_or(TIN_MAX - 1)
1484 + 1
1485 }
1486
1487 pub fn token_name(&self, tin: Tin) -> String {
1488 self.match_tokens
1489 .values()
1490 .find(|matcher| matcher.tin == tin)
1491 .map(|matcher| matcher.name.clone())
1492 .or_else(|| {
1493 self.fixed
1494 .tokens
1495 .values()
1496 .find(|token| token.tin == tin)
1497 .map(|token| token.name.clone())
1498 })
1499 .or_else(|| {
1500 self.tokens
1501 .iter()
1502 .find(|(_, token_tin)| **token_tin == tin)
1503 .map(|(name, _)| name.clone())
1504 })
1505 .unwrap_or_else(|| crate::token::tin_name(tin).to_string())
1506 }
1507}