1#![doc = include_str!("../README.md")]
4#![allow(clippy::result_large_err)]
5
6pub const VERSION: &str = "0.12.10";
7
8pub mod builtins;
9pub mod context;
10pub mod error;
11pub mod grammar;
12pub mod lexer;
13mod merge;
14pub mod options;
15pub mod parser;
16pub mod rule;
17mod text;
18pub mod token;
19mod tracked;
20use crate::tracked::Tracked;
21pub mod utility;
22pub mod value;
23
24pub use context::{ActionError, Context, ContextSeed, InstanceInfo};
25pub use error::{RecoveredAt, TabnasError};
26pub use grammar::{
27 GrammarError, GrammarGroups, GrammarSetting, GrammarSettingAlt, GrammarSettingRule, GrammarSpec,
28};
29pub use lexer::{Lexer, RelexCheckpoint};
30pub use merge::MergeError;
31pub use options::MAX_RULE_HISTORY;
32pub use options::{
33 BudgetCheck, BudgetOptions, ColorOptions, CommentDef, CommentSuffixMatcher, ConfigModifier,
34 ContextParsePrepare, DebugOptions, DebugOutput, DebugPrintOptions, DebugSourceFormatter,
35 ErrMsgOptions, ErrorSuffix, ErrorSuffixCallback, ErrorSuffixContext, FixedOptions, FixedToken,
36 ImperativeCommentSuffixMatcher, ImperativeLexCheck, ImperativeLexMatcher,
37 ImperativeTextModifier, InfoOptions, LexCheck, LexCheckResult, LexCheckToken, LexMatcher,
38 LexMatcherCallback, LexMatcherFactory, ListOptions, MapMerge, MapOptions, MatchToken,
39 MatchTokenCallback, MatchTokenMatcher, MatchTokenResult, MatchValue, Options, ParseOptions,
40 ParsePrepare, ParsePrepareWithInstance, ParserOptions, ParserStart, ParserStartWithContext,
41 ParserStartWithInstance, RecoverOptions, ResultOptions, RewindOptions, SafeOptions,
42 SpaceOptions, TextModifier, ValueDef, ValueOptions, ValueTextModifier, ValueTransform,
43};
44pub use parser::{Continuations, ParseRecovery, Parser};
45pub use rule::{
46 ActionBinding, AltAction, AltActionBinding, AltBack, AltBackWithMatch, AltCondition,
47 AltConditionWithLexer, AltConditionWithLexerAndMatch, AltConditionWithMatch, AltError,
48 AltErrorWithMatch, AltMatch, AltModifier, AltModifierWithMatch, AltNext, AltNextWithMatch,
49 AltSpec, CompareOp, Condition, Rule, RuleDone, RuleDoneAlt, RuleName, RuleSnapshot, RuleSpec,
50 RuleState, StateAction,
51};
52pub use token::{
53 name_to_tin, tin_name, Point, Site, Tin, Token, TokenCode, TokenText, TokenValFunc, TIN_AA,
54 TIN_BD, TIN_CA, TIN_CB, TIN_CL, TIN_CM, TIN_CS, TIN_LN, TIN_MAX, TIN_NR, TIN_OB, TIN_OS,
55 TIN_SP, TIN_ST, TIN_TX, TIN_UK, TIN_VL, TIN_ZZ,
56};
57pub use value::{ListRef, MapRef, Text, Value};
58
59use indexmap::IndexMap;
60use std::any::Any;
61use std::collections::HashMap;
62use std::fmt;
63use std::panic::{catch_unwind, AssertUnwindSafe};
64use std::sync::atomic::{AtomicU64, Ordering};
65use std::sync::Arc;
66
67static NEXT_INSTANCE_ID: AtomicU64 = AtomicU64::new(1);
68
69type DecorationValue = dyn Any + Send + Sync;
70type DecorationEquality = dyn Fn(&DecorationValue) -> bool + Send + Sync;
71
72#[derive(Clone)]
79pub struct Decoration {
80 value: Arc<DecorationValue>,
81 equals: Arc<DecorationEquality>,
82 type_name: &'static str,
83}
84
85impl Decoration {
86 pub fn new<T>(value: T) -> Self
87 where
88 T: Any + PartialEq + Send + Sync,
89 {
90 let value = Arc::new(value);
91 let comparable = value.clone();
92 Self {
93 value,
94 equals: Arc::new(move |other| {
95 other
96 .downcast_ref::<T>()
97 .is_some_and(|other| comparable.as_ref() == other)
98 }),
99 type_name: std::any::type_name::<T>(),
100 }
101 }
102
103 pub fn opaque<T>(value: T) -> Self
104 where
105 T: Any + Send + Sync,
106 {
107 let value = Arc::new(value);
108 let identity = value.clone();
109 Self {
110 value,
111 equals: Arc::new(move |other| {
112 other
113 .downcast_ref::<T>()
114 .is_some_and(|other| std::ptr::eq(identity.as_ref(), other))
115 }),
116 type_name: std::any::type_name::<T>(),
117 }
118 }
119
120 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
121 self.value.downcast_ref()
122 }
123
124 pub fn is<T: Any>(&self) -> bool {
125 self.value.is::<T>()
126 }
127
128 pub fn type_name(&self) -> &'static str {
129 self.type_name
130 }
131
132 pub(crate) fn equivalent(&self, other: &Self) -> bool {
133 self.type_name == other.type_name && (self.equals)(other.value.as_ref())
134 }
135}
136
137impl fmt::Debug for Decoration {
138 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
139 formatter
140 .debug_struct("Decoration")
141 .field("type_name", &self.type_name)
142 .finish_non_exhaustive()
143 }
144}
145
146pub type Action = Arc<dyn Fn(&mut Rule) + Send + Sync>;
147pub type ContextAction =
148 Arc<dyn Fn(&mut Rule, &mut Context) -> Result<(), ActionError> + Send + Sync>;
149pub type TokenSubscriber = Arc<dyn Fn(&Token) + Send + Sync>;
150pub type LexSubscriber = Arc<dyn Fn(&mut Token, &mut Rule, &mut Context) + Send + Sync>;
151pub type RuleSubscriber = Arc<dyn Fn(&mut Rule, &mut Context) + Send + Sync>;
152pub type RuleDoneSubscriber = Arc<dyn Fn(&Rule, &Context, &RuleDone) + Send + Sync>;
153pub type ParseGuard = Arc<dyn Fn(&Context) -> bool + Send + Sync>;
155
156pub type PluginCallback = Arc<dyn Fn(&mut Tabnas, &Value) -> Result<(), PluginError> + Send + Sync>;
157
158#[derive(Clone)]
161pub struct Plugin {
162 pub name: String,
163 pub defaults: Value,
164 callback: PluginCallback,
165}
166
167impl Plugin {
168 pub fn new(
169 name: impl Into<String>,
170 callback: impl Fn(&mut Tabnas, &Value) -> Result<(), PluginError> + Send + Sync + 'static,
171 ) -> Self {
172 Self {
173 name: name.into(),
174 defaults: Value::object(IndexMap::new()),
175 callback: Arc::new(callback),
176 }
177 }
178
179 pub fn with_defaults(mut self, defaults: Value) -> Self {
180 self.defaults = defaults;
181 self
182 }
183}
184
185impl fmt::Debug for Plugin {
186 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
187 formatter
188 .debug_struct("Plugin")
189 .field("name", &self.name)
190 .field("defaults", &self.defaults)
191 .field("callback", &"<function>")
192 .finish()
193 }
194}
195
196#[derive(Debug, Clone, PartialEq, Eq)]
197pub struct PluginError(pub String);
198
199impl fmt::Display for PluginError {
200 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
201 formatter.write_str(&self.0)
202 }
203}
204
205impl std::error::Error for PluginError {}
206
207#[derive(Clone)]
208pub struct Tabnas {
209 pub id: String,
210 pub parent_id: Option<String>,
212 pub options: Tracked<Options>,
218 prepared_options: PreparedOptions,
221 prepared_parser: PreparedParser,
223 pub(crate) raw_options: Options,
227 pub rules: Tracked<IndexMap<String, RuleSpec>>,
228 pub actions: Tracked<HashMap<String, Action>>,
229 pub context_actions: Tracked<HashMap<String, ContextAction>>,
230 pub matched_actions: Tracked<HashMap<String, AltAction>>,
231 pub state_actions: Tracked<HashMap<String, StateAction>>,
232 pub token_subscribers: Tracked<Vec<TokenSubscriber>>,
233 pub lex_subscribers: Tracked<Vec<LexSubscriber>>,
234 pub rule_subscribers: Tracked<Vec<RuleSubscriber>>,
235 pub rule_done_subscribers: Tracked<Vec<RuleDoneSubscriber>>,
236 pub parse_guards: Tracked<IndexMap<String, ParseGuard>>,
239 pub plugins: Tracked<Vec<Plugin>>,
240 pub plugin_options: IndexMap<String, Value>,
241 pub decorations: IndexMap<String, Decoration>,
243 pub(crate) alt_conditions: HashMap<String, AltCondition>,
244 pub(crate) alt_match_conditions: HashMap<String, AltConditionWithMatch>,
245 pub(crate) alt_lexer_conditions: HashMap<String, AltConditionWithLexer>,
246 pub(crate) alt_lexer_match_conditions: HashMap<String, AltConditionWithLexerAndMatch>,
247 pub(crate) alt_modifiers: HashMap<String, AltModifier>,
248 pub(crate) alt_match_modifiers: HashMap<String, AltModifierWithMatch>,
249 pub(crate) alt_errors: HashMap<String, AltError>,
250 pub(crate) alt_match_errors: HashMap<String, AltErrorWithMatch>,
251 pub(crate) alt_pushes: HashMap<String, AltNext>,
252 pub(crate) alt_match_pushes: HashMap<String, AltNextWithMatch>,
253 pub(crate) alt_replaces: HashMap<String, AltNext>,
254 pub(crate) alt_match_replaces: HashMap<String, AltNextWithMatch>,
255 pub(crate) alt_backtracks: HashMap<String, AltBack>,
256 pub(crate) alt_match_backtracks: HashMap<String, AltBackWithMatch>,
257 pub(crate) match_token_refs: HashMap<String, (MatchTokenCallback, bool)>,
258 pub(crate) value_transform_refs: HashMap<String, ValueTransform>,
259 pub(crate) text_modifier_refs: HashMap<String, TextModifier>,
260 pub(crate) lex_check_refs: HashMap<String, LexCheck>,
261 pub(crate) comment_suffix_refs: HashMap<String, CommentSuffixMatcher>,
262 pub(crate) match_value_refs: HashMap<String, MatchTokenCallback>,
263 pub(crate) parse_prepare_refs: HashMap<String, ParsePrepare>,
264 pub(crate) budget_check_refs: HashMap<String, BudgetCheck>,
265 pub(crate) lex_match_refs: HashMap<String, LexMatcherCallback>,
266 pub(crate) imperative_lex_match_refs: HashMap<String, ImperativeLexMatcher>,
267 pub(crate) lex_match_factory_refs: HashMap<String, LexMatcherFactory>,
268 pub(crate) error_suffix_refs: HashMap<String, ErrorSuffixCallback>,
269 pub(crate) config_modifier_refs: HashMap<String, ConfigModifier>,
270 pub(crate) parser_start_refs: HashMap<String, ParserStart>,
271 pub(crate) parser_start_instance_refs: HashMap<String, ParserStartWithInstance>,
272 pub(crate) parser_start_context_refs: HashMap<String, ParserStartWithContext>,
273 pub(crate) map_merge_refs: HashMap<String, MapMerge>,
274}
275
276impl Default for Tabnas {
277 fn default() -> Self {
278 Self::new()
279 }
280}
281
282impl Tabnas {
283 pub fn new() -> Self {
284 Self::with_options(Options::default())
285 }
286
287 pub fn with_options(options: Options) -> Self {
288 if let Err(error) = options.validate_comment_definitions() {
289 panic!("invalid options: {error}");
290 }
291 let sequence = NEXT_INSTANCE_ID.fetch_add(1, Ordering::Relaxed);
292 let id = format!(
293 "Tabnas/{sequence}{}",
294 if options.tag.is_empty() || options.tag == "-" {
295 String::new()
296 } else {
297 format!("/{}", options.tag)
298 }
299 );
300 let plugin_options = options.plugin.clone();
301 let tabnas = Tabnas {
302 id,
303 parent_id: None,
304 raw_options: options.clone(),
305 options: Tracked::new(options),
306 prepared_options: PreparedOptions::default(),
307 prepared_parser: PreparedParser::default(),
308 rules: Tracked::new(IndexMap::new()),
309 actions: Tracked::new(HashMap::new()),
310 context_actions: Tracked::new(HashMap::new()),
311 matched_actions: Tracked::new(HashMap::new()),
312 state_actions: Tracked::new(HashMap::new()),
313 token_subscribers: Tracked::new(Vec::new()),
314 lex_subscribers: Tracked::new(Vec::new()),
315 rule_subscribers: Tracked::new(Vec::new()),
316 rule_done_subscribers: Tracked::new(Vec::new()),
317 parse_guards: Tracked::new(IndexMap::new()),
318 plugins: Tracked::new(Vec::new()),
319 plugin_options,
320 decorations: IndexMap::new(),
321 alt_conditions: HashMap::new(),
322 alt_match_conditions: HashMap::new(),
323 alt_lexer_conditions: HashMap::new(),
324 alt_lexer_match_conditions: HashMap::new(),
325 alt_modifiers: HashMap::new(),
326 alt_match_modifiers: HashMap::new(),
327 alt_errors: HashMap::new(),
328 alt_match_errors: HashMap::new(),
329 alt_pushes: HashMap::new(),
330 alt_match_pushes: HashMap::new(),
331 alt_replaces: HashMap::new(),
332 alt_match_replaces: HashMap::new(),
333 alt_backtracks: HashMap::new(),
334 alt_match_backtracks: HashMap::new(),
335 match_token_refs: HashMap::new(),
336 value_transform_refs: HashMap::new(),
337 text_modifier_refs: HashMap::new(),
338 lex_check_refs: HashMap::new(),
339 comment_suffix_refs: HashMap::new(),
340 match_value_refs: HashMap::new(),
341 parse_prepare_refs: HashMap::new(),
342 budget_check_refs: HashMap::new(),
343 lex_match_refs: HashMap::new(),
344 imperative_lex_match_refs: HashMap::new(),
345 lex_match_factory_refs: HashMap::new(),
346 error_suffix_refs: HashMap::new(),
347 config_modifier_refs: HashMap::new(),
348 parser_start_refs: HashMap::new(),
349 parser_start_instance_refs: HashMap::new(),
350 parser_start_context_refs: HashMap::new(),
351 map_merge_refs: HashMap::new(),
352 };
353 tabnas.emit_debug_config();
354 tabnas
355 }
356
357 pub fn rule(&mut self, spec: RuleSpec) -> &mut Self {
358 self.rules.insert(spec.name.clone(), spec);
359 self
360 }
361
362 pub fn define_rule(
365 &mut self,
366 name: impl Into<String>,
367 define: impl FnOnce(&mut RuleSpec),
368 ) -> &mut Self {
369 let name = name.into();
370 let spec = self
371 .rules
372 .entry(name.clone())
373 .or_insert_with(|| RuleSpec::new(name));
374 define(spec);
375 self
376 }
377
378 pub fn define_rule_with_parser(
382 &mut self,
383 name: impl Into<String>,
384 define: impl FnOnce(&mut RuleSpec, &Parser),
385 ) -> &mut Self {
386 let name = name.into();
387 self.rules
388 .entry(name.clone())
389 .or_insert_with(|| RuleSpec::new(name.clone()));
390 let parser = self.parser();
391 let spec = self
392 .rules
393 .get_mut(&name)
394 .expect("rule was inserted before its parser view was built");
395 define(spec, &parser);
396 self
397 }
398
399 pub fn remove_rule(&mut self, name: &str) -> Option<RuleSpec> {
401 self.rules.shift_remove(name)
402 }
403
404 pub fn use_plugin(
408 &mut self,
409 plugin: Plugin,
410 options: Option<Value>,
411 ) -> Result<&mut Self, PluginError> {
412 let name = plugin.name.to_lowercase();
413 if name.is_empty() {
414 return Err(PluginError(
415 "Tabnas::use_plugin: plugin name is empty".into(),
416 ));
417 }
418 let current = self
419 .plugin_options
420 .get(&name)
421 .cloned()
422 .unwrap_or_else(|| Value::object(IndexMap::new()));
423 let merged = merge_plugin_values(
424 merge_plugin_values(current, plugin.defaults.clone()),
425 options.unwrap_or(Value::Undefined),
426 );
427 self.plugin_options.insert(name.clone(), merged.clone());
428 self.options.plugin.insert(name.clone(), merged.clone());
429 self.raw_options.plugin.insert(name, merged.clone());
430 self.plugins.push(plugin.clone());
431 match catch_unwind(AssertUnwindSafe(|| (plugin.callback)(self, &merged))) {
432 Ok(Ok(())) => Ok(self),
433 Ok(Err(error)) => Err(error),
434 Err(payload) => Err(PluginError(format!(
435 "plugin {} panicked: {}",
436 plugin.name,
437 panic_message(payload)
438 ))),
439 }
440 }
441
442 pub fn plugin_options(&self, name: &str) -> Option<&Value> {
444 self.plugin_options.get(&name.to_lowercase())
445 }
446
447 pub fn set_plugin_options(&mut self, name: impl Into<String>, options: Value) -> &mut Self {
449 let name = name.into().to_lowercase();
450 let current = self
451 .plugin_options
452 .get(&name)
453 .cloned()
454 .unwrap_or_else(|| Value::object(IndexMap::new()));
455 let merged = merge_plugin_values(current, options);
456 self.plugin_options.insert(name.clone(), merged.clone());
457 self.options.plugin.insert(name.clone(), merged.clone());
458 self.raw_options.plugin.insert(name, merged);
459 self
460 }
461
462 pub fn derive(&self, modify: impl FnOnce(&mut Options)) -> Result<Self, PluginError> {
465 let mut raw_options = if self.options.config_modify.is_empty() {
466 self.options.peek().clone()
469 } else {
470 self.raw_options.clone()
471 };
472 modify(&mut raw_options);
473 let mut options = raw_options.clone();
474 options.refresh_configuration().map_err(PluginError)?;
475 let mut child = Self::with_options(options);
476 child.parent_id = Some(self.id.clone());
477 child.raw_options = raw_options;
478 child.plugin_options = self.plugin_options.clone();
479 child.decorations = self.decorations.clone();
480 child.inherit_function_references(self);
481 child.parse_guards = Tracked::new(self.parse_guards.peek().clone());
485 for plugin in self.plugins.iter() {
486 let options = child
487 .plugin_options
488 .get(&plugin.name.to_lowercase())
489 .cloned();
490 child.use_plugin(plugin.clone(), options)?;
491 }
492 Ok(child)
493 }
494
495 fn inherit_function_references(&mut self, parent: &Self) {
496 self.actions = parent.actions.clone();
502 self.context_actions = parent.context_actions.clone();
503 self.matched_actions = parent.matched_actions.clone();
504 self.state_actions = parent.state_actions.clone();
505 self.alt_conditions = parent.alt_conditions.clone();
506 self.alt_match_conditions = parent.alt_match_conditions.clone();
507 self.alt_lexer_conditions = parent.alt_lexer_conditions.clone();
508 self.alt_lexer_match_conditions = parent.alt_lexer_match_conditions.clone();
509 self.alt_modifiers = parent.alt_modifiers.clone();
510 self.alt_match_modifiers = parent.alt_match_modifiers.clone();
511 self.alt_errors = parent.alt_errors.clone();
512 self.alt_match_errors = parent.alt_match_errors.clone();
513 self.alt_pushes = parent.alt_pushes.clone();
514 self.alt_match_pushes = parent.alt_match_pushes.clone();
515 self.alt_replaces = parent.alt_replaces.clone();
516 self.alt_match_replaces = parent.alt_match_replaces.clone();
517 self.alt_backtracks = parent.alt_backtracks.clone();
518 self.alt_match_backtracks = parent.alt_match_backtracks.clone();
519 self.match_token_refs = parent.match_token_refs.clone();
520 self.value_transform_refs = parent.value_transform_refs.clone();
521 self.text_modifier_refs = parent.text_modifier_refs.clone();
522 self.lex_check_refs = parent.lex_check_refs.clone();
523 self.comment_suffix_refs = parent.comment_suffix_refs.clone();
524 self.match_value_refs = parent.match_value_refs.clone();
525 self.parse_prepare_refs = parent.parse_prepare_refs.clone();
526 self.budget_check_refs = parent.budget_check_refs.clone();
527 self.lex_match_refs = parent.lex_match_refs.clone();
528 self.imperative_lex_match_refs = parent.imperative_lex_match_refs.clone();
529 self.lex_match_factory_refs = parent.lex_match_factory_refs.clone();
530 self.error_suffix_refs = parent.error_suffix_refs.clone();
531 self.config_modifier_refs = parent.config_modifier_refs.clone();
532 self.parser_start_refs = parent.parser_start_refs.clone();
533 self.parser_start_instance_refs = parent.parser_start_instance_refs.clone();
534 self.parser_start_context_refs = parent.parser_start_context_refs.clone();
535 self.map_merge_refs = parent.map_merge_refs.clone();
536 }
537
538 pub fn merge(&self, other: &Self) -> Result<Self, MergeError> {
542 merge::merge(self, other)
543 }
544
545 pub fn empty(&self) -> Self {
548 Self::with_options(Options::empty())
549 }
550
551 pub fn empty_with_options(&self, options: Options) -> Self {
553 Self::with_options(options)
554 }
555
556 pub fn token(&mut self, name: impl Into<String>) -> Tin {
559 let name = name.into();
560 let tin = self.options.register_token(name.clone());
561 self.raw_options.register_token(name);
562 tin
563 }
564
565 pub fn token_with_source(&mut self, name: impl Into<String>, source: impl Into<String>) -> Tin {
567 let name = name.into();
568 let name = if name.starts_with('#') {
569 name
570 } else {
571 format!("#{name}")
572 };
573 let source = source.into();
574 let tin = self.token(name.clone());
575 let token = FixedToken {
576 name: name.clone(),
577 tin,
578 source,
579 };
580 self.options
581 .fixed
582 .tokens
583 .insert(name.clone(), token.clone());
584 self.raw_options.fixed.tokens.insert(name, token);
585 tin
586 }
587
588 pub fn config(&self) -> Options {
590 self.options.peek().clone()
591 }
592
593 pub fn describe(&self) -> String {
597 use std::collections::BTreeSet;
598 use std::fmt::Write as _;
599
600 let mut output = String::from("=== Tabnas Instance ===\n");
601 let _ = writeln!(output, "Id: {}", self.id);
602 let _ = writeln!(output, "Tag: {}", self.options.tag);
603
604 output.push_str("\n--- Tokens ---\n");
605 let mut token_names = BTreeSet::new();
606 token_names.extend(self.options.tokens.keys().cloned());
607 token_names.extend(self.options.fixed.tokens.keys().cloned());
608 token_names.extend(self.options.match_tokens.keys().cloned());
609 for name in token_names {
610 if let Some(tin) = self.options.token(&name) {
611 let _ = writeln!(output, " {name} = {tin}");
612 }
613 }
614
615 output.push_str("\n--- Fixed Tokens ---\n");
616 let mut fixed = self.options.fixed.tokens.values().collect::<Vec<_>>();
617 fixed.sort_by(|left, right| {
618 left.source
619 .cmp(&right.source)
620 .then_with(|| left.name.cmp(&right.name))
621 });
622 for token in fixed {
623 let _ = writeln!(
624 output,
625 " {:?} -> {} ({})",
626 token.source, token.name, token.tin
627 );
628 }
629
630 output.push_str("\n--- Rules ---\n");
631 for (name, rule) in self.rules.iter() {
632 let _ = writeln!(
633 output,
634 " {name}: open={} close={} bo={} ao={} bc={} ac={}",
635 rule.open.len(),
636 rule.close.len(),
637 rule.bo.len() + rule.bo_fns.len() + rule.bo_state_fns.len(),
638 rule.ao.len() + rule.ao_fns.len() + rule.ao_state_fns.len(),
639 rule.bc.len() + rule.bc_fns.len() + rule.bc_state_fns.len(),
640 rule.ac.len() + rule.ac_fns.len() + rule.ac_state_fns.len(),
641 );
642 }
643
644 if !self.options.lex.matchers.is_empty() {
645 output.push_str("\n--- Custom Matchers ---\n");
646 for (name, matcher) in &self.options.lex.matchers {
647 let _ = writeln!(output, " {name} (priority={})", matcher.order);
648 }
649 }
650
651 let _ = writeln!(output, "\n--- Plugins: {} ---", self.plugins.len());
652 for plugin in self.plugins.iter() {
653 let _ = writeln!(output, " {}", plugin.name);
654 }
655 output.push_str("\n--- Subscriptions ---\n");
656 let _ = writeln!(
657 output,
658 " Token subscribers: {}",
659 self.token_subscribers.len()
660 );
661 let _ = writeln!(output, " Lex subscribers: {}", self.lex_subscribers.len());
662 let _ = writeln!(
663 output,
664 " Rule subscribers: {}",
665 self.rule_subscribers.len()
666 );
667 let _ = writeln!(
668 output,
669 " RuleDone subscribers: {}",
670 self.rule_done_subscribers.len()
671 );
672 let _ = writeln!(output, " Parse guards: {}", self.parse_guards.len());
673
674 output.push_str("\n--- Config ---\n");
675 let _ = writeln!(output, " FixedLex: {}", self.options.fixed.lex);
676 let _ = writeln!(output, " SpaceLex: {}", self.options.space.lex);
677 let _ = writeln!(output, " LineLex: {}", self.options.line.lex);
678 let _ = writeln!(output, " TextLex: {}", self.options.text.lex);
679 let _ = writeln!(output, " NumberLex: {}", self.options.number.lex);
680 let _ = writeln!(output, " CommentLex: {}", self.options.comment.lex);
681 let _ = writeln!(output, " StringLex: {}", self.options.string.lex);
682 let _ = writeln!(output, " ValueLex: {}", self.options.value.lex);
683 let _ = writeln!(output, " MapExtend: {}", self.options.map.extend);
684 let _ = writeln!(output, " ListProperty: {}", self.options.list.property);
685 let _ = writeln!(output, " SafeKey: {}", self.options.safe.key);
686 let _ = writeln!(output, " FinishRule: {}", self.options.rule.finish);
687 let _ = writeln!(output, " RuleStart: {}", self.options.rule.start);
688 output
689 }
690
691 pub fn enable_trace_with(&mut self, sink: impl Fn(&str) + Send + Sync + 'static) -> &mut Self {
695 let sink = Arc::new(sink);
696 let lex_sink = sink.clone();
697 self.subscribe_lex(move |token, _, context| {
698 lex_sink(&format!(
699 "[lex] {} tin={} src={:?} val={} at {}:{}",
700 token.name,
701 token.tin,
702 token.src,
703 context.options.debug.format_source(&token.val),
704 token.site.ri,
705 token.site.ci
706 ));
707 });
708 self.subscribe_rules(move |rule, context| {
709 sink(&format!(
710 "[rule] {} state={:?} node={} ki={}",
711 rule.name,
712 rule.state,
713 context.options.debug.format_source(&rule.node.borrow()),
714 context.iteration
715 ));
716 });
717 self
718 }
719
720 pub fn enable_trace(&mut self) -> &mut Self {
721 self.subscribe_lex(|token, _, context| {
722 context.options.debug.write(&format!(
723 "[lex] {} tin={} src={:?} val={} at {}:{}",
724 token.name,
725 token.tin,
726 token.src,
727 context.options.debug.format_source(&token.val),
728 token.site.ri,
729 token.site.ci
730 ));
731 });
732 self.subscribe_rules(|rule, context| {
733 context.options.debug.write(&format!(
734 "[rule] {} state={:?} node={} ki={}",
735 rule.name,
736 rule.state,
737 context.options.debug.format_source(&rule.node.borrow()),
738 context.iteration
739 ));
740 });
741 self
742 }
743
744 pub(crate) fn emit_debug_config(&self) {
745 if self.options.debug.print.config {
746 self.options.debug.write(&format!("{:#?}", self.options));
747 }
748 }
749
750 pub fn set_options(
753 &mut self,
754 modify: impl FnOnce(&mut Options),
755 ) -> Result<&mut Self, PluginError> {
756 let mut raw_options = if self.options.config_modify.is_empty() {
757 self.options.peek().clone()
758 } else {
759 self.raw_options.clone()
760 };
761 modify(&mut raw_options);
762 let mut resolved = raw_options.clone();
763 resolved.refresh_configuration().map_err(PluginError)?;
764 self.raw_options = raw_options;
765 *self.options = resolved;
766 self.plugin_options = self.options.plugin.clone();
767 self.emit_debug_config();
768 Ok(self)
769 }
770
771 pub fn installed_plugins(&self) -> Vec<Plugin> {
773 self.plugins.peek().clone()
774 }
775
776 pub fn decorate<T>(&mut self, name: impl Into<String>, value: T) -> &mut Self
778 where
779 T: Any + PartialEq + Send + Sync,
780 {
781 self.decorations.insert(name.into(), Decoration::new(value));
782 self
783 }
784
785 pub fn decorate_opaque<T>(&mut self, name: impl Into<String>, value: T) -> &mut Self
788 where
789 T: Any + Send + Sync,
790 {
791 self.decorations
792 .insert(name.into(), Decoration::opaque(value));
793 self
794 }
795
796 pub fn decoration<T: Any>(&self, name: &str) -> Option<&T> {
797 self.decorations
798 .get(name)
799 .and_then(Decoration::downcast_ref)
800 }
801
802 pub fn decoration_entry(&self, name: &str) -> Option<&Decoration> {
803 self.decorations.get(name)
804 }
805
806 pub fn rule_specs(&self) -> Vec<&RuleSpec> {
808 self.rules.values().collect()
809 }
810
811 pub fn rule_names(&self) -> Vec<String> {
813 self.rules.keys().cloned().collect()
814 }
815
816 pub fn token_set(&self, name: &str) -> Option<Vec<Tin>> {
817 self.options
818 .token_set
819 .get(name.trim_start_matches('#'))
820 .cloned()
821 }
822
823 pub fn set_token_set(&mut self, name: impl Into<String>, tins: Vec<Tin>) -> &mut Self {
824 let name = name.into();
825 let name = name.trim_start_matches('#').to_owned();
826 self.options.token_set.insert(name.clone(), tins.clone());
827 self.raw_options.token_set.insert(name, tins);
828 self
829 }
830
831 pub fn fixed(&self, source: &str) -> Option<Tin> {
833 self.options
834 .fixed
835 .tokens
836 .values()
837 .find(|token| token.source == source)
838 .map(|token| token.tin)
839 }
840
841 pub fn fixed_source(&self, tin: Tin) -> Option<&str> {
843 self.options
844 .fixed
845 .tokens
846 .values()
847 .find(|token| token.tin == tin)
848 .map(|token| token.source.as_str())
849 }
850
851 pub fn token_name(&self, tin: Tin) -> String {
852 self.options.token_name(tin)
853 }
854
855 pub fn action(
856 &mut self,
857 name: impl Into<String>,
858 action: impl Fn(&mut Rule) + Send + Sync + 'static,
859 ) -> &mut Self {
860 self.actions.insert(name.into(), Arc::new(action));
861 self
862 }
863
864 pub fn subscribe_tokens(
865 &mut self,
866 subscriber: impl Fn(&Token) + Send + Sync + 'static,
867 ) -> &mut Self {
868 self.token_subscribers.push(Arc::new(subscriber));
869 self
870 }
871
872 pub fn subscribe_lex(
875 &mut self,
876 subscriber: impl Fn(&mut Token, &mut Rule, &mut Context) + Send + Sync + 'static,
877 ) -> &mut Self {
878 self.lex_subscribers.push(Arc::new(subscriber));
879 self
880 }
881
882 pub fn subscribe_rules(
883 &mut self,
884 subscriber: impl Fn(&mut Rule, &mut Context) + Send + Sync + 'static,
885 ) -> &mut Self {
886 self.rule_subscribers.push(Arc::new(subscriber));
887 self
888 }
889
890 pub fn subscribe_rule_done(
891 &mut self,
892 subscriber: impl Fn(&Rule, &Context, &RuleDone) + Send + Sync + 'static,
893 ) -> &mut Self {
894 self.rule_done_subscribers.push(Arc::new(subscriber));
895 self
896 }
897
898 pub fn action_with_context(
899 &mut self,
900 name: impl Into<String>,
901 action: impl Fn(&mut Rule, &mut Context) -> Result<(), ActionError> + Send + Sync + 'static,
902 ) -> &mut Self {
903 self.context_actions.insert(name.into(), Arc::new(action));
904 self
905 }
906
907 pub fn action_with_match_ref(
910 &mut self,
911 name: impl Into<String>,
912 action: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Result<Option<Token>, ActionError>
913 + Send
914 + Sync
915 + 'static,
916 ) -> &mut Self {
917 self.matched_actions.insert(name.into(), Arc::new(action));
918 self
919 }
920
921 pub fn state_action_ref(
925 &mut self,
926 name: impl Into<String>,
927 action: impl Fn(&mut Rule, &mut Context) -> Result<(), ActionError> + Send + Sync + 'static,
928 ) -> &mut Self {
929 self.context_actions.insert(name.into(), Arc::new(action));
930 self
931 }
932
933 pub fn state_action_with_next_ref(
936 &mut self,
937 name: impl Into<String>,
938 action: impl Fn(
939 &mut Rule,
940 &mut Context,
941 Option<&RuleSnapshot>,
942 Option<Token>,
943 ) -> Result<Option<Token>, ActionError>
944 + Send
945 + Sync
946 + 'static,
947 ) -> &mut Self {
948 self.state_actions.insert(name.into(), Arc::new(action));
949 self
950 }
951
952 pub fn alt_condition(
954 &mut self,
955 name: impl Into<String>,
956 condition: impl Fn(&mut Rule, &mut Context) -> bool + Send + Sync + 'static,
957 ) -> &mut Self {
958 self.alt_conditions.insert(name.into(), Arc::new(condition));
959 self
960 }
961
962 pub fn alt_condition_with_match(
965 &mut self,
966 name: impl Into<String>,
967 condition: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> bool + Send + Sync + 'static,
968 ) -> &mut Self {
969 self.alt_match_conditions
970 .insert(name.into(), Arc::new(condition));
971 self
972 }
973
974 pub fn alt_condition_with_lexer(
978 &mut self,
979 name: impl Into<String>,
980 condition: impl for<'source> Fn(&mut Rule, &mut Context, &mut Lexer<'source>) -> bool
981 + Send
982 + Sync
983 + 'static,
984 ) -> &mut Self {
985 self.alt_lexer_conditions
986 .insert(name.into(), Arc::new(condition));
987 self
988 }
989
990 pub fn alt_condition_with_lexer_and_match(
993 &mut self,
994 name: impl Into<String>,
995 condition: impl for<'source> Fn(&mut Rule, &mut Context, &mut AltMatch, &mut Lexer<'source>) -> bool
996 + Send
997 + Sync
998 + 'static,
999 ) -> &mut Self {
1000 self.alt_lexer_match_conditions
1001 .insert(name.into(), Arc::new(condition));
1002 self
1003 }
1004
1005 pub fn alt_modifier(
1007 &mut self,
1008 name: impl Into<String>,
1009 modifier: impl Fn(AltSpec, &mut Rule, &mut Context) -> AltSpec + Send + Sync + 'static,
1010 ) -> &mut Self {
1011 self.alt_modifiers.insert(name.into(), Arc::new(modifier));
1012 self
1013 }
1014
1015 pub fn alt_modifier_with_match(
1016 &mut self,
1017 name: impl Into<String>,
1018 modifier: impl Fn(AltMatch, &mut Rule, &mut Context, Option<&RuleSnapshot>) -> AltMatch
1019 + Send
1020 + Sync
1021 + 'static,
1022 ) -> &mut Self {
1023 self.alt_match_modifiers
1024 .insert(name.into(), Arc::new(modifier));
1025 self
1026 }
1027
1028 pub fn alt_error(
1030 &mut self,
1031 name: impl Into<String>,
1032 error: impl Fn(&mut Rule, &mut Context) -> Option<Token> + Send + Sync + 'static,
1033 ) -> &mut Self {
1034 self.alt_errors.insert(name.into(), Arc::new(error));
1035 self
1036 }
1037
1038 pub fn alt_error_with_match(
1039 &mut self,
1040 name: impl Into<String>,
1041 error: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Option<Token> + Send + Sync + 'static,
1042 ) -> &mut Self {
1043 self.alt_match_errors.insert(name.into(), Arc::new(error));
1044 self
1045 }
1046
1047 pub fn alt_push(
1049 &mut self,
1050 name: impl Into<String>,
1051 route: impl Fn(&mut Rule, &mut Context) -> Option<String> + Send + Sync + 'static,
1052 ) -> &mut Self {
1053 self.alt_pushes.insert(name.into(), Arc::new(route));
1054 self
1055 }
1056
1057 pub fn alt_push_with_match(
1058 &mut self,
1059 name: impl Into<String>,
1060 route: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Option<String> + Send + Sync + 'static,
1061 ) -> &mut Self {
1062 self.alt_match_pushes.insert(name.into(), Arc::new(route));
1063 self
1064 }
1065
1066 pub fn alt_replace(
1068 &mut self,
1069 name: impl Into<String>,
1070 route: impl Fn(&mut Rule, &mut Context) -> Option<String> + Send + Sync + 'static,
1071 ) -> &mut Self {
1072 self.alt_replaces.insert(name.into(), Arc::new(route));
1073 self
1074 }
1075
1076 pub fn alt_replace_with_match(
1077 &mut self,
1078 name: impl Into<String>,
1079 route: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Option<String> + Send + Sync + 'static,
1080 ) -> &mut Self {
1081 self.alt_match_replaces.insert(name.into(), Arc::new(route));
1082 self
1083 }
1084
1085 pub fn alt_backtrack(
1087 &mut self,
1088 name: impl Into<String>,
1089 backtrack: impl Fn(&mut Rule, &mut Context) -> usize + Send + Sync + 'static,
1090 ) -> &mut Self {
1091 self.alt_backtracks.insert(name.into(), Arc::new(backtrack));
1092 self
1093 }
1094
1095 pub fn alt_backtrack_with_match(
1096 &mut self,
1097 name: impl Into<String>,
1098 backtrack: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> usize + Send + Sync + 'static,
1099 ) -> &mut Self {
1100 self.alt_match_backtracks
1101 .insert(name.into(), Arc::new(backtrack));
1102 self
1103 }
1104
1105 pub fn match_token_ref(
1109 &mut self,
1110 name: impl Into<String>,
1111 eager: bool,
1112 matcher: impl Fn(&str) -> Option<MatchTokenResult> + Send + Sync + 'static,
1113 ) -> &mut Self {
1114 self.match_token_refs
1115 .insert(name.into(), (Arc::new(matcher), eager));
1116 self
1117 }
1118
1119 pub fn match_value_ref(
1122 &mut self,
1123 name: impl Into<String>,
1124 matcher: impl Fn(&str) -> Option<MatchTokenResult> + Send + Sync + 'static,
1125 ) -> &mut Self {
1126 self.match_value_refs.insert(name.into(), Arc::new(matcher));
1127 self
1128 }
1129
1130 pub fn value_transform_ref(
1137 &mut self,
1138 name: impl Into<String>,
1139 transform: impl Fn(&[String]) -> Value + Send + Sync + 'static,
1140 ) -> &mut Self {
1141 self.value_transform_refs
1142 .insert(name.into(), Arc::new(transform));
1143 self
1144 }
1145
1146 pub fn text_modifier_ref(
1149 &mut self,
1150 name: impl Into<String>,
1151 modifier: impl Fn(Value) -> Value + Send + Sync + 'static,
1152 ) -> &mut Self {
1153 self.text_modifier_refs
1154 .insert(name.into(), TextModifier::new(modifier));
1155 self
1156 }
1157
1158 pub fn imperative_text_modifier_ref(
1162 &mut self,
1163 name: impl Into<String>,
1164 modifier: impl for<'source> Fn(Value, &mut Lexer<'source>, &mut Rule, &mut Context, &Options) -> Value
1165 + Send
1166 + Sync
1167 + 'static,
1168 ) -> &mut Self {
1169 self.text_modifier_refs
1170 .insert(name.into(), TextModifier::new_imperative(modifier));
1171 self
1172 }
1173
1174 pub fn lex_check_ref(
1177 &mut self,
1178 name: impl Into<String>,
1179 check: impl Fn(&str) -> LexCheckResult + Send + Sync + 'static,
1180 ) -> &mut Self {
1181 self.lex_check_refs
1182 .insert(name.into(), LexCheck::new(check));
1183 self
1184 }
1185
1186 pub fn imperative_lex_check_ref(
1189 &mut self,
1190 name: impl Into<String>,
1191 check: impl for<'source> Fn(&mut Lexer<'source>) -> LexCheckResult + Send + Sync + 'static,
1192 ) -> &mut Self {
1193 self.lex_check_refs
1194 .insert(name.into(), LexCheck::new_imperative(check));
1195 self
1196 }
1197
1198 pub fn lex_match_ref(
1201 &mut self,
1202 name: impl Into<String>,
1203 matcher: impl Fn(&str) -> Option<LexCheckToken> + Send + Sync + 'static,
1204 ) -> &mut Self {
1205 self.lex_match_refs.insert(name.into(), Arc::new(matcher));
1206 self
1207 }
1208
1209 pub fn imperative_lex_match_ref(
1213 &mut self,
1214 name: impl Into<String>,
1215 matcher: impl for<'source> Fn(&mut Lexer<'source>, &mut Rule, &mut Context) -> Option<Token>
1216 + Send
1217 + Sync
1218 + 'static,
1219 ) -> &mut Self {
1220 self.imperative_lex_match_refs
1221 .insert(name.into(), Arc::new(matcher));
1222 self
1223 }
1224
1225 pub fn lex_match_factory_ref(
1229 &mut self,
1230 name: impl Into<String>,
1231 factory: impl Fn(&Options) -> Option<ImperativeLexMatcher> + Send + Sync + 'static,
1232 ) -> &mut Self {
1233 self.lex_match_factory_refs
1234 .insert(name.into(), Arc::new(factory));
1235 self
1236 }
1237
1238 pub fn error_suffix_ref(
1241 &mut self,
1242 name: impl Into<String>,
1243 render: impl Fn(&ErrorSuffixContext) -> String + Send + Sync + 'static,
1244 ) -> &mut Self {
1245 self.error_suffix_refs.insert(name.into(), Arc::new(render));
1246 self
1247 }
1248
1249 pub fn config_modifier_ref(
1252 &mut self,
1253 name: impl Into<String>,
1254 modifier: impl Fn(&mut Options) + Send + Sync + 'static,
1255 ) -> &mut Self {
1256 self.config_modifier_refs
1257 .insert(name.into(), ConfigModifier::new(modifier));
1258 self
1259 }
1260
1261 pub fn config_modifier_with_options_ref(
1265 &mut self,
1266 name: impl Into<String>,
1267 modifier: impl Fn(&mut Options, &Options) + Send + Sync + 'static,
1268 ) -> &mut Self {
1269 self.config_modifier_refs
1270 .insert(name.into(), ConfigModifier::with_options(modifier));
1271 self
1272 }
1273
1274 pub fn parser_start_ref(
1277 &mut self,
1278 name: impl Into<String>,
1279 start: impl Fn(&str) -> Result<Value, Box<TabnasError>> + Send + Sync + 'static,
1280 ) -> &mut Self {
1281 self.parser_start_refs.insert(name.into(), Arc::new(start));
1282 self
1283 }
1284
1285 pub fn parser_start_with_instance_ref(
1288 &mut self,
1289 name: impl Into<String>,
1290 start: impl Fn(&str, &Tabnas, &Value) -> Result<Value, Box<TabnasError>> + Send + Sync + 'static,
1291 ) -> &mut Self {
1292 self.parser_start_instance_refs
1293 .insert(name.into(), Arc::new(start));
1294 self
1295 }
1296
1297 pub fn parser_start_with_context_ref(
1300 &mut self,
1301 name: impl Into<String>,
1302 start: impl Fn(&str, &Tabnas, &Value, Option<&ContextSeed>) -> Result<Value, Box<TabnasError>>
1303 + Send
1304 + Sync
1305 + 'static,
1306 ) -> &mut Self {
1307 self.parser_start_context_refs
1308 .insert(name.into(), Arc::new(start));
1309 self
1310 }
1311
1312 pub fn map_merge_ref(
1315 &mut self,
1316 name: impl Into<String>,
1317 merge: impl Fn(Value, Value, &mut Rule, &mut Context) -> Value + Send + Sync + 'static,
1318 ) -> &mut Self {
1319 self.map_merge_refs.insert(name.into(), Arc::new(merge));
1320 self
1321 }
1322
1323 pub fn comment_suffix_ref(
1326 &mut self,
1327 name: impl Into<String>,
1328 matcher: impl Fn(&str) -> Option<String> + Send + Sync + 'static,
1329 ) -> &mut Self {
1330 self.comment_suffix_refs
1331 .insert(name.into(), CommentSuffixMatcher::new(matcher));
1332 self
1333 }
1334
1335 pub fn imperative_comment_suffix_ref(
1339 &mut self,
1340 name: impl Into<String>,
1341 matcher: impl for<'source> Fn(&mut Lexer<'source>) -> Option<Token> + Send + Sync + 'static,
1342 ) -> &mut Self {
1343 self.comment_suffix_refs
1344 .insert(name.into(), CommentSuffixMatcher::new_imperative(matcher));
1345 self
1346 }
1347
1348 pub fn parse_budget(
1349 &mut self,
1350 check_every_n: usize,
1351 check: impl Fn(&Context) -> bool + Send + Sync + 'static,
1352 ) -> &mut Self {
1353 self.options.parse.budget.check_every_n = check_every_n;
1354 self.options.parse.budget.on_check = Some(Arc::new(check));
1355 self
1356 }
1357
1358 pub fn parse_budget_ref(
1361 &mut self,
1362 name: impl Into<String>,
1363 check: impl Fn(&Context) -> bool + Send + Sync + 'static,
1364 ) -> &mut Self {
1365 self.budget_check_refs.insert(name.into(), Arc::new(check));
1366 self
1367 }
1368
1369 pub fn parse_guard(
1396 &mut self,
1397 name: impl Into<String>,
1398 check: impl Fn(&Context) -> bool + Send + Sync + 'static,
1399 ) -> &mut Self {
1400 self.parse_guards.insert(name.into(), Arc::new(check));
1401 self
1402 }
1403
1404 pub fn remove_parse_guard(&mut self, name: &str) -> &mut Self {
1407 self.parse_guards.shift_remove(name);
1408 self
1409 }
1410
1411 pub fn parse_prepare(
1412 &mut self,
1413 prepare: impl Fn(&mut Context) + Send + Sync + 'static,
1414 ) -> &mut Self {
1415 self.options
1416 .parse
1417 .prepare
1418 .push(ParsePrepare::Context(Arc::new(prepare)));
1419 self
1420 }
1421
1422 pub fn parse_prepare_with_instance(
1425 &mut self,
1426 prepare: impl Fn(&Tabnas, &mut Context, &Value) + Send + Sync + 'static,
1427 ) -> &mut Self {
1428 self.options
1429 .parse
1430 .prepare
1431 .push(ParsePrepare::WithInstance(Arc::new(prepare)));
1432 self
1433 }
1434
1435 pub fn parse_prepare_ref(
1438 &mut self,
1439 name: impl Into<String>,
1440 prepare: impl Fn(&mut Context) + Send + Sync + 'static,
1441 ) -> &mut Self {
1442 self.parse_prepare_refs
1443 .insert(name.into(), ParsePrepare::Context(Arc::new(prepare)));
1444 self
1445 }
1446
1447 pub fn parse_prepare_with_instance_ref(
1450 &mut self,
1451 name: impl Into<String>,
1452 prepare: impl Fn(&Tabnas, &mut Context, &Value) + Send + Sync + 'static,
1453 ) -> &mut Self {
1454 self.parse_prepare_refs
1455 .insert(name.into(), ParsePrepare::WithInstance(Arc::new(prepare)));
1456 self
1457 }
1458
1459 pub fn parse(&self, src: &str) -> Result<Value, TabnasError> {
1460 self.parser().parse_for(self, src, Value::Undefined)
1461 }
1462
1463 pub fn parse_with_meta(&self, src: &str, meta: Value) -> Result<Value, TabnasError> {
1464 self.parser().parse_for(self, src, meta)
1465 }
1466
1467 pub fn parse_with_context(
1468 &self,
1469 src: &str,
1470 meta: Value,
1471 parent: &ContextSeed,
1472 ) -> Result<Value, TabnasError> {
1473 self.parser()
1474 .parse_for_with_context(self, src, meta, parent)
1475 }
1476
1477 pub fn continuations(&self, src: &str) -> Continuations {
1478 self.parser().continuations_for(self, src)
1479 }
1480
1481 pub fn parse_recover(&self, src: &str) -> ParseRecovery {
1482 self.parser().parse_recover_for(self, src, Value::Undefined)
1483 }
1484
1485 pub fn parse_recover_with_meta(&self, src: &str, meta: Value) -> ParseRecovery {
1486 self.parser().parse_recover_for(self, src, meta)
1487 }
1488
1489 pub fn parse_recover_with_context(
1490 &self,
1491 src: &str,
1492 meta: Value,
1493 parent: &ContextSeed,
1494 ) -> ParseRecovery {
1495 self.parser()
1496 .parse_recover_for_with_context(self, src, meta, parent)
1497 }
1498
1499 fn grammar_generation(&self) -> u64 {
1502 self.options
1503 .generation()
1504 .wrapping_add(self.rules.generation())
1505 .wrapping_add(self.actions.generation())
1506 .wrapping_add(self.context_actions.generation())
1507 .wrapping_add(self.matched_actions.generation())
1508 .wrapping_add(self.state_actions.generation())
1509 .wrapping_add(self.token_subscribers.generation())
1510 .wrapping_add(self.lex_subscribers.generation())
1511 .wrapping_add(self.rule_subscribers.generation())
1512 .wrapping_add(self.rule_done_subscribers.generation())
1513 .wrapping_add(self.parse_guards.generation())
1514 .wrapping_add(self.plugins.generation())
1515 }
1516
1517 fn parser(&self) -> Arc<Parser> {
1518 self.prepared_parser
1519 .get(self.grammar_generation(), || self.build_parser())
1520 }
1521
1522 fn build_parser(&self) -> Parser {
1523 let mut p = Parser::from_shared(self.prepared_options.get(&self.options));
1524 p.set_instance_info(InstanceInfo {
1525 id: self.id.clone(),
1526 parent_id: self.parent_id.clone(),
1527 tag: self.options.tag.clone(),
1528 plugins: self
1529 .plugins
1530 .iter()
1531 .map(|plugin| plugin.name.clone())
1532 .collect(),
1533 rule_names: self.rule_names(),
1534 });
1535 for spec in self.rules.values() {
1536 p.add_rule(spec.clone());
1537 }
1538 for (name, action) in self.actions.iter() {
1539 p.add_action(name.clone(), action.clone());
1540 }
1541 for (name, action) in self.context_actions.iter() {
1542 p.add_context_action(name.clone(), action.clone());
1543 }
1544 for (name, action) in self.matched_actions.iter() {
1545 p.add_matched_action(name.clone(), action.clone());
1546 }
1547 for (name, action) in self.state_actions.iter() {
1548 p.add_state_action(name.clone(), action.clone());
1549 }
1550 for subscriber in self.token_subscribers.iter() {
1551 p.add_token_subscriber(subscriber.clone());
1552 }
1553 for subscriber in self.lex_subscribers.iter() {
1554 p.add_lex_subscriber(subscriber.clone());
1555 }
1556 for subscriber in self.rule_subscribers.iter() {
1557 p.add_rule_subscriber(subscriber.clone());
1558 }
1559 for subscriber in self.rule_done_subscribers.iter() {
1560 p.add_rule_done_subscriber(subscriber.clone());
1561 }
1562 for guard in self.parse_guards.values() {
1563 p.add_parse_guard(guard.clone());
1564 }
1565 p
1566 }
1567
1568 pub fn make_json() -> Self {
1577 let mut opts = Options::default();
1578 opts.text.lex = false;
1579 opts.comment.lex = false;
1580 opts.map.extend = false;
1581 opts.lex.empty = false;
1582 opts.rule.finish = false;
1583 opts.rule.include = "json".to_string();
1584
1585 opts.number.hex = false;
1586 opts.number.oct = false;
1587 opts.number.bin = false;
1588 opts.number.sep = None;
1589 opts.number.exclude = Some(r"^(?:\+|[+-]?\.|-?0\d)|\.$".to_string());
1593
1594 opts.string.chars = "\"".to_string();
1595 opts.string.multi_chars = "".to_string();
1596 opts.string.allow_unknown = false;
1597 opts.string.escape_strict = true;
1598 for escape in ['v', '\'', '`'] {
1599 opts.string.escape.remove(&escape);
1600 }
1601
1602 let mut tn = Tabnas::with_options(opts);
1603
1604 let mut val = RuleSpec::new("val");
1606 val.bo.push("@val-bo".to_string());
1607 val.bc.push("@val-bc".to_string());
1608
1609 val.open.push(AltSpec {
1611 s: vec![vec![TIN_OB]],
1612 p: Some("map".to_string()),
1613 b: 1,
1614 g: "map,json".to_string(),
1615 ..Default::default()
1616 });
1617 val.open.push(AltSpec {
1618 s: vec![vec![TIN_OS]],
1619 p: Some("list".to_string()),
1620 b: 1,
1621 g: "list,json".to_string(),
1622 ..Default::default()
1623 });
1624 val.open.push(AltSpec {
1625 s: vec![vec![TIN_TX, TIN_NR, TIN_ST, TIN_VL]],
1626 g: "val,json".to_string(),
1627 ..Default::default()
1628 });
1629
1630 val.close.push(AltSpec {
1632 s: vec![vec![TIN_ZZ]],
1633 g: "end,json".to_string(),
1634 ..Default::default()
1635 });
1636 val.close.push(AltSpec {
1637 s: vec![],
1638 b: 1,
1639 g: "more,json".to_string(),
1640 ..Default::default()
1641 });
1642 tn.rule(val);
1643
1644 let mut map = RuleSpec::new("map");
1646 map.bo.push("@map-bo".to_string());
1647 let mut n_pk = HashMap::new();
1648 n_pk.insert("pk".to_string(), 0);
1649
1650 map.open.push(AltSpec {
1651 s: vec![vec![TIN_OB], vec![TIN_CB]],
1652 b: 1,
1653 n: n_pk.clone(),
1654 g: "map,json".to_string(),
1655 ..Default::default()
1656 });
1657 map.open.push(AltSpec {
1658 s: vec![vec![TIN_OB]],
1659 p: Some("pair".to_string()),
1660 n: n_pk,
1661 g: "map,json,pair".to_string(),
1662 ..Default::default()
1663 });
1664
1665 map.close.push(AltSpec {
1666 s: vec![vec![TIN_CB]],
1667 g: "end,json".to_string(),
1668 ..Default::default()
1669 });
1670 tn.rule(map);
1671
1672 let mut list = RuleSpec::new("list");
1674 list.bo.push("@list-bo".to_string());
1675
1676 list.open.push(AltSpec {
1677 s: vec![vec![TIN_OS], vec![TIN_CS]],
1678 b: 1,
1679 g: "list,json".to_string(),
1680 ..Default::default()
1681 });
1682 list.open.push(AltSpec {
1683 s: vec![vec![TIN_OS]],
1684 p: Some("elem".to_string()),
1685 g: "list,elem,json".to_string(),
1686 ..Default::default()
1687 });
1688
1689 list.close.push(AltSpec {
1690 s: vec![vec![TIN_CS]],
1691 g: "end,json".to_string(),
1692 ..Default::default()
1693 });
1694 tn.rule(list);
1695
1696 let mut pair = RuleSpec::new("pair");
1698 pair.bc.push("@pair-bc".to_string());
1699
1700 let mut u_pair = HashMap::new();
1701 u_pair.insert("pair".to_string(), Value::Bool(true));
1702
1703 pair.open.push(AltSpec {
1704 s: vec![vec![TIN_ST], vec![TIN_CL]],
1705 p: Some("val".to_string()),
1706 u: u_pair,
1707 a: vec!["@pairkey".to_string()],
1708 g: "map,pair,key,json".to_string(),
1709 ..Default::default()
1710 });
1711
1712 pair.close.push(AltSpec {
1713 s: vec![vec![TIN_CA]],
1714 r: Some("pair".to_string()),
1715 g: "map,pair,json".to_string(),
1716 ..Default::default()
1717 });
1718 pair.close.push(AltSpec {
1719 s: vec![vec![TIN_CB]],
1720 b: 1,
1721 g: "map,pair,json".to_string(),
1722 ..Default::default()
1723 });
1724 tn.rule(pair);
1725
1726 let mut elem = RuleSpec::new("elem");
1728 elem.bc.push("@elem-bc".to_string());
1729
1730 elem.open.push(AltSpec {
1731 s: vec![],
1732 p: Some("val".to_string()),
1733 g: "list,elem,val,json".to_string(),
1734 ..Default::default()
1735 });
1736
1737 elem.close.push(AltSpec {
1738 s: vec![vec![TIN_CA]],
1739 r: Some("elem".to_string()),
1740 g: "list,elem,json".to_string(),
1741 ..Default::default()
1742 });
1743 elem.close.push(AltSpec {
1744 s: vec![vec![TIN_CS]],
1745 b: 1,
1746 g: "list,elem,json".to_string(),
1747 ..Default::default()
1748 });
1749 tn.rule(elem);
1750
1751 tn
1752 }
1753}
1754
1755impl fmt::Display for Tabnas {
1756 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1757 formatter.write_str(&self.id)
1758 }
1759}
1760
1761fn panic_message(payload: Box<dyn std::any::Any + Send>) -> String {
1762 if let Some(message) = payload.downcast_ref::<&str>() {
1763 (*message).to_string()
1764 } else if let Some(message) = payload.downcast_ref::<String>() {
1765 message.clone()
1766 } else {
1767 "non-string panic payload".into()
1768 }
1769}
1770
1771pub(crate) fn merge_plugin_values(base: Value, overlay: Value) -> Value {
1772 const DANGEROUS: [&str; 3] = ["__proto__", "constructor", "prototype"];
1773 match (base, overlay) {
1774 (base, Value::Undefined) => base,
1775 (Value::Object(base), Value::Object(overlay)) => {
1776 let mut base = crate::value::unwrap_arc(base);
1777 for (key, value) in crate::value::unwrap_arc(overlay) {
1778 if DANGEROUS.contains(&key.as_str()) {
1779 continue;
1780 }
1781 let previous = base.shift_remove(&key).unwrap_or(Value::Undefined);
1782 base.insert(key, merge_plugin_values(previous, value));
1783 }
1784 Value::object(base)
1785 }
1786 (Value::Array(base), Value::Array(overlay)) => {
1787 let length = base.len().max(overlay.len());
1788 let mut base = crate::value::unwrap_arc(base).into_iter();
1789 let mut overlay = crate::value::unwrap_arc(overlay).into_iter();
1790 Value::array(
1791 (0..length)
1792 .map(|_| match (base.next(), overlay.next()) {
1793 (Some(base), Some(overlay)) => merge_plugin_values(base, overlay),
1794 (Some(base), None) => base,
1795 (None, Some(overlay)) => overlay,
1796 (None, None) => unreachable!("length comes from both iterators"),
1797 })
1798 .collect(),
1799 )
1800 }
1801 (_, overlay) => overlay,
1802 }
1803}
1804
1805#[derive(Default)]
1813struct PreparedOptions(std::sync::Mutex<Option<(u64, Arc<Options>)>>);
1814
1815impl PreparedOptions {
1816 fn get(&self, options: &crate::tracked::Tracked<Options>) -> Arc<Options> {
1817 let generation = options.generation();
1818 let mut slot = self.0.lock().expect("prepared options lock");
1819 if let Some((prepared_at, ref prepared)) = *slot {
1820 if prepared_at == generation {
1821 return Arc::clone(prepared);
1822 }
1823 }
1824 let mut prepared_value = options.peek().clone();
1825 prepared_value.sort_for_lexing();
1826 let prepared = Arc::new(prepared_value);
1827 *slot = Some((generation, Arc::clone(&prepared)));
1828 prepared
1829 }
1830}
1831
1832impl Clone for PreparedOptions {
1835 fn clone(&self) -> Self {
1836 PreparedOptions::default()
1837 }
1838}
1839
1840#[derive(Default)]
1853struct PreparedParser(std::sync::Mutex<Option<(u64, Arc<Parser>)>>);
1854
1855impl PreparedParser {
1856 fn get(&self, generation: u64, build: impl FnOnce() -> Parser) -> Arc<Parser> {
1857 let mut slot = self.0.lock().expect("prepared parser lock");
1858 if let Some((prepared_at, ref prepared)) = *slot {
1859 if prepared_at == generation {
1860 return Arc::clone(prepared);
1861 }
1862 }
1863 let prepared = Arc::new(build());
1864 *slot = Some((generation, Arc::clone(&prepared)));
1865 prepared
1866 }
1867}
1868
1869impl Clone for PreparedParser {
1870 fn clone(&self) -> Self {
1871 PreparedParser::default()
1872 }
1873}