1#![doc = include_str!("../README.md")]
4#![allow(clippy::result_large_err)]
5
6pub const VERSION: &str = "0.12.8";
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 let sequence = NEXT_INSTANCE_ID.fetch_add(1, Ordering::Relaxed);
289 let id = format!(
290 "Tabnas/{sequence}{}",
291 if options.tag.is_empty() || options.tag == "-" {
292 String::new()
293 } else {
294 format!("/{}", options.tag)
295 }
296 );
297 let plugin_options = options.plugin.clone();
298 let tabnas = Tabnas {
299 id,
300 parent_id: None,
301 raw_options: options.clone(),
302 options: Tracked::new(options),
303 prepared_options: PreparedOptions::default(),
304 prepared_parser: PreparedParser::default(),
305 rules: Tracked::new(IndexMap::new()),
306 actions: Tracked::new(HashMap::new()),
307 context_actions: Tracked::new(HashMap::new()),
308 matched_actions: Tracked::new(HashMap::new()),
309 state_actions: Tracked::new(HashMap::new()),
310 token_subscribers: Tracked::new(Vec::new()),
311 lex_subscribers: Tracked::new(Vec::new()),
312 rule_subscribers: Tracked::new(Vec::new()),
313 rule_done_subscribers: Tracked::new(Vec::new()),
314 parse_guards: Tracked::new(IndexMap::new()),
315 plugins: Tracked::new(Vec::new()),
316 plugin_options,
317 decorations: IndexMap::new(),
318 alt_conditions: HashMap::new(),
319 alt_match_conditions: HashMap::new(),
320 alt_lexer_conditions: HashMap::new(),
321 alt_lexer_match_conditions: HashMap::new(),
322 alt_modifiers: HashMap::new(),
323 alt_match_modifiers: HashMap::new(),
324 alt_errors: HashMap::new(),
325 alt_match_errors: HashMap::new(),
326 alt_pushes: HashMap::new(),
327 alt_match_pushes: HashMap::new(),
328 alt_replaces: HashMap::new(),
329 alt_match_replaces: HashMap::new(),
330 alt_backtracks: HashMap::new(),
331 alt_match_backtracks: HashMap::new(),
332 match_token_refs: HashMap::new(),
333 value_transform_refs: HashMap::new(),
334 text_modifier_refs: HashMap::new(),
335 lex_check_refs: HashMap::new(),
336 comment_suffix_refs: HashMap::new(),
337 match_value_refs: HashMap::new(),
338 parse_prepare_refs: HashMap::new(),
339 budget_check_refs: HashMap::new(),
340 lex_match_refs: HashMap::new(),
341 imperative_lex_match_refs: HashMap::new(),
342 lex_match_factory_refs: HashMap::new(),
343 error_suffix_refs: HashMap::new(),
344 config_modifier_refs: HashMap::new(),
345 parser_start_refs: HashMap::new(),
346 parser_start_instance_refs: HashMap::new(),
347 parser_start_context_refs: HashMap::new(),
348 map_merge_refs: HashMap::new(),
349 };
350 tabnas.emit_debug_config();
351 tabnas
352 }
353
354 pub fn rule(&mut self, spec: RuleSpec) -> &mut Self {
355 self.rules.insert(spec.name.clone(), spec);
356 self
357 }
358
359 pub fn define_rule(
362 &mut self,
363 name: impl Into<String>,
364 define: impl FnOnce(&mut RuleSpec),
365 ) -> &mut Self {
366 let name = name.into();
367 let spec = self
368 .rules
369 .entry(name.clone())
370 .or_insert_with(|| RuleSpec::new(name));
371 define(spec);
372 self
373 }
374
375 pub fn define_rule_with_parser(
379 &mut self,
380 name: impl Into<String>,
381 define: impl FnOnce(&mut RuleSpec, &Parser),
382 ) -> &mut Self {
383 let name = name.into();
384 self.rules
385 .entry(name.clone())
386 .or_insert_with(|| RuleSpec::new(name.clone()));
387 let parser = self.parser();
388 let spec = self
389 .rules
390 .get_mut(&name)
391 .expect("rule was inserted before its parser view was built");
392 define(spec, &parser);
393 self
394 }
395
396 pub fn remove_rule(&mut self, name: &str) -> Option<RuleSpec> {
398 self.rules.shift_remove(name)
399 }
400
401 pub fn use_plugin(
405 &mut self,
406 plugin: Plugin,
407 options: Option<Value>,
408 ) -> Result<&mut Self, PluginError> {
409 let name = plugin.name.to_lowercase();
410 if name.is_empty() {
411 return Err(PluginError(
412 "Tabnas::use_plugin: plugin name is empty".into(),
413 ));
414 }
415 let current = self
416 .plugin_options
417 .get(&name)
418 .cloned()
419 .unwrap_or_else(|| Value::object(IndexMap::new()));
420 let merged = merge_plugin_values(
421 merge_plugin_values(current, plugin.defaults.clone()),
422 options.unwrap_or(Value::Undefined),
423 );
424 self.plugin_options.insert(name.clone(), merged.clone());
425 self.options.plugin.insert(name.clone(), merged.clone());
426 self.raw_options.plugin.insert(name, merged.clone());
427 self.plugins.push(plugin.clone());
428 match catch_unwind(AssertUnwindSafe(|| (plugin.callback)(self, &merged))) {
429 Ok(Ok(())) => Ok(self),
430 Ok(Err(error)) => Err(error),
431 Err(payload) => Err(PluginError(format!(
432 "plugin {} panicked: {}",
433 plugin.name,
434 panic_message(payload)
435 ))),
436 }
437 }
438
439 pub fn plugin_options(&self, name: &str) -> Option<&Value> {
441 self.plugin_options.get(&name.to_lowercase())
442 }
443
444 pub fn set_plugin_options(&mut self, name: impl Into<String>, options: Value) -> &mut Self {
446 let name = name.into().to_lowercase();
447 let current = self
448 .plugin_options
449 .get(&name)
450 .cloned()
451 .unwrap_or_else(|| Value::object(IndexMap::new()));
452 let merged = merge_plugin_values(current, options);
453 self.plugin_options.insert(name.clone(), merged.clone());
454 self.options.plugin.insert(name.clone(), merged.clone());
455 self.raw_options.plugin.insert(name, merged);
456 self
457 }
458
459 pub fn derive(&self, modify: impl FnOnce(&mut Options)) -> Result<Self, PluginError> {
462 let mut raw_options = if self.options.config_modify.is_empty() {
463 self.options.peek().clone()
466 } else {
467 self.raw_options.clone()
468 };
469 modify(&mut raw_options);
470 let mut options = raw_options.clone();
471 options.refresh_configuration().map_err(PluginError)?;
472 let mut child = Self::with_options(options);
473 child.parent_id = Some(self.id.clone());
474 child.raw_options = raw_options;
475 child.plugin_options = self.plugin_options.clone();
476 child.decorations = self.decorations.clone();
477 child.inherit_function_references(self);
478 child.parse_guards = Tracked::new(self.parse_guards.peek().clone());
482 for plugin in self.plugins.iter() {
483 let options = child
484 .plugin_options
485 .get(&plugin.name.to_lowercase())
486 .cloned();
487 child.use_plugin(plugin.clone(), options)?;
488 }
489 Ok(child)
490 }
491
492 fn inherit_function_references(&mut self, parent: &Self) {
493 self.actions = parent.actions.clone();
499 self.context_actions = parent.context_actions.clone();
500 self.matched_actions = parent.matched_actions.clone();
501 self.state_actions = parent.state_actions.clone();
502 self.alt_conditions = parent.alt_conditions.clone();
503 self.alt_match_conditions = parent.alt_match_conditions.clone();
504 self.alt_lexer_conditions = parent.alt_lexer_conditions.clone();
505 self.alt_lexer_match_conditions = parent.alt_lexer_match_conditions.clone();
506 self.alt_modifiers = parent.alt_modifiers.clone();
507 self.alt_match_modifiers = parent.alt_match_modifiers.clone();
508 self.alt_errors = parent.alt_errors.clone();
509 self.alt_match_errors = parent.alt_match_errors.clone();
510 self.alt_pushes = parent.alt_pushes.clone();
511 self.alt_match_pushes = parent.alt_match_pushes.clone();
512 self.alt_replaces = parent.alt_replaces.clone();
513 self.alt_match_replaces = parent.alt_match_replaces.clone();
514 self.alt_backtracks = parent.alt_backtracks.clone();
515 self.alt_match_backtracks = parent.alt_match_backtracks.clone();
516 self.match_token_refs = parent.match_token_refs.clone();
517 self.value_transform_refs = parent.value_transform_refs.clone();
518 self.text_modifier_refs = parent.text_modifier_refs.clone();
519 self.lex_check_refs = parent.lex_check_refs.clone();
520 self.comment_suffix_refs = parent.comment_suffix_refs.clone();
521 self.match_value_refs = parent.match_value_refs.clone();
522 self.parse_prepare_refs = parent.parse_prepare_refs.clone();
523 self.budget_check_refs = parent.budget_check_refs.clone();
524 self.lex_match_refs = parent.lex_match_refs.clone();
525 self.imperative_lex_match_refs = parent.imperative_lex_match_refs.clone();
526 self.lex_match_factory_refs = parent.lex_match_factory_refs.clone();
527 self.error_suffix_refs = parent.error_suffix_refs.clone();
528 self.config_modifier_refs = parent.config_modifier_refs.clone();
529 self.parser_start_refs = parent.parser_start_refs.clone();
530 self.parser_start_instance_refs = parent.parser_start_instance_refs.clone();
531 self.parser_start_context_refs = parent.parser_start_context_refs.clone();
532 self.map_merge_refs = parent.map_merge_refs.clone();
533 }
534
535 pub fn merge(&self, other: &Self) -> Result<Self, MergeError> {
539 merge::merge(self, other)
540 }
541
542 pub fn empty(&self) -> Self {
545 Self::with_options(Options::empty())
546 }
547
548 pub fn empty_with_options(&self, options: Options) -> Self {
550 Self::with_options(options)
551 }
552
553 pub fn token(&mut self, name: impl Into<String>) -> Tin {
556 let name = name.into();
557 let tin = self.options.register_token(name.clone());
558 self.raw_options.register_token(name);
559 tin
560 }
561
562 pub fn token_with_source(&mut self, name: impl Into<String>, source: impl Into<String>) -> Tin {
564 let name = name.into();
565 let name = if name.starts_with('#') {
566 name
567 } else {
568 format!("#{name}")
569 };
570 let source = source.into();
571 let tin = self.token(name.clone());
572 let token = FixedToken {
573 name: name.clone(),
574 tin,
575 source,
576 };
577 self.options
578 .fixed
579 .tokens
580 .insert(name.clone(), token.clone());
581 self.raw_options.fixed.tokens.insert(name, token);
582 tin
583 }
584
585 pub fn config(&self) -> Options {
587 self.options.peek().clone()
588 }
589
590 pub fn describe(&self) -> String {
594 use std::collections::BTreeSet;
595 use std::fmt::Write as _;
596
597 let mut output = String::from("=== Tabnas Instance ===\n");
598 let _ = writeln!(output, "Id: {}", self.id);
599 let _ = writeln!(output, "Tag: {}", self.options.tag);
600
601 output.push_str("\n--- Tokens ---\n");
602 let mut token_names = BTreeSet::new();
603 token_names.extend(self.options.tokens.keys().cloned());
604 token_names.extend(self.options.fixed.tokens.keys().cloned());
605 token_names.extend(self.options.match_tokens.keys().cloned());
606 for name in token_names {
607 if let Some(tin) = self.options.token(&name) {
608 let _ = writeln!(output, " {name} = {tin}");
609 }
610 }
611
612 output.push_str("\n--- Fixed Tokens ---\n");
613 let mut fixed = self.options.fixed.tokens.values().collect::<Vec<_>>();
614 fixed.sort_by(|left, right| {
615 left.source
616 .cmp(&right.source)
617 .then_with(|| left.name.cmp(&right.name))
618 });
619 for token in fixed {
620 let _ = writeln!(
621 output,
622 " {:?} -> {} ({})",
623 token.source, token.name, token.tin
624 );
625 }
626
627 output.push_str("\n--- Rules ---\n");
628 for (name, rule) in self.rules.iter() {
629 let _ = writeln!(
630 output,
631 " {name}: open={} close={} bo={} ao={} bc={} ac={}",
632 rule.open.len(),
633 rule.close.len(),
634 rule.bo.len() + rule.bo_fns.len() + rule.bo_state_fns.len(),
635 rule.ao.len() + rule.ao_fns.len() + rule.ao_state_fns.len(),
636 rule.bc.len() + rule.bc_fns.len() + rule.bc_state_fns.len(),
637 rule.ac.len() + rule.ac_fns.len() + rule.ac_state_fns.len(),
638 );
639 }
640
641 if !self.options.lex.matchers.is_empty() {
642 output.push_str("\n--- Custom Matchers ---\n");
643 for (name, matcher) in &self.options.lex.matchers {
644 let _ = writeln!(output, " {name} (priority={})", matcher.order);
645 }
646 }
647
648 let _ = writeln!(output, "\n--- Plugins: {} ---", self.plugins.len());
649 for plugin in self.plugins.iter() {
650 let _ = writeln!(output, " {}", plugin.name);
651 }
652 output.push_str("\n--- Subscriptions ---\n");
653 let _ = writeln!(
654 output,
655 " Token subscribers: {}",
656 self.token_subscribers.len()
657 );
658 let _ = writeln!(output, " Lex subscribers: {}", self.lex_subscribers.len());
659 let _ = writeln!(
660 output,
661 " Rule subscribers: {}",
662 self.rule_subscribers.len()
663 );
664 let _ = writeln!(
665 output,
666 " RuleDone subscribers: {}",
667 self.rule_done_subscribers.len()
668 );
669 let _ = writeln!(output, " Parse guards: {}", self.parse_guards.len());
670
671 output.push_str("\n--- Config ---\n");
672 let _ = writeln!(output, " FixedLex: {}", self.options.fixed.lex);
673 let _ = writeln!(output, " SpaceLex: {}", self.options.space.lex);
674 let _ = writeln!(output, " LineLex: {}", self.options.line.lex);
675 let _ = writeln!(output, " TextLex: {}", self.options.text.lex);
676 let _ = writeln!(output, " NumberLex: {}", self.options.number.lex);
677 let _ = writeln!(output, " CommentLex: {}", self.options.comment.lex);
678 let _ = writeln!(output, " StringLex: {}", self.options.string.lex);
679 let _ = writeln!(output, " ValueLex: {}", self.options.value.lex);
680 let _ = writeln!(output, " MapExtend: {}", self.options.map.extend);
681 let _ = writeln!(output, " ListProperty: {}", self.options.list.property);
682 let _ = writeln!(output, " SafeKey: {}", self.options.safe.key);
683 let _ = writeln!(output, " FinishRule: {}", self.options.rule.finish);
684 let _ = writeln!(output, " RuleStart: {}", self.options.rule.start);
685 output
686 }
687
688 pub fn enable_trace_with(&mut self, sink: impl Fn(&str) + Send + Sync + 'static) -> &mut Self {
692 let sink = Arc::new(sink);
693 let lex_sink = sink.clone();
694 self.subscribe_lex(move |token, _, context| {
695 lex_sink(&format!(
696 "[lex] {} tin={} src={:?} val={} at {}:{}",
697 token.name,
698 token.tin,
699 token.src,
700 context.options.debug.format_source(&token.val),
701 token.site.ri,
702 token.site.ci
703 ));
704 });
705 self.subscribe_rules(move |rule, context| {
706 sink(&format!(
707 "[rule] {} state={:?} node={} ki={}",
708 rule.name,
709 rule.state,
710 context.options.debug.format_source(&rule.node.borrow()),
711 context.iteration
712 ));
713 });
714 self
715 }
716
717 pub fn enable_trace(&mut self) -> &mut Self {
718 self.subscribe_lex(|token, _, context| {
719 context.options.debug.write(&format!(
720 "[lex] {} tin={} src={:?} val={} at {}:{}",
721 token.name,
722 token.tin,
723 token.src,
724 context.options.debug.format_source(&token.val),
725 token.site.ri,
726 token.site.ci
727 ));
728 });
729 self.subscribe_rules(|rule, context| {
730 context.options.debug.write(&format!(
731 "[rule] {} state={:?} node={} ki={}",
732 rule.name,
733 rule.state,
734 context.options.debug.format_source(&rule.node.borrow()),
735 context.iteration
736 ));
737 });
738 self
739 }
740
741 pub(crate) fn emit_debug_config(&self) {
742 if self.options.debug.print.config {
743 self.options.debug.write(&format!("{:#?}", self.options));
744 }
745 }
746
747 pub fn set_options(
750 &mut self,
751 modify: impl FnOnce(&mut Options),
752 ) -> Result<&mut Self, PluginError> {
753 let mut raw_options = if self.options.config_modify.is_empty() {
754 self.options.peek().clone()
755 } else {
756 self.raw_options.clone()
757 };
758 modify(&mut raw_options);
759 let mut resolved = raw_options.clone();
760 resolved.refresh_configuration().map_err(PluginError)?;
761 self.raw_options = raw_options;
762 *self.options = resolved;
763 self.plugin_options = self.options.plugin.clone();
764 self.emit_debug_config();
765 Ok(self)
766 }
767
768 pub fn installed_plugins(&self) -> Vec<Plugin> {
770 self.plugins.peek().clone()
771 }
772
773 pub fn decorate<T>(&mut self, name: impl Into<String>, value: T) -> &mut Self
775 where
776 T: Any + PartialEq + Send + Sync,
777 {
778 self.decorations.insert(name.into(), Decoration::new(value));
779 self
780 }
781
782 pub fn decorate_opaque<T>(&mut self, name: impl Into<String>, value: T) -> &mut Self
785 where
786 T: Any + Send + Sync,
787 {
788 self.decorations
789 .insert(name.into(), Decoration::opaque(value));
790 self
791 }
792
793 pub fn decoration<T: Any>(&self, name: &str) -> Option<&T> {
794 self.decorations
795 .get(name)
796 .and_then(Decoration::downcast_ref)
797 }
798
799 pub fn decoration_entry(&self, name: &str) -> Option<&Decoration> {
800 self.decorations.get(name)
801 }
802
803 pub fn rule_specs(&self) -> Vec<&RuleSpec> {
805 self.rules.values().collect()
806 }
807
808 pub fn rule_names(&self) -> Vec<String> {
810 self.rules.keys().cloned().collect()
811 }
812
813 pub fn token_set(&self, name: &str) -> Option<Vec<Tin>> {
814 self.options
815 .token_set
816 .get(name.trim_start_matches('#'))
817 .cloned()
818 }
819
820 pub fn set_token_set(&mut self, name: impl Into<String>, tins: Vec<Tin>) -> &mut Self {
821 let name = name.into();
822 let name = name.trim_start_matches('#').to_owned();
823 self.options.token_set.insert(name.clone(), tins.clone());
824 self.raw_options.token_set.insert(name, tins);
825 self
826 }
827
828 pub fn fixed(&self, source: &str) -> Option<Tin> {
830 self.options
831 .fixed
832 .tokens
833 .values()
834 .find(|token| token.source == source)
835 .map(|token| token.tin)
836 }
837
838 pub fn fixed_source(&self, tin: Tin) -> Option<&str> {
840 self.options
841 .fixed
842 .tokens
843 .values()
844 .find(|token| token.tin == tin)
845 .map(|token| token.source.as_str())
846 }
847
848 pub fn token_name(&self, tin: Tin) -> String {
849 self.options.token_name(tin)
850 }
851
852 pub fn action(
853 &mut self,
854 name: impl Into<String>,
855 action: impl Fn(&mut Rule) + Send + Sync + 'static,
856 ) -> &mut Self {
857 self.actions.insert(name.into(), Arc::new(action));
858 self
859 }
860
861 pub fn subscribe_tokens(
862 &mut self,
863 subscriber: impl Fn(&Token) + Send + Sync + 'static,
864 ) -> &mut Self {
865 self.token_subscribers.push(Arc::new(subscriber));
866 self
867 }
868
869 pub fn subscribe_lex(
872 &mut self,
873 subscriber: impl Fn(&mut Token, &mut Rule, &mut Context) + Send + Sync + 'static,
874 ) -> &mut Self {
875 self.lex_subscribers.push(Arc::new(subscriber));
876 self
877 }
878
879 pub fn subscribe_rules(
880 &mut self,
881 subscriber: impl Fn(&mut Rule, &mut Context) + Send + Sync + 'static,
882 ) -> &mut Self {
883 self.rule_subscribers.push(Arc::new(subscriber));
884 self
885 }
886
887 pub fn subscribe_rule_done(
888 &mut self,
889 subscriber: impl Fn(&Rule, &Context, &RuleDone) + Send + Sync + 'static,
890 ) -> &mut Self {
891 self.rule_done_subscribers.push(Arc::new(subscriber));
892 self
893 }
894
895 pub fn action_with_context(
896 &mut self,
897 name: impl Into<String>,
898 action: impl Fn(&mut Rule, &mut Context) -> Result<(), ActionError> + Send + Sync + 'static,
899 ) -> &mut Self {
900 self.context_actions.insert(name.into(), Arc::new(action));
901 self
902 }
903
904 pub fn action_with_match_ref(
907 &mut self,
908 name: impl Into<String>,
909 action: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Result<Option<Token>, ActionError>
910 + Send
911 + Sync
912 + 'static,
913 ) -> &mut Self {
914 self.matched_actions.insert(name.into(), Arc::new(action));
915 self
916 }
917
918 pub fn state_action_ref(
922 &mut self,
923 name: impl Into<String>,
924 action: impl Fn(&mut Rule, &mut Context) -> Result<(), ActionError> + Send + Sync + 'static,
925 ) -> &mut Self {
926 self.context_actions.insert(name.into(), Arc::new(action));
927 self
928 }
929
930 pub fn state_action_with_next_ref(
933 &mut self,
934 name: impl Into<String>,
935 action: impl Fn(
936 &mut Rule,
937 &mut Context,
938 Option<&RuleSnapshot>,
939 Option<Token>,
940 ) -> Result<Option<Token>, ActionError>
941 + Send
942 + Sync
943 + 'static,
944 ) -> &mut Self {
945 self.state_actions.insert(name.into(), Arc::new(action));
946 self
947 }
948
949 pub fn alt_condition(
951 &mut self,
952 name: impl Into<String>,
953 condition: impl Fn(&mut Rule, &mut Context) -> bool + Send + Sync + 'static,
954 ) -> &mut Self {
955 self.alt_conditions.insert(name.into(), Arc::new(condition));
956 self
957 }
958
959 pub fn alt_condition_with_match(
962 &mut self,
963 name: impl Into<String>,
964 condition: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> bool + Send + Sync + 'static,
965 ) -> &mut Self {
966 self.alt_match_conditions
967 .insert(name.into(), Arc::new(condition));
968 self
969 }
970
971 pub fn alt_condition_with_lexer(
975 &mut self,
976 name: impl Into<String>,
977 condition: impl for<'source> Fn(&mut Rule, &mut Context, &mut Lexer<'source>) -> bool
978 + Send
979 + Sync
980 + 'static,
981 ) -> &mut Self {
982 self.alt_lexer_conditions
983 .insert(name.into(), Arc::new(condition));
984 self
985 }
986
987 pub fn alt_condition_with_lexer_and_match(
990 &mut self,
991 name: impl Into<String>,
992 condition: impl for<'source> Fn(&mut Rule, &mut Context, &mut AltMatch, &mut Lexer<'source>) -> bool
993 + Send
994 + Sync
995 + 'static,
996 ) -> &mut Self {
997 self.alt_lexer_match_conditions
998 .insert(name.into(), Arc::new(condition));
999 self
1000 }
1001
1002 pub fn alt_modifier(
1004 &mut self,
1005 name: impl Into<String>,
1006 modifier: impl Fn(AltSpec, &mut Rule, &mut Context) -> AltSpec + Send + Sync + 'static,
1007 ) -> &mut Self {
1008 self.alt_modifiers.insert(name.into(), Arc::new(modifier));
1009 self
1010 }
1011
1012 pub fn alt_modifier_with_match(
1013 &mut self,
1014 name: impl Into<String>,
1015 modifier: impl Fn(AltMatch, &mut Rule, &mut Context, Option<&RuleSnapshot>) -> AltMatch
1016 + Send
1017 + Sync
1018 + 'static,
1019 ) -> &mut Self {
1020 self.alt_match_modifiers
1021 .insert(name.into(), Arc::new(modifier));
1022 self
1023 }
1024
1025 pub fn alt_error(
1027 &mut self,
1028 name: impl Into<String>,
1029 error: impl Fn(&mut Rule, &mut Context) -> Option<Token> + Send + Sync + 'static,
1030 ) -> &mut Self {
1031 self.alt_errors.insert(name.into(), Arc::new(error));
1032 self
1033 }
1034
1035 pub fn alt_error_with_match(
1036 &mut self,
1037 name: impl Into<String>,
1038 error: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Option<Token> + Send + Sync + 'static,
1039 ) -> &mut Self {
1040 self.alt_match_errors.insert(name.into(), Arc::new(error));
1041 self
1042 }
1043
1044 pub fn alt_push(
1046 &mut self,
1047 name: impl Into<String>,
1048 route: impl Fn(&mut Rule, &mut Context) -> Option<String> + Send + Sync + 'static,
1049 ) -> &mut Self {
1050 self.alt_pushes.insert(name.into(), Arc::new(route));
1051 self
1052 }
1053
1054 pub fn alt_push_with_match(
1055 &mut self,
1056 name: impl Into<String>,
1057 route: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Option<String> + Send + Sync + 'static,
1058 ) -> &mut Self {
1059 self.alt_match_pushes.insert(name.into(), Arc::new(route));
1060 self
1061 }
1062
1063 pub fn alt_replace(
1065 &mut self,
1066 name: impl Into<String>,
1067 route: impl Fn(&mut Rule, &mut Context) -> Option<String> + Send + Sync + 'static,
1068 ) -> &mut Self {
1069 self.alt_replaces.insert(name.into(), Arc::new(route));
1070 self
1071 }
1072
1073 pub fn alt_replace_with_match(
1074 &mut self,
1075 name: impl Into<String>,
1076 route: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> Option<String> + Send + Sync + 'static,
1077 ) -> &mut Self {
1078 self.alt_match_replaces.insert(name.into(), Arc::new(route));
1079 self
1080 }
1081
1082 pub fn alt_backtrack(
1084 &mut self,
1085 name: impl Into<String>,
1086 backtrack: impl Fn(&mut Rule, &mut Context) -> usize + Send + Sync + 'static,
1087 ) -> &mut Self {
1088 self.alt_backtracks.insert(name.into(), Arc::new(backtrack));
1089 self
1090 }
1091
1092 pub fn alt_backtrack_with_match(
1093 &mut self,
1094 name: impl Into<String>,
1095 backtrack: impl Fn(&mut Rule, &mut Context, &mut AltMatch) -> usize + Send + Sync + 'static,
1096 ) -> &mut Self {
1097 self.alt_match_backtracks
1098 .insert(name.into(), Arc::new(backtrack));
1099 self
1100 }
1101
1102 pub fn match_token_ref(
1106 &mut self,
1107 name: impl Into<String>,
1108 eager: bool,
1109 matcher: impl Fn(&str) -> Option<MatchTokenResult> + Send + Sync + 'static,
1110 ) -> &mut Self {
1111 self.match_token_refs
1112 .insert(name.into(), (Arc::new(matcher), eager));
1113 self
1114 }
1115
1116 pub fn match_value_ref(
1119 &mut self,
1120 name: impl Into<String>,
1121 matcher: impl Fn(&str) -> Option<MatchTokenResult> + Send + Sync + 'static,
1122 ) -> &mut Self {
1123 self.match_value_refs.insert(name.into(), Arc::new(matcher));
1124 self
1125 }
1126
1127 pub fn value_transform_ref(
1134 &mut self,
1135 name: impl Into<String>,
1136 transform: impl Fn(&[String]) -> Value + Send + Sync + 'static,
1137 ) -> &mut Self {
1138 self.value_transform_refs
1139 .insert(name.into(), Arc::new(transform));
1140 self
1141 }
1142
1143 pub fn text_modifier_ref(
1146 &mut self,
1147 name: impl Into<String>,
1148 modifier: impl Fn(Value) -> Value + Send + Sync + 'static,
1149 ) -> &mut Self {
1150 self.text_modifier_refs
1151 .insert(name.into(), TextModifier::new(modifier));
1152 self
1153 }
1154
1155 pub fn imperative_text_modifier_ref(
1159 &mut self,
1160 name: impl Into<String>,
1161 modifier: impl for<'source> Fn(Value, &mut Lexer<'source>, &mut Rule, &mut Context, &Options) -> Value
1162 + Send
1163 + Sync
1164 + 'static,
1165 ) -> &mut Self {
1166 self.text_modifier_refs
1167 .insert(name.into(), TextModifier::new_imperative(modifier));
1168 self
1169 }
1170
1171 pub fn lex_check_ref(
1174 &mut self,
1175 name: impl Into<String>,
1176 check: impl Fn(&str) -> LexCheckResult + Send + Sync + 'static,
1177 ) -> &mut Self {
1178 self.lex_check_refs
1179 .insert(name.into(), LexCheck::new(check));
1180 self
1181 }
1182
1183 pub fn imperative_lex_check_ref(
1186 &mut self,
1187 name: impl Into<String>,
1188 check: impl for<'source> Fn(&mut Lexer<'source>) -> LexCheckResult + Send + Sync + 'static,
1189 ) -> &mut Self {
1190 self.lex_check_refs
1191 .insert(name.into(), LexCheck::new_imperative(check));
1192 self
1193 }
1194
1195 pub fn lex_match_ref(
1198 &mut self,
1199 name: impl Into<String>,
1200 matcher: impl Fn(&str) -> Option<LexCheckToken> + Send + Sync + 'static,
1201 ) -> &mut Self {
1202 self.lex_match_refs.insert(name.into(), Arc::new(matcher));
1203 self
1204 }
1205
1206 pub fn imperative_lex_match_ref(
1210 &mut self,
1211 name: impl Into<String>,
1212 matcher: impl for<'source> Fn(&mut Lexer<'source>, &mut Rule, &mut Context) -> Option<Token>
1213 + Send
1214 + Sync
1215 + 'static,
1216 ) -> &mut Self {
1217 self.imperative_lex_match_refs
1218 .insert(name.into(), Arc::new(matcher));
1219 self
1220 }
1221
1222 pub fn lex_match_factory_ref(
1226 &mut self,
1227 name: impl Into<String>,
1228 factory: impl Fn(&Options) -> Option<ImperativeLexMatcher> + Send + Sync + 'static,
1229 ) -> &mut Self {
1230 self.lex_match_factory_refs
1231 .insert(name.into(), Arc::new(factory));
1232 self
1233 }
1234
1235 pub fn error_suffix_ref(
1238 &mut self,
1239 name: impl Into<String>,
1240 render: impl Fn(&ErrorSuffixContext) -> String + Send + Sync + 'static,
1241 ) -> &mut Self {
1242 self.error_suffix_refs.insert(name.into(), Arc::new(render));
1243 self
1244 }
1245
1246 pub fn config_modifier_ref(
1249 &mut self,
1250 name: impl Into<String>,
1251 modifier: impl Fn(&mut Options) + Send + Sync + 'static,
1252 ) -> &mut Self {
1253 self.config_modifier_refs
1254 .insert(name.into(), ConfigModifier::new(modifier));
1255 self
1256 }
1257
1258 pub fn config_modifier_with_options_ref(
1262 &mut self,
1263 name: impl Into<String>,
1264 modifier: impl Fn(&mut Options, &Options) + Send + Sync + 'static,
1265 ) -> &mut Self {
1266 self.config_modifier_refs
1267 .insert(name.into(), ConfigModifier::with_options(modifier));
1268 self
1269 }
1270
1271 pub fn parser_start_ref(
1274 &mut self,
1275 name: impl Into<String>,
1276 start: impl Fn(&str) -> Result<Value, Box<TabnasError>> + Send + Sync + 'static,
1277 ) -> &mut Self {
1278 self.parser_start_refs.insert(name.into(), Arc::new(start));
1279 self
1280 }
1281
1282 pub fn parser_start_with_instance_ref(
1285 &mut self,
1286 name: impl Into<String>,
1287 start: impl Fn(&str, &Tabnas, &Value) -> Result<Value, Box<TabnasError>> + Send + Sync + 'static,
1288 ) -> &mut Self {
1289 self.parser_start_instance_refs
1290 .insert(name.into(), Arc::new(start));
1291 self
1292 }
1293
1294 pub fn parser_start_with_context_ref(
1297 &mut self,
1298 name: impl Into<String>,
1299 start: impl Fn(&str, &Tabnas, &Value, Option<&ContextSeed>) -> Result<Value, Box<TabnasError>>
1300 + Send
1301 + Sync
1302 + 'static,
1303 ) -> &mut Self {
1304 self.parser_start_context_refs
1305 .insert(name.into(), Arc::new(start));
1306 self
1307 }
1308
1309 pub fn map_merge_ref(
1312 &mut self,
1313 name: impl Into<String>,
1314 merge: impl Fn(Value, Value, &mut Rule, &mut Context) -> Value + Send + Sync + 'static,
1315 ) -> &mut Self {
1316 self.map_merge_refs.insert(name.into(), Arc::new(merge));
1317 self
1318 }
1319
1320 pub fn comment_suffix_ref(
1323 &mut self,
1324 name: impl Into<String>,
1325 matcher: impl Fn(&str) -> Option<String> + Send + Sync + 'static,
1326 ) -> &mut Self {
1327 self.comment_suffix_refs
1328 .insert(name.into(), CommentSuffixMatcher::new(matcher));
1329 self
1330 }
1331
1332 pub fn imperative_comment_suffix_ref(
1336 &mut self,
1337 name: impl Into<String>,
1338 matcher: impl for<'source> Fn(&mut Lexer<'source>) -> Option<Token> + Send + Sync + 'static,
1339 ) -> &mut Self {
1340 self.comment_suffix_refs
1341 .insert(name.into(), CommentSuffixMatcher::new_imperative(matcher));
1342 self
1343 }
1344
1345 pub fn parse_budget(
1346 &mut self,
1347 check_every_n: usize,
1348 check: impl Fn(&Context) -> bool + Send + Sync + 'static,
1349 ) -> &mut Self {
1350 self.options.parse.budget.check_every_n = check_every_n;
1351 self.options.parse.budget.on_check = Some(Arc::new(check));
1352 self
1353 }
1354
1355 pub fn parse_budget_ref(
1358 &mut self,
1359 name: impl Into<String>,
1360 check: impl Fn(&Context) -> bool + Send + Sync + 'static,
1361 ) -> &mut Self {
1362 self.budget_check_refs.insert(name.into(), Arc::new(check));
1363 self
1364 }
1365
1366 pub fn parse_guard(
1393 &mut self,
1394 name: impl Into<String>,
1395 check: impl Fn(&Context) -> bool + Send + Sync + 'static,
1396 ) -> &mut Self {
1397 self.parse_guards.insert(name.into(), Arc::new(check));
1398 self
1399 }
1400
1401 pub fn remove_parse_guard(&mut self, name: &str) -> &mut Self {
1404 self.parse_guards.shift_remove(name);
1405 self
1406 }
1407
1408 pub fn parse_prepare(
1409 &mut self,
1410 prepare: impl Fn(&mut Context) + Send + Sync + 'static,
1411 ) -> &mut Self {
1412 self.options
1413 .parse
1414 .prepare
1415 .push(ParsePrepare::Context(Arc::new(prepare)));
1416 self
1417 }
1418
1419 pub fn parse_prepare_with_instance(
1422 &mut self,
1423 prepare: impl Fn(&Tabnas, &mut Context, &Value) + Send + Sync + 'static,
1424 ) -> &mut Self {
1425 self.options
1426 .parse
1427 .prepare
1428 .push(ParsePrepare::WithInstance(Arc::new(prepare)));
1429 self
1430 }
1431
1432 pub fn parse_prepare_ref(
1435 &mut self,
1436 name: impl Into<String>,
1437 prepare: impl Fn(&mut Context) + Send + Sync + 'static,
1438 ) -> &mut Self {
1439 self.parse_prepare_refs
1440 .insert(name.into(), ParsePrepare::Context(Arc::new(prepare)));
1441 self
1442 }
1443
1444 pub fn parse_prepare_with_instance_ref(
1447 &mut self,
1448 name: impl Into<String>,
1449 prepare: impl Fn(&Tabnas, &mut Context, &Value) + Send + Sync + 'static,
1450 ) -> &mut Self {
1451 self.parse_prepare_refs
1452 .insert(name.into(), ParsePrepare::WithInstance(Arc::new(prepare)));
1453 self
1454 }
1455
1456 pub fn parse(&self, src: &str) -> Result<Value, TabnasError> {
1457 self.parser().parse_for(self, src, Value::Undefined)
1458 }
1459
1460 pub fn parse_with_meta(&self, src: &str, meta: Value) -> Result<Value, TabnasError> {
1461 self.parser().parse_for(self, src, meta)
1462 }
1463
1464 pub fn parse_with_context(
1465 &self,
1466 src: &str,
1467 meta: Value,
1468 parent: &ContextSeed,
1469 ) -> Result<Value, TabnasError> {
1470 self.parser()
1471 .parse_for_with_context(self, src, meta, parent)
1472 }
1473
1474 pub fn continuations(&self, src: &str) -> Continuations {
1475 self.parser().continuations_for(self, src)
1476 }
1477
1478 pub fn parse_recover(&self, src: &str) -> ParseRecovery {
1479 self.parser().parse_recover_for(self, src, Value::Undefined)
1480 }
1481
1482 pub fn parse_recover_with_meta(&self, src: &str, meta: Value) -> ParseRecovery {
1483 self.parser().parse_recover_for(self, src, meta)
1484 }
1485
1486 pub fn parse_recover_with_context(
1487 &self,
1488 src: &str,
1489 meta: Value,
1490 parent: &ContextSeed,
1491 ) -> ParseRecovery {
1492 self.parser()
1493 .parse_recover_for_with_context(self, src, meta, parent)
1494 }
1495
1496 fn grammar_generation(&self) -> u64 {
1499 self.options
1500 .generation()
1501 .wrapping_add(self.rules.generation())
1502 .wrapping_add(self.actions.generation())
1503 .wrapping_add(self.context_actions.generation())
1504 .wrapping_add(self.matched_actions.generation())
1505 .wrapping_add(self.state_actions.generation())
1506 .wrapping_add(self.token_subscribers.generation())
1507 .wrapping_add(self.lex_subscribers.generation())
1508 .wrapping_add(self.rule_subscribers.generation())
1509 .wrapping_add(self.rule_done_subscribers.generation())
1510 .wrapping_add(self.parse_guards.generation())
1511 .wrapping_add(self.plugins.generation())
1512 }
1513
1514 fn parser(&self) -> Arc<Parser> {
1515 self.prepared_parser
1516 .get(self.grammar_generation(), || self.build_parser())
1517 }
1518
1519 fn build_parser(&self) -> Parser {
1520 let mut p = Parser::from_shared(self.prepared_options.get(&self.options));
1521 p.set_instance_info(InstanceInfo {
1522 id: self.id.clone(),
1523 parent_id: self.parent_id.clone(),
1524 tag: self.options.tag.clone(),
1525 plugins: self
1526 .plugins
1527 .iter()
1528 .map(|plugin| plugin.name.clone())
1529 .collect(),
1530 rule_names: self.rule_names(),
1531 });
1532 for spec in self.rules.values() {
1533 p.add_rule(spec.clone());
1534 }
1535 for (name, action) in self.actions.iter() {
1536 p.add_action(name.clone(), action.clone());
1537 }
1538 for (name, action) in self.context_actions.iter() {
1539 p.add_context_action(name.clone(), action.clone());
1540 }
1541 for (name, action) in self.matched_actions.iter() {
1542 p.add_matched_action(name.clone(), action.clone());
1543 }
1544 for (name, action) in self.state_actions.iter() {
1545 p.add_state_action(name.clone(), action.clone());
1546 }
1547 for subscriber in self.token_subscribers.iter() {
1548 p.add_token_subscriber(subscriber.clone());
1549 }
1550 for subscriber in self.lex_subscribers.iter() {
1551 p.add_lex_subscriber(subscriber.clone());
1552 }
1553 for subscriber in self.rule_subscribers.iter() {
1554 p.add_rule_subscriber(subscriber.clone());
1555 }
1556 for subscriber in self.rule_done_subscribers.iter() {
1557 p.add_rule_done_subscriber(subscriber.clone());
1558 }
1559 for guard in self.parse_guards.values() {
1560 p.add_parse_guard(guard.clone());
1561 }
1562 p
1563 }
1564
1565 pub fn make_json() -> Self {
1574 let mut opts = Options::default();
1575 opts.text.lex = false;
1576 opts.comment.lex = false;
1577 opts.map.extend = false;
1578 opts.lex.empty = false;
1579 opts.rule.finish = false;
1580 opts.rule.include = "json".to_string();
1581
1582 opts.number.hex = false;
1583 opts.number.oct = false;
1584 opts.number.bin = false;
1585 opts.number.sep = None;
1586 opts.number.exclude = Some(r"^(?:\+|[+-]?\.|-?0\d)|\.$".to_string());
1590
1591 opts.string.chars = "\"".to_string();
1592 opts.string.multi_chars = "".to_string();
1593 opts.string.allow_unknown = false;
1594 opts.string.escape_strict = true;
1595 for escape in ['v', '\'', '`'] {
1596 opts.string.escape.remove(&escape);
1597 }
1598
1599 let mut tn = Tabnas::with_options(opts);
1600
1601 let mut val = RuleSpec::new("val");
1603 val.bo.push("@val-bo".to_string());
1604 val.bc.push("@val-bc".to_string());
1605
1606 val.open.push(AltSpec {
1608 s: vec![vec![TIN_OB]],
1609 p: Some("map".to_string()),
1610 b: 1,
1611 g: "map,json".to_string(),
1612 ..Default::default()
1613 });
1614 val.open.push(AltSpec {
1615 s: vec![vec![TIN_OS]],
1616 p: Some("list".to_string()),
1617 b: 1,
1618 g: "list,json".to_string(),
1619 ..Default::default()
1620 });
1621 val.open.push(AltSpec {
1622 s: vec![vec![TIN_TX, TIN_NR, TIN_ST, TIN_VL]],
1623 g: "val,json".to_string(),
1624 ..Default::default()
1625 });
1626
1627 val.close.push(AltSpec {
1629 s: vec![vec![TIN_ZZ]],
1630 g: "end,json".to_string(),
1631 ..Default::default()
1632 });
1633 val.close.push(AltSpec {
1634 s: vec![],
1635 b: 1,
1636 g: "more,json".to_string(),
1637 ..Default::default()
1638 });
1639 tn.rule(val);
1640
1641 let mut map = RuleSpec::new("map");
1643 map.bo.push("@map-bo".to_string());
1644 let mut n_pk = HashMap::new();
1645 n_pk.insert("pk".to_string(), 0);
1646
1647 map.open.push(AltSpec {
1648 s: vec![vec![TIN_OB], vec![TIN_CB]],
1649 b: 1,
1650 n: n_pk.clone(),
1651 g: "map,json".to_string(),
1652 ..Default::default()
1653 });
1654 map.open.push(AltSpec {
1655 s: vec![vec![TIN_OB]],
1656 p: Some("pair".to_string()),
1657 n: n_pk,
1658 g: "map,json,pair".to_string(),
1659 ..Default::default()
1660 });
1661
1662 map.close.push(AltSpec {
1663 s: vec![vec![TIN_CB]],
1664 g: "end,json".to_string(),
1665 ..Default::default()
1666 });
1667 tn.rule(map);
1668
1669 let mut list = RuleSpec::new("list");
1671 list.bo.push("@list-bo".to_string());
1672
1673 list.open.push(AltSpec {
1674 s: vec![vec![TIN_OS], vec![TIN_CS]],
1675 b: 1,
1676 g: "list,json".to_string(),
1677 ..Default::default()
1678 });
1679 list.open.push(AltSpec {
1680 s: vec![vec![TIN_OS]],
1681 p: Some("elem".to_string()),
1682 g: "list,elem,json".to_string(),
1683 ..Default::default()
1684 });
1685
1686 list.close.push(AltSpec {
1687 s: vec![vec![TIN_CS]],
1688 g: "end,json".to_string(),
1689 ..Default::default()
1690 });
1691 tn.rule(list);
1692
1693 let mut pair = RuleSpec::new("pair");
1695 pair.bc.push("@pair-bc".to_string());
1696
1697 let mut u_pair = HashMap::new();
1698 u_pair.insert("pair".to_string(), Value::Bool(true));
1699
1700 pair.open.push(AltSpec {
1701 s: vec![vec![TIN_ST], vec![TIN_CL]],
1702 p: Some("val".to_string()),
1703 u: u_pair,
1704 a: vec!["@pairkey".to_string()],
1705 g: "map,pair,key,json".to_string(),
1706 ..Default::default()
1707 });
1708
1709 pair.close.push(AltSpec {
1710 s: vec![vec![TIN_CA]],
1711 r: Some("pair".to_string()),
1712 g: "map,pair,json".to_string(),
1713 ..Default::default()
1714 });
1715 pair.close.push(AltSpec {
1716 s: vec![vec![TIN_CB]],
1717 b: 1,
1718 g: "map,pair,json".to_string(),
1719 ..Default::default()
1720 });
1721 tn.rule(pair);
1722
1723 let mut elem = RuleSpec::new("elem");
1725 elem.bc.push("@elem-bc".to_string());
1726
1727 elem.open.push(AltSpec {
1728 s: vec![],
1729 p: Some("val".to_string()),
1730 g: "list,elem,val,json".to_string(),
1731 ..Default::default()
1732 });
1733
1734 elem.close.push(AltSpec {
1735 s: vec![vec![TIN_CA]],
1736 r: Some("elem".to_string()),
1737 g: "list,elem,json".to_string(),
1738 ..Default::default()
1739 });
1740 elem.close.push(AltSpec {
1741 s: vec![vec![TIN_CS]],
1742 b: 1,
1743 g: "list,elem,json".to_string(),
1744 ..Default::default()
1745 });
1746 tn.rule(elem);
1747
1748 tn
1749 }
1750}
1751
1752impl fmt::Display for Tabnas {
1753 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1754 formatter.write_str(&self.id)
1755 }
1756}
1757
1758fn panic_message(payload: Box<dyn std::any::Any + Send>) -> String {
1759 if let Some(message) = payload.downcast_ref::<&str>() {
1760 (*message).to_string()
1761 } else if let Some(message) = payload.downcast_ref::<String>() {
1762 message.clone()
1763 } else {
1764 "non-string panic payload".into()
1765 }
1766}
1767
1768pub(crate) fn merge_plugin_values(base: Value, overlay: Value) -> Value {
1769 const DANGEROUS: [&str; 3] = ["__proto__", "constructor", "prototype"];
1770 match (base, overlay) {
1771 (base, Value::Undefined) => base,
1772 (Value::Object(base), Value::Object(overlay)) => {
1773 let mut base = crate::value::unwrap_arc(base);
1774 for (key, value) in crate::value::unwrap_arc(overlay) {
1775 if DANGEROUS.contains(&key.as_str()) {
1776 continue;
1777 }
1778 let previous = base.shift_remove(&key).unwrap_or(Value::Undefined);
1779 base.insert(key, merge_plugin_values(previous, value));
1780 }
1781 Value::object(base)
1782 }
1783 (Value::Array(base), Value::Array(overlay)) => {
1784 let length = base.len().max(overlay.len());
1785 let mut base = crate::value::unwrap_arc(base).into_iter();
1786 let mut overlay = crate::value::unwrap_arc(overlay).into_iter();
1787 Value::array(
1788 (0..length)
1789 .map(|_| match (base.next(), overlay.next()) {
1790 (Some(base), Some(overlay)) => merge_plugin_values(base, overlay),
1791 (Some(base), None) => base,
1792 (None, Some(overlay)) => overlay,
1793 (None, None) => unreachable!("length comes from both iterators"),
1794 })
1795 .collect(),
1796 )
1797 }
1798 (_, overlay) => overlay,
1799 }
1800}
1801
1802#[derive(Default)]
1810struct PreparedOptions(std::sync::Mutex<Option<(u64, Arc<Options>)>>);
1811
1812impl PreparedOptions {
1813 fn get(&self, options: &crate::tracked::Tracked<Options>) -> Arc<Options> {
1814 let generation = options.generation();
1815 let mut slot = self.0.lock().expect("prepared options lock");
1816 if let Some((prepared_at, ref prepared)) = *slot {
1817 if prepared_at == generation {
1818 return Arc::clone(prepared);
1819 }
1820 }
1821 let mut prepared_value = options.peek().clone();
1822 prepared_value.sort_for_lexing();
1823 let prepared = Arc::new(prepared_value);
1824 *slot = Some((generation, Arc::clone(&prepared)));
1825 prepared
1826 }
1827}
1828
1829impl Clone for PreparedOptions {
1832 fn clone(&self) -> Self {
1833 PreparedOptions::default()
1834 }
1835}
1836
1837#[derive(Default)]
1850struct PreparedParser(std::sync::Mutex<Option<(u64, Arc<Parser>)>>);
1851
1852impl PreparedParser {
1853 fn get(&self, generation: u64, build: impl FnOnce() -> Parser) -> Arc<Parser> {
1854 let mut slot = self.0.lock().expect("prepared parser lock");
1855 if let Some((prepared_at, ref prepared)) = *slot {
1856 if prepared_at == generation {
1857 return Arc::clone(prepared);
1858 }
1859 }
1860 let prepared = Arc::new(build());
1861 *slot = Some((generation, Arc::clone(&prepared)));
1862 prepared
1863 }
1864}
1865
1866impl Clone for PreparedParser {
1867 fn clone(&self) -> Self {
1868 PreparedParser::default()
1869 }
1870}