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,
861 pub maxmul: usize,
862 pub include: String,
863 pub exclude: String,
864 pub start: String,
865 pub history: Option<usize>,
873}
874
875#[derive(Debug, Clone)]
876pub struct MatchToken {
877 pub name: String,
878 pub tin: Tin,
879 pub matcher: MatchTokenMatcher,
880 pub eager: bool,
881}
882
883#[derive(Clone)]
884pub struct MatchValue {
885 pub name: String,
886 pub matcher: MatchTokenMatcher,
887 pub val: Option<crate::Value>,
888 pub transform: Option<ValueTransform>,
889}
890
891impl fmt::Debug for MatchValue {
892 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
893 formatter
894 .debug_struct("MatchValue")
895 .field("name", &self.name)
896 .field("matcher", &self.matcher)
897 .field("val", &self.val)
898 .field("transform", &self.transform.as_ref().map(|_| "<function>"))
899 .finish()
900 }
901}
902
903#[derive(Debug, Clone, PartialEq)]
904pub struct MatchTokenResult {
905 pub source: String,
907 pub value: crate::Value,
909}
910
911impl MatchTokenResult {
912 pub fn new(source: impl Into<String>, value: crate::Value) -> Self {
913 Self {
914 source: source.into(),
915 value,
916 }
917 }
918}
919
920pub type MatchTokenCallback = Arc<dyn Fn(&str) -> Option<MatchTokenResult> + Send + Sync>;
921
922pub type LexMatcherCallback = Arc<dyn Fn(&str) -> Option<LexCheckToken> + Send + Sync>;
926
927pub type ImperativeLexMatcher = Arc<
930 dyn for<'source> Fn(&mut Lexer<'source>, &mut Rule, &mut Context) -> Option<Token>
931 + Send
932 + Sync,
933>;
934
935pub type LexMatcherFactory = Arc<dyn Fn(&Options) -> Option<ImperativeLexMatcher> + Send + Sync>;
938
939#[derive(Clone)]
940pub struct LexMatcher {
941 pub name: String,
942 pub order: f64,
943 pub matcher: Option<LexMatcherCallback>,
944 pub imperative: Option<ImperativeLexMatcher>,
945 pub factory: Option<LexMatcherFactory>,
946}
947
948impl fmt::Debug for LexMatcher {
949 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
950 formatter
951 .debug_struct("LexMatcher")
952 .field("name", &self.name)
953 .field("order", &self.order)
954 .field("matcher", &self.matcher.as_ref().map(|_| "<function>"))
955 .field(
956 "imperative",
957 &self.imperative.as_ref().map(|_| "<function>"),
958 )
959 .field("factory", &self.factory.as_ref().map(|_| "<function>"))
960 .finish()
961 }
962}
963
964#[derive(Clone)]
965pub enum MatchTokenMatcher {
966 Regex(Regex),
967 Callback(MatchTokenCallback),
968}
969
970impl fmt::Debug for MatchTokenMatcher {
971 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
972 match self {
973 Self::Regex(regex) => formatter.debug_tuple("Regex").field(regex).finish(),
974 Self::Callback(_) => formatter.write_str("Callback(<function>)"),
975 }
976 }
977}
978
979impl Default for RuleOptions {
980 fn default() -> Self {
981 RuleOptions {
982 finish: true,
983 maxmul: 3,
984 include: String::new(),
985 exclude: String::new(),
986 start: "val".to_string(),
987 history: None,
988 }
989 }
990}
991
992pub type BudgetCheck = Arc<dyn Fn(&Context) -> bool + Send + Sync>;
993
994#[derive(Clone, Default)]
995pub struct BudgetOptions {
996 pub check_every_n: usize,
997 pub on_check: Option<BudgetCheck>,
998}
999
1000impl fmt::Debug for BudgetOptions {
1001 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1002 formatter
1003 .debug_struct("BudgetOptions")
1004 .field("check_every_n", &self.check_every_n)
1005 .field("on_check", &self.on_check.as_ref().map(|_| "<callback>"))
1006 .finish()
1007 }
1008}
1009
1010#[derive(Debug, Clone)]
1011pub struct RecoverOptions {
1012 pub enabled: bool,
1013 pub sync_groups: Vec<String>,
1014 pub sync_tokens: Vec<String>,
1015 pub pop_until_valid: bool,
1016 pub max_skip: usize,
1017 pub max_recoveries: usize,
1018 pub suppress: usize,
1019}
1020
1021impl Default for RecoverOptions {
1022 fn default() -> Self {
1023 Self {
1024 enabled: false,
1025 sync_groups: vec!["close".into(), "comma".into(), "end".into()],
1026 sync_tokens: Vec::new(),
1027 pop_until_valid: true,
1028 max_skip: 64,
1029 max_recoveries: 32,
1030 suppress: 4,
1031 }
1032 }
1033}
1034
1035pub type ContextParsePrepare = Arc<dyn Fn(&mut Context) + Send + Sync>;
1036pub type ParsePrepareWithInstance =
1037 Arc<dyn Fn(&crate::Tabnas, &mut Context, &crate::Value) + Send + Sync>;
1038
1039#[derive(Clone)]
1043pub enum ParsePrepare {
1044 Context(ContextParsePrepare),
1045 WithInstance(ParsePrepareWithInstance),
1046}
1047
1048impl ParsePrepare {
1049 pub(crate) fn same_callback(&self, other: &Self) -> bool {
1050 match (self, other) {
1051 (Self::Context(left), Self::Context(right)) => Arc::ptr_eq(left, right),
1052 (Self::WithInstance(left), Self::WithInstance(right)) => Arc::ptr_eq(left, right),
1053 _ => false,
1054 }
1055 }
1056
1057 pub(crate) fn run(
1058 &self,
1059 owner: Option<&crate::Tabnas>,
1060 context: &mut Context,
1061 meta: &crate::Value,
1062 ) -> Result<(), &'static str> {
1063 match self {
1064 Self::Context(callback) => {
1065 callback(context);
1066 Ok(())
1067 }
1068 Self::WithInstance(callback) => {
1069 let owner = owner.ok_or(
1070 "parse.prepare requires an owning Tabnas instance; call Tabnas::parse",
1071 )?;
1072 callback(owner, context, meta);
1073 Ok(())
1074 }
1075 }
1076 }
1077}
1078
1079impl fmt::Debug for ParsePrepare {
1080 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1081 match self {
1082 Self::Context(_) => formatter.write_str("ParsePrepare::Context(<function>)"),
1083 Self::WithInstance(_) => formatter.write_str("ParsePrepare::WithInstance(<function>)"),
1084 }
1085 }
1086}
1087
1088pub type ParserStart =
1089 Arc<dyn Fn(&str) -> Result<crate::Value, Box<crate::TabnasError>> + Send + Sync>;
1090pub type ParserStartWithInstance = Arc<
1091 dyn Fn(&str, &crate::Tabnas, &crate::Value) -> Result<crate::Value, Box<crate::TabnasError>>
1092 + Send
1093 + Sync,
1094>;
1095pub type ParserStartWithContext = Arc<
1096 dyn Fn(
1097 &str,
1098 &crate::Tabnas,
1099 &crate::Value,
1100 Option<&crate::ContextSeed>,
1101 ) -> Result<crate::Value, Box<crate::TabnasError>>
1102 + Send
1103 + Sync,
1104>;
1105
1106pub type DebugOutput = Arc<dyn Fn(&str) + Send + Sync>;
1107pub type DebugSourceFormatter = Arc<dyn Fn(&crate::Value) -> String + Send + Sync>;
1108
1109#[derive(Clone, Default)]
1110pub struct DebugPrintOptions {
1111 pub config: bool,
1112 pub source: Option<DebugSourceFormatter>,
1113}
1114
1115impl fmt::Debug for DebugPrintOptions {
1116 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1117 formatter
1118 .debug_struct("DebugPrintOptions")
1119 .field("config", &self.config)
1120 .field("source", &self.source.as_ref().map(|_| "<callback>"))
1121 .finish()
1122 }
1123}
1124
1125#[derive(Clone)]
1126pub struct DebugOptions {
1127 pub maxlen: usize,
1130 pub print: DebugPrintOptions,
1131 pub output: Option<DebugOutput>,
1134}
1135
1136impl Default for DebugOptions {
1137 fn default() -> Self {
1138 Self {
1139 maxlen: 99,
1140 print: DebugPrintOptions::default(),
1141 output: None,
1142 }
1143 }
1144}
1145
1146impl fmt::Debug for DebugOptions {
1147 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1148 formatter
1149 .debug_struct("DebugOptions")
1150 .field("maxlen", &self.maxlen)
1151 .field("print", &self.print)
1152 .field("output", &self.output.as_ref().map(|_| "<callback>"))
1153 .finish()
1154 }
1155}
1156
1157impl DebugOptions {
1158 pub fn format_source(&self, value: &crate::Value) -> String {
1159 if let Some(formatter) = &self.print.source {
1160 return formatter(value);
1161 }
1162 let rendered = match value {
1163 crate::Value::Undefined | crate::Value::Null => String::new(),
1164 value => serde_json::to_string(&value.to_json()).unwrap_or_else(|_| value.to_string()),
1165 };
1166 let mut chars = rendered.chars();
1167 let prefix = chars.by_ref().take(self.maxlen).collect::<String>();
1168 if chars.next().is_some() {
1169 format!("{prefix}...")
1170 } else {
1171 prefix
1172 }
1173 }
1174
1175 pub fn write(&self, message: &str) {
1176 if let Some(output) = &self.output {
1177 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| output(message)));
1181 } else {
1182 eprintln!("{message}");
1183 }
1184 }
1185}
1186
1187#[derive(Clone, Default)]
1188pub struct ParserOptions {
1189 pub start: Option<ParserStart>,
1190 pub start_with_instance: Option<ParserStartWithInstance>,
1191 pub start_with_context: Option<ParserStartWithContext>,
1192}
1193
1194impl fmt::Debug for ParserOptions {
1195 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1196 formatter
1197 .debug_struct("ParserOptions")
1198 .field("start", &self.start.as_ref().map(|_| "<callback>"))
1199 .field(
1200 "start_with_instance",
1201 &self.start_with_instance.as_ref().map(|_| "<callback>"),
1202 )
1203 .field(
1204 "start_with_context",
1205 &self.start_with_context.as_ref().map(|_| "<callback>"),
1206 )
1207 .finish()
1208 }
1209}
1210
1211#[derive(Clone, Default)]
1212pub struct ParseOptions {
1213 pub prepare: Vec<ParsePrepare>,
1214 pub named_prepare: IndexMap<String, ParsePrepare>,
1215 pub budget: BudgetOptions,
1216 pub recover: RecoverOptions,
1217}
1218
1219impl fmt::Debug for ParseOptions {
1220 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1221 formatter
1222 .debug_struct("ParseOptions")
1223 .field("prepare", &self.prepare.len())
1224 .field("named_prepare", &self.named_prepare.len())
1225 .field("budget", &self.budget)
1226 .field("recover", &self.recover)
1227 .finish()
1228 }
1229}
1230
1231#[derive(Debug, Clone)]
1232pub struct Options {
1233 pub safe: SafeOptions,
1234 pub fixed: FixedOptions,
1235 pub space: SpaceOptions,
1236 pub text: TextOptions,
1237 pub number: NumberOptions,
1238 pub string: StringOptions,
1239 pub line: LineOptions,
1240 pub comment: CommentOptions,
1241 pub value: ValueOptions,
1242 pub ender: Vec<String>,
1243 pub map: MapOptions,
1244 pub list: ListOptions,
1245 pub info: InfoOptions,
1246 pub lex: LexOptions,
1247 pub rewind: RewindOptions,
1248 pub rule: RuleOptions,
1249 pub result: ResultOptions,
1250 pub parse: ParseOptions,
1251 pub parser: ParserOptions,
1252 pub debug: DebugOptions,
1253 pub plugin: IndexMap<String, crate::Value>,
1255 pub token_set: HashMap<String, Vec<Tin>>,
1256 pub tokens: IndexMap<String, Tin>,
1259 pub match_lex: bool,
1261 pub match_check: Option<LexCheck>,
1262 pub match_tokens: IndexMap<String, MatchToken>,
1263 pub match_values: IndexMap<String, MatchValue>,
1264 pub error: HashMap<String, String>,
1265 pub hint: HashMap<String, String>,
1266 pub errmsg: ErrMsgOptions,
1267 pub color: ColorOptions,
1268 pub config_modify: IndexMap<String, ConfigModifier>,
1269 pub tag: String,
1270}
1271
1272impl Default for Options {
1273 fn default() -> Self {
1274 let mut token_set = HashMap::new();
1275 token_set.insert("IGNORE".to_string(), vec![TIN_SP, TIN_LN, TIN_CM]);
1276 token_set.insert("VAL".to_string(), vec![TIN_TX, TIN_NR, TIN_ST, TIN_VL]);
1277 token_set.insert("KEY".to_string(), vec![TIN_TX, TIN_NR, TIN_ST, TIN_VL]);
1278
1279 Options {
1280 safe: SafeOptions::default(),
1281 fixed: FixedOptions::default(),
1282 space: SpaceOptions::default(),
1283 text: TextOptions::default(),
1284 number: NumberOptions::default(),
1285 string: StringOptions::default(),
1286 line: LineOptions::default(),
1287 comment: CommentOptions::default(),
1288 value: ValueOptions::default(),
1289 ender: Vec::new(),
1290 map: MapOptions::default(),
1291 list: ListOptions::default(),
1292 info: InfoOptions::default(),
1293 lex: LexOptions::default(),
1294 rewind: RewindOptions::default(),
1295 rule: RuleOptions::default(),
1296 result: ResultOptions::default(),
1297 parse: ParseOptions::default(),
1298 parser: ParserOptions::default(),
1299 debug: DebugOptions::default(),
1300 plugin: IndexMap::new(),
1301 token_set,
1302 tokens: IndexMap::new(),
1303 match_lex: true,
1304 match_check: None,
1305 match_tokens: IndexMap::new(),
1306 match_values: IndexMap::new(),
1307 error: crate::error::default_error_messages(),
1308 hint: crate::error::default_error_hints(),
1309 errmsg: ErrMsgOptions::default(),
1310 color: ColorOptions::default(),
1311 config_modify: IndexMap::new(),
1312 tag: "-".to_string(),
1313 }
1314 }
1315}
1316
1317impl Options {
1318 pub(crate) fn validate_comment_definitions(&self) -> Result<(), String> {
1324 for (name, definition) in &self.comment.definitions {
1325 if !definition.line && definition.end.is_empty() {
1326 return Err(format!(
1327 "options.comment.def.{name}.end: block comments require a non-empty end marker"
1328 ));
1329 }
1330 }
1331 Ok(())
1332 }
1333
1334 pub fn refresh_configuration(&mut self) -> Result<(), String> {
1338 let raw_options = self.clone();
1339 let modifiers: Vec<_> = self
1340 .config_modify
1341 .iter()
1342 .map(|(name, modifier)| (name.clone(), modifier.clone()))
1343 .collect();
1344 for (name, modifier) in modifiers {
1345 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1346 modifier.run(self, &raw_options)
1347 }))
1348 .map_err(|_| format!("config modifier {name} panicked"))?;
1349 }
1350 self.validate_comment_definitions()?;
1351 self.refresh_lex_matchers()
1352 }
1353
1354 pub fn refresh_lex_matchers(&mut self) -> Result<(), String> {
1357 let factories: Vec<_> = self
1358 .lex
1359 .matchers
1360 .iter()
1361 .filter_map(|(name, matcher)| {
1362 matcher
1363 .factory
1364 .as_ref()
1365 .map(|factory| (name.clone(), factory.clone()))
1366 })
1367 .collect();
1368 for (name, factory) in factories {
1369 let matcher = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| factory(self)))
1370 .map_err(|_| format!("lexer matcher factory {name} panicked"))?;
1371 if let Some(entry) = self.lex.matchers.get_mut(&name) {
1372 entry.imperative = matcher;
1373 }
1374 }
1375 Ok(())
1376 }
1377
1378 pub fn empty() -> Self {
1382 let mut options = Self::default();
1383 options.fixed.lex = false;
1384 options.fixed.tokens.clear();
1385 options.space.lex = false;
1386 options.text.lex = false;
1387 options.number.lex = false;
1388 options.string.lex = false;
1389 options.line.lex = false;
1390 options.comment.lex = false;
1391 options.comment.definitions.clear();
1392 options.value.lex = false;
1393 options.value.definitions.clear();
1394 options.match_lex = false;
1395 options.match_tokens.clear();
1396 options.match_values.clear();
1397 options.lex.matchers.clear();
1398 options.token_set.clear();
1399 options.tokens.clear();
1400 options
1401 }
1402
1403 pub(crate) fn sort_for_lexing(&mut self) {
1409 self.match_tokens
1410 .sort_by(|_, left, _, right| left.tin.cmp(&right.tin));
1411 self.match_values.sort_keys();
1412 self.lex.matchers.sort_by(|name_a, left, name_b, right| {
1413 left.order
1414 .total_cmp(&right.order)
1415 .then_with(|| name_a.cmp(name_b))
1416 });
1417 }
1418
1419 pub fn is_ignored(&self, tin: Tin) -> bool {
1420 self.token_set
1421 .get("IGNORE")
1422 .is_some_and(|ignored| ignored.contains(&tin))
1423 }
1424
1425 pub(crate) fn ignore_tins(&self) -> Vec<Tin> {
1430 self.token_set.get("IGNORE").cloned().unwrap_or_default()
1431 }
1432
1433 pub(crate) fn char_sets(&self) -> crate::text::CharSets {
1443 crate::text::CharSets {
1444 space: crate::text::CharSet::new(&self.space.chars),
1445 line_ends: crate::text::CharSet::with_extra(&self.line.chars, &self.line.fixed),
1446 line: crate::text::CharSet::new(&self.line.chars),
1447 row: crate::text::CharSet::new(&self.line.row_chars),
1448 string: crate::text::CharSet::new(&self.string.chars),
1449 }
1450 }
1451
1452 pub fn token(&self, name: &str) -> Option<Tin> {
1453 crate::token::name_to_tin(name).or_else(|| {
1454 let name = if name.starts_with('#') {
1455 name.to_string()
1456 } else {
1457 format!("#{name}")
1458 };
1459 self.tokens
1460 .get(&name)
1461 .copied()
1462 .or_else(|| self.match_tokens.get(&name).map(|matcher| matcher.tin))
1463 .or_else(|| self.fixed.tokens.get(&name).map(|token| token.tin))
1464 })
1465 }
1466
1467 pub fn register_token(&mut self, name: impl Into<String>) -> Tin {
1468 let name = name.into();
1469 let name = if name.starts_with('#') {
1470 name
1471 } else {
1472 format!("#{name}")
1473 };
1474 if let Some(tin) = self.token(&name) {
1475 return tin;
1476 }
1477 let tin = self.next_tin();
1478 self.tokens.insert(name, tin);
1479 tin
1480 }
1481
1482 pub fn next_tin(&self) -> Tin {
1483 self.match_tokens
1484 .values()
1485 .map(|matcher| matcher.tin)
1486 .chain(self.fixed.tokens.values().map(|token| token.tin))
1487 .chain(self.tokens.values().copied())
1488 .max()
1489 .unwrap_or(TIN_MAX - 1)
1490 + 1
1491 }
1492
1493 pub fn token_name(&self, tin: Tin) -> String {
1494 self.match_tokens
1495 .values()
1496 .find(|matcher| matcher.tin == tin)
1497 .map(|matcher| matcher.name.clone())
1498 .or_else(|| {
1499 self.fixed
1500 .tokens
1501 .values()
1502 .find(|token| token.tin == tin)
1503 .map(|token| token.name.clone())
1504 })
1505 .or_else(|| {
1506 self.tokens
1507 .iter()
1508 .find(|(_, token_tin)| **token_tin == tin)
1509 .map(|(name, _)| name.clone())
1510 })
1511 .unwrap_or_else(|| crate::token::tin_name(tin).to_string())
1512 }
1513}