1#![allow(clippy::result_large_err)]
45
46use std::cell::{Cell, RefCell};
47use std::collections::HashMap;
48use std::fmt;
49use std::rc::Rc;
50use std::sync::{Arc, OnceLock};
51
52use indexmap::IndexMap;
53
54use tabnas::{
55 AltMatch, AltSpec, Context, ListRef, Plugin, PluginError, Rule, RuleSnapshot, RuleSpec, Tabnas,
56 TabnasError, Tin, Token, Value, TIN_CA, TIN_CB, TIN_CL, TIN_CS, TIN_NR, TIN_ST, TIN_TX, TIN_VL,
57 TIN_ZZ,
58};
59
60pub const VERSION: &str = "0.5.15";
66
67pub const PLUGIN_NAME: &str = "Expr";
69
70#[cfg(doctest)]
74#[doc = include_str!("../README.md")]
75mod readme_examples {}
76
77pub use tabnas::TabnasError as ExprError;
80
81pub const MIN_SAFE_INTEGER: i64 = -9_007_199_254_740_991;
84
85pub const MAX_SAFE_INTEGER: i64 = 9_007_199_254_740_991;
88
89#[derive(Debug, Clone, Default, PartialEq, Eq)]
97pub struct PrevalDef {
98 pub active: bool,
99 pub required: bool,
100 pub allow: Option<Vec<String>>,
101}
102
103#[derive(Debug, Clone, PartialEq)]
109pub struct OpDef {
110 pub src: Vec<String>,
111 pub osrc: String,
112 pub csrc: String,
113 pub left: Option<i64>,
114 pub right: Option<i64>,
115 pub prefix: bool,
116 pub suffix: bool,
117 pub infix: bool,
118 pub ternary: bool,
119 pub paren: bool,
120 pub preval: Option<PrevalDef>,
121 pub use_data: Value,
123}
124
125impl Default for OpDef {
126 fn default() -> Self {
127 OpDef {
128 src: Vec::new(),
129 osrc: String::new(),
130 csrc: String::new(),
131 left: None,
132 right: None,
133 prefix: false,
134 suffix: false,
135 infix: false,
136 ternary: false,
137 paren: false,
138 preval: None,
139 use_data: Value::Undefined,
140 }
141 }
142}
143
144impl OpDef {
145 pub fn infix(src: impl Into<String>, left: i64, right: i64) -> Self {
147 OpDef {
148 src: vec![src.into()],
149 infix: true,
150 left: Some(left),
151 right: Some(right),
152 ..Default::default()
153 }
154 }
155
156 pub fn prefix(src: impl Into<String>, right: i64) -> Self {
158 OpDef {
159 src: vec![src.into()],
160 prefix: true,
161 right: Some(right),
162 ..Default::default()
163 }
164 }
165
166 pub fn suffix(src: impl Into<String>, left: i64) -> Self {
168 OpDef {
169 src: vec![src.into()],
170 suffix: true,
171 left: Some(left),
172 ..Default::default()
173 }
174 }
175
176 pub fn ternary(first: impl Into<String>, second: impl Into<String>) -> Self {
178 OpDef {
179 src: vec![first.into(), second.into()],
180 ternary: true,
181 ..Default::default()
182 }
183 }
184
185 pub fn paren(osrc: impl Into<String>, csrc: impl Into<String>) -> Self {
187 OpDef {
188 osrc: osrc.into(),
189 csrc: csrc.into(),
190 paren: true,
191 ..Default::default()
192 }
193 }
194
195 pub fn with_preval(mut self, preval: PrevalDef) -> Self {
197 self.preval = Some(preval);
198 self
199 }
200
201 pub fn with_use(mut self, use_data: Value) -> Self {
203 self.use_data = use_data;
204 self
205 }
206}
207
208#[derive(Debug, Clone, PartialEq)]
211pub struct Op {
212 pub name: String,
213 pub src: String,
214 pub left: i64,
215 pub right: i64,
216 pub use_data: Value,
217 pub prefix: bool,
218 pub suffix: bool,
219 pub infix: bool,
220 pub ternary: bool,
221 pub paren: bool,
222 pub terms: usize,
223 pub tkn: String,
224 pub tin: Tin,
225 pub osrc: String,
226 pub csrc: String,
227 pub otkn: String,
228 pub otin: Tin,
229 pub ctkn: String,
230 pub ctin: Tin,
231 pub preval: PrevalDef,
232 pub ternary_index: Option<usize>,
235}
236
237impl Default for Op {
238 fn default() -> Self {
239 Op {
240 name: String::new(),
241 src: String::new(),
242 left: MIN_SAFE_INTEGER,
243 right: MAX_SAFE_INTEGER,
244 use_data: Value::Undefined,
245 prefix: false,
246 suffix: false,
247 infix: false,
248 ternary: false,
249 paren: false,
250 terms: 0,
251 tkn: String::new(),
252 tin: -1,
253 osrc: String::new(),
254 csrc: String::new(),
255 otkn: String::new(),
256 otin: -1,
257 ctkn: String::new(),
258 ctin: -1,
259 preval: PrevalDef::default(),
260 ternary_index: None,
261 }
262 }
263}
264
265impl Op {
266 fn to_value(&self, token: Option<&Token>) -> Value {
270 let mut map: IndexMap<String, Value> = IndexMap::new();
271 map.insert("src".into(), Value::String(self.src.clone()));
272 map.insert("left".into(), number(self.left));
273 map.insert("right".into(), number(self.right));
274 map.insert("name".into(), Value::String(self.name.clone()));
275 map.insert("infix".into(), Value::Bool(self.infix));
276 map.insert("prefix".into(), Value::Bool(self.prefix));
277 map.insert("suffix".into(), Value::Bool(self.suffix));
278 map.insert("ternary".into(), Value::Bool(self.ternary));
279 map.insert("tkn".into(), Value::String(self.tkn.clone()));
280 map.insert("tin".into(), Value::Number(f64::from(self.tin)));
281 map.insert("terms".into(), Value::Number(self.terms as f64));
282 map.insert("use".into(), self.use_value());
283 map.insert("paren".into(), Value::Bool(self.paren));
284 map.insert("osrc".into(), Value::String(self.osrc.clone()));
285 map.insert("csrc".into(), Value::String(self.csrc.clone()));
286 map.insert("otkn".into(), Value::String(self.otkn.clone()));
287 map.insert("ctkn".into(), Value::String(self.ctkn.clone()));
288 map.insert("otin".into(), Value::Number(f64::from(self.otin)));
289 map.insert("ctin".into(), Value::Number(f64::from(self.ctin)));
290 map.insert("preval".into(), self.preval_value());
291 map.insert("token".into(), token_value(token));
292 Value::object(map)
293 }
294
295 fn use_value(&self) -> Value {
296 let mut used: IndexMap<String, Value> = match &self.use_data {
297 Value::Object(entries) => (**entries).clone(),
298 _ => IndexMap::new(),
299 };
300 if let Some(index) = self.ternary_index {
301 let mut ternary: IndexMap<String, Value> = IndexMap::new();
302 ternary.insert("opI".into(), Value::Number(index as f64));
303 used.insert("ternary".into(), Value::object(ternary));
304 }
305 Value::object(used)
306 }
307
308 fn preval_value(&self) -> Value {
309 let mut preval: IndexMap<String, Value> = IndexMap::new();
310 preval.insert("active".into(), Value::Bool(self.preval.active));
311 preval.insert("required".into(), Value::Bool(self.preval.required));
312 if let Some(allow) = &self.preval.allow {
313 preval.insert(
314 "allow".into(),
315 Value::array(allow.iter().cloned().map(Value::String).collect()),
316 );
317 }
318 Value::object(preval)
319 }
320}
321
322fn number(value: i64) -> Value {
326 Value::Number(value as f64)
327}
328
329fn token_value(token: Option<&Token>) -> Value {
332 let Some(token) = token else {
333 return Value::object(IndexMap::new());
334 };
335 let mut map: IndexMap<String, Value> = IndexMap::new();
336 map.insert("isToken".into(), Value::Bool(true));
337 map.insert("name".into(), Value::String(token.name.as_str().into()));
338 map.insert("tin".into(), Value::Number(f64::from(token.tin)));
339 map.insert("src".into(), Value::String(token.src.as_str().into()));
340 map.insert("len".into(), Value::Number(token.len as f64));
341 map.insert("sI".into(), Value::Number(token.site.pos as f64));
342 map.insert("rI".into(), Value::Number(token.site.ri as f64));
343 map.insert("cI".into(), Value::Number(token.site.ci as f64));
344 Value::object(map)
345}
346
347pub struct EvalSite<'a> {
360 rule: Option<Rc<RuleSnapshot>>,
361 context: Option<&'a mut Context>,
362 token: Option<Token>,
363}
364
365impl<'a> EvalSite<'a> {
366 pub fn detached() -> Self {
368 EvalSite {
369 rule: None,
370 context: None,
371 token: None,
372 }
373 }
374
375 pub fn new(rule: Option<Rc<RuleSnapshot>>, context: &'a mut Context) -> Self {
377 EvalSite {
378 rule,
379 context: Some(context),
380 token: None,
381 }
382 }
383
384 pub fn rule(&self) -> Option<&RuleSnapshot> {
386 self.rule.as_deref()
387 }
388
389 pub fn token(&self) -> Option<&Token> {
402 self.token.as_ref()
403 }
404
405 pub fn context(&mut self) -> Option<&mut Context> {
407 self.context.as_deref_mut()
408 }
409
410 pub fn flag(&self, name: &str) -> bool {
414 self.rule
415 .as_ref()
416 .is_some_and(|rule| matches!(rule.u.get(name), Some(Value::Bool(true))))
417 }
418
419 fn reborrow(&mut self) -> EvalSite<'_> {
423 EvalSite {
424 rule: self.rule.clone(),
425 context: self.context.as_deref_mut(),
426 token: None,
427 }
428 }
429}
430
431pub type Evaluate = Arc<dyn Fn(&mut EvalSite<'_>, &Op, &[Value]) -> Value + Send + Sync>;
435
436#[derive(Clone, Default)]
443pub struct ExprOptions {
444 pub op: IndexMap<String, Option<OpDef>>,
445 pub evaluate: Option<Evaluate>,
446}
447
448impl fmt::Debug for ExprOptions {
449 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
450 formatter
451 .debug_struct("ExprOptions")
452 .field("op", &self.op)
453 .field("evaluate", &self.evaluate.as_ref().map(|_| "<function>"))
454 .finish()
455 }
456}
457
458impl ExprOptions {
459 pub fn new() -> Self {
462 Self::default()
463 }
464
465 pub fn with_op(mut self, name: impl Into<String>, def: OpDef) -> Self {
467 self.op.insert(name.into(), Some(def));
468 self
469 }
470
471 pub fn without_op(mut self, name: impl Into<String>) -> Self {
473 self.op.insert(name.into(), None);
474 self
475 }
476
477 pub fn with_evaluate(
479 mut self,
480 evaluate: impl Fn(&mut EvalSite<'_>, &Op, &[Value]) -> Value + Send + Sync + 'static,
481 ) -> Self {
482 self.evaluate = Some(Arc::new(evaluate));
483 self
484 }
485
486 pub fn from_value(options: &Value) -> Self {
490 let mut resolved = ExprOptions::new();
491 let Some(op) = object_get(options, "op") else {
492 return resolved;
493 };
494 let Value::Object(entries) = op else {
495 return resolved;
496 };
497 for (name, def) in entries.iter() {
498 match def {
499 Value::Object(_) => {
500 resolved
501 .op
502 .insert(name.clone(), Some(op_def_from_value(def)));
503 }
504 _ => {
506 resolved.op.insert(name.clone(), None);
507 }
508 }
509 }
510 resolved
511 }
512}
513
514fn object_get<'a>(value: &'a Value, key: &str) -> Option<&'a Value> {
515 match value {
516 Value::Object(map) => map.get(key),
517 Value::MapRef(map) => map.value.get(key),
518 _ => None,
519 }
520}
521
522fn value_bool(value: Option<&Value>) -> bool {
523 matches!(value, Some(Value::Bool(true)))
524}
525
526fn value_i64(value: Option<&Value>) -> Option<i64> {
527 match value {
528 Some(Value::Number(number)) => Some(*number as i64),
529 _ => None,
530 }
531}
532
533fn value_string(value: Option<&Value>) -> String {
534 match value {
535 Some(Value::String(text)) => text.clone(),
536 Some(Value::Text(text)) => text.string.clone(),
537 _ => String::new(),
538 }
539}
540
541fn op_def_from_value(def: &Value) -> OpDef {
542 let mut out = OpDef {
543 osrc: value_string(object_get(def, "osrc")),
544 csrc: value_string(object_get(def, "csrc")),
545 left: value_i64(object_get(def, "left")),
546 right: value_i64(object_get(def, "right")),
547 prefix: value_bool(object_get(def, "prefix")),
548 suffix: value_bool(object_get(def, "suffix")),
549 infix: value_bool(object_get(def, "infix")),
550 ternary: value_bool(object_get(def, "ternary")),
551 paren: value_bool(object_get(def, "paren")),
552 use_data: object_get(def, "use").cloned().unwrap_or(Value::Undefined),
553 ..Default::default()
554 };
555 match object_get(def, "src") {
556 Some(Value::String(src)) => out.src = vec![src.clone()],
557 Some(Value::Array(srcs)) => {
558 out.src = srcs
559 .iter()
560 .map(|src| value_string(Some(src)))
561 .collect::<Vec<_>>()
562 }
563 _ => {}
564 }
565 out.preval = match object_get(def, "preval") {
566 None | Some(Value::Undefined) | Some(Value::Null) => None,
567 Some(Value::Bool(active)) => Some(PrevalDef {
568 active: *active,
569 required: false,
570 allow: None,
571 }),
572 Some(preval) => Some(PrevalDef {
573 active: match object_get(preval, "active") {
575 None | Some(Value::Undefined) | Some(Value::Null) => true,
576 Some(Value::Bool(active)) => *active,
577 Some(_) => true,
578 },
579 required: value_bool(object_get(preval, "required")),
580 allow: match object_get(preval, "allow") {
581 Some(Value::Array(allow)) => Some(
582 allow
583 .iter()
584 .map(|entry| value_string(Some(entry)))
585 .collect::<Vec<_>>(),
586 ),
587 _ => None,
588 },
589 }),
590 };
591 out
592}
593
594pub fn defaults() -> Value {
618 let mut ops: IndexMap<String, Value> = IndexMap::new();
619 ops.insert("positive".into(), prefix_value("+", 4_000_000));
620 ops.insert("negative".into(), prefix_value("-", 4_000_000));
621 ops.insert("addition".into(), infix_value("+", 2_000_000, 2_100_000));
624 ops.insert("subtraction".into(), infix_value("-", 2_000_000, 2_100_000));
625 ops.insert(
626 "multiplication".into(),
627 infix_value("*", 3_000_000, 3_100_000),
628 );
629 ops.insert("division".into(), infix_value("/", 3_000_000, 3_100_000));
630 ops.insert("remainder".into(), infix_value("%", 3_000_000, 3_100_000));
631 ops.insert("plain".into(), paren_value("(", ")"));
632
633 let mut map: IndexMap<String, Value> = IndexMap::new();
634 map.insert("op".into(), Value::object(ops));
635 Value::object(map)
636}
637
638fn prefix_value(src: &str, right: i64) -> Value {
639 let mut def: IndexMap<String, Value> = IndexMap::new();
640 def.insert("prefix".into(), Value::Bool(true));
641 def.insert("right".into(), number(right));
642 def.insert("src".into(), Value::String(src.into()));
643 Value::object(def)
644}
645
646fn infix_value(src: &str, left: i64, right: i64) -> Value {
647 let mut def: IndexMap<String, Value> = IndexMap::new();
648 def.insert("infix".into(), Value::Bool(true));
649 def.insert("left".into(), number(left));
650 def.insert("right".into(), number(right));
651 def.insert("src".into(), Value::String(src.into()));
652 Value::object(def)
653}
654
655fn paren_value(osrc: &str, csrc: &str) -> Value {
656 let mut def: IndexMap<String, Value> = IndexMap::new();
657 def.insert("paren".into(), Value::Bool(true));
658 def.insert("osrc".into(), Value::String(osrc.into()));
659 def.insert("csrc".into(), Value::String(csrc.into()));
660 Value::object(def)
661}
662
663fn default_ops() -> IndexMap<String, Option<OpDef>> {
665 ExprOptions::from_value(&defaults()).op
666}
667
668fn resolve_options(options: &ExprOptions) -> IndexMap<String, Option<OpDef>> {
672 let mut resolved = default_ops();
673 for (name, def) in &options.op {
674 resolved.shift_remove(name);
675 match def {
676 Some(def) => {
677 resolved.insert(name.clone(), Some(def.clone()));
678 }
679 None => {
680 resolved.insert(name.clone(), None);
681 }
682 }
683 }
684 resolved
685}
686
687#[derive(Debug, Clone)]
716struct ExprNode {
717 op: Option<Arc<Op>>,
718 token: Option<Token>,
719 terms: Vec<Value>,
720 root: u64,
730 size: usize,
734}
735
736#[derive(Default)]
737struct Arena {
738 nodes: HashMap<u64, ExprNode>,
739 next_id: u64,
740 active: usize,
743}
744
745thread_local! {
746 static ARENA: RefCell<Arena> = RefCell::new(Arena::default());
747 static OVER_LIMIT: Cell<bool> = const { Cell::new(false) };
750}
751
752const EXPR_META: &str = "expr";
754
755pub const NODE_LIMIT: usize = 127;
768
769pub const RULE_LIMIT: usize = 1024;
780
781fn node_id(value: &Value) -> Option<u64> {
783 let Value::ListRef(list) = value else {
784 return None;
785 };
786 match list.meta.get(EXPR_META) {
787 Some(Value::Number(id)) => Some(*id as u64),
788 _ => None,
789 }
790}
791
792pub fn is_op(value: &Value) -> bool {
795 op_of(value).is_some()
796}
797
798fn node_length(value: &Value) -> usize {
802 if let Some(length) = with_node(value, |entry| {
803 entry.terms.len() + usize::from(entry.op.is_some())
804 }) {
805 return length;
806 }
807 match value {
808 Value::Array(entries) => entries.len(),
809 Value::ListRef(list) => list.value.len(),
810 _ => 0,
811 }
812}
813
814fn is_op_kind(value: &Value, kind: fn(&Op) -> bool) -> bool {
815 op_of(value).is_some_and(|op| kind(&op))
816}
817
818fn is_paren_op(value: &Value) -> bool {
819 is_op_kind(value, |op| op.paren)
820}
821
822fn is_ternary_op(value: &Value) -> bool {
823 is_op_kind(value, |op| op.ternary)
824}
825
826pub fn op_of(value: &Value) -> Option<Arc<Op>> {
828 let id = node_id(value)?;
829 ARENA.with(|arena| {
830 arena
831 .borrow()
832 .nodes
833 .get(&id)
834 .and_then(|node| node.op.clone())
835 })
836}
837
838pub fn terms_of(value: &Value) -> Option<Vec<Value>> {
840 let id = node_id(value)?;
841 ARENA.with(|arena| arena.borrow().nodes.get(&id).map(|node| node.terms.clone()))
842}
843
844fn new_node_under(
847 op: Option<Arc<Op>>,
848 token: Option<Token>,
849 terms: Vec<Value>,
850 under: Option<&Value>,
851) -> Value {
852 let inherited = under.and_then(root_id);
853 let terms_taken = terms.clone();
854 let id = ARENA.with(|arena| {
855 let mut arena = arena.borrow_mut();
856 arena.next_id += 1;
857 let id = arena.next_id;
858 arena.nodes.insert(
859 id,
860 ExprNode {
861 op,
862 token,
863 terms,
864 root: inherited.unwrap_or(id),
865 size: 1,
866 },
867 );
868 id
869 });
870 let handle = handle_for(id);
871 if under.is_some() {
872 grow(&handle, 1);
873 }
874 adopt_all(&handle, &terms_taken);
875 handle
876}
877
878fn new_node(op: Option<Arc<Op>>, token: Option<Token>, terms: Vec<Value>) -> Value {
879 new_node_under(op, token, terms, None)
880}
881
882fn grow(node: &Value, count: usize) {
885 let Some(root) = root_id(node) else {
886 return;
887 };
888 let over = ARENA.with(|arena| {
889 let mut arena = arena.borrow_mut();
890 match arena.nodes.get_mut(&root) {
891 Some(entry) => {
892 entry.size += count;
893 entry.size > NODE_LIMIT
894 }
895 None => false,
896 }
897 });
898 if over {
899 OVER_LIMIT.with(|flag| flag.set(true));
900 }
901}
902
903fn expression_size(node: &Value) -> usize {
905 let Some(root) = root_id(node) else {
906 return 0;
907 };
908 ARENA.with(|arena| {
909 arena
910 .borrow()
911 .nodes
912 .get(&root)
913 .map_or(0, |entry| entry.size)
914 })
915}
916
917fn adopt(container: &Value, term: &Value) {
921 let (Some(into), Some(from)) = (root_id(container), root_id(term)) else {
922 return;
923 };
924 if into == from {
925 return;
926 }
927 grow(container, expression_size(term));
928}
929
930fn adopt_all(container: &Value, terms: &[Value]) {
931 for term in terms {
932 adopt(container, term);
933 }
934}
935
936fn handle_for(id: u64) -> Value {
939 let mut meta: IndexMap<String, Value> = IndexMap::new();
940 meta.insert(EXPR_META.into(), Value::Number(id as f64));
941 Value::ListRef(Arc::new(ListRef {
942 value: Vec::new(),
943 implicit: false,
944 child: None,
945 meta,
946 }))
947}
948
949fn root_id(value: &Value) -> Option<u64> {
951 let id = node_id(value)?;
952 ARENA.with(|arena| arena.borrow().nodes.get(&id).map(|node| node.root))
953}
954
955fn root_node(value: &Value) -> Value {
957 match root_id(value) {
958 Some(id) => handle_for(id),
959 None => value.clone(),
960 }
961}
962
963fn with_node<R>(value: &Value, read: impl FnOnce(&ExprNode) -> R) -> Option<R> {
964 let id = node_id(value)?;
965 ARENA.with(|arena| arena.borrow().nodes.get(&id).map(read))
966}
967
968fn with_node_mut<R>(value: &Value, write: impl FnOnce(&mut ExprNode) -> R) -> Option<R> {
969 let id = node_id(value)?;
970 ARENA.with(|arena| arena.borrow_mut().nodes.get_mut(&id).map(write))
971}
972
973fn update_expr_node(node: &Value, op: Option<Arc<Op>>, token: Option<Token>, terms: Vec<Value>) {
976 adopt_all(node, &terms);
977 with_node_mut(node, |entry| {
978 entry.op = op;
979 entry.token = token;
980 entry.terms = terms;
981 });
982}
983
984fn dup_node(node: &Value) -> Value {
987 let Some((op, token, terms)) = with_node(node, |entry| {
988 (entry.op.clone(), entry.token.clone(), entry.terms.clone())
989 }) else {
990 return node.clone();
991 };
992 new_node_under(op, token, terms, Some(node))
993}
994
995fn term_at(node: &Value, index: usize) -> Value {
998 with_node(node, |entry| {
999 entry
1000 .terms
1001 .get(index.saturating_sub(1))
1002 .cloned()
1003 .unwrap_or(Value::Undefined)
1004 })
1005 .unwrap_or(Value::Undefined)
1006}
1007
1008fn set_term(node: &Value, index: usize, value: Value) {
1011 adopt(node, &value);
1012 with_node_mut(node, |entry| {
1013 let slot = index.saturating_sub(1);
1014 while entry.terms.len() <= slot {
1015 entry.terms.push(Value::Undefined);
1016 }
1017 entry.terms[slot] = value;
1018 });
1019}
1020
1021fn push_term(node: &Value, value: Value) {
1023 adopt(node, &value);
1024 with_node_mut(node, |entry| entry.terms.push(value));
1025}
1026
1027fn term_count(node: &Value) -> usize {
1029 with_node(node, |entry| entry.terms.len()).unwrap_or(0)
1030}
1031
1032fn released_handle(id: u64) -> ! {
1046 panic!(
1047 "tabnas-expr: expression node {id} has been released. The value \
1048 holding this handle outlived its parse: realize it with \
1049 `tabnas_expr::realize` inside the `parse_scope` closure, or before \
1050 the next parse on this thread, and let the realized value escape \
1051 instead."
1052 )
1053}
1054
1055fn release_arena() {
1062 ARENA.with(|arena| {
1063 let mut arena = arena.borrow_mut();
1064 if 0 == arena.active {
1065 arena.nodes.clear();
1066 EVALUATED.with(|set| set.borrow_mut().clear());
1067 OVER_LIMIT.with(|flag| flag.set(false));
1068 }
1069 });
1070}
1071
1072struct ArenaGuard;
1075
1076impl ArenaGuard {
1077 fn enter() -> Self {
1078 ARENA.with(|arena| arena.borrow_mut().active += 1);
1079 OVER_LIMIT.with(|flag| flag.set(false));
1080 ArenaGuard
1081 }
1082}
1083
1084impl Drop for ArenaGuard {
1085 fn drop(&mut self) {
1086 ARENA.with(|arena| {
1087 let mut arena = arena.borrow_mut();
1088 arena.active = arena.active.saturating_sub(1);
1089 if 0 == arena.active {
1090 arena.nodes.clear();
1091 EVALUATED.with(|set| set.borrow_mut().clear());
1092 OVER_LIMIT.with(|flag| flag.set(false));
1093 }
1094 });
1095 }
1096}
1097
1098pub fn realize(value: &Value) -> Value {
1110 let mut open: Vec<u64> = Vec::new();
1111 realize_seen(value, &mut open)
1112}
1113
1114fn realize_seen(value: &Value, open: &mut Vec<u64>) -> Value {
1115 match value {
1116 Value::ListRef(list) => {
1117 let Some(id) = node_id(value) else {
1118 let mut out = (**list).clone();
1119 out.value = out
1120 .value
1121 .iter()
1122 .map(|entry| realize_seen(entry, open))
1123 .collect();
1124 return Value::ListRef(Arc::new(out));
1125 };
1126 if open.contains(&id) {
1130 return Value::String("[CIRCLE]".into());
1131 }
1132 let Some((op, token, terms)) = with_node(value, |entry| {
1133 (entry.op.clone(), entry.token.clone(), entry.terms.clone())
1134 }) else {
1135 released_handle(id)
1136 };
1137 open.push(id);
1138 let mut out = Vec::with_capacity(terms.len() + 1);
1139 if let Some(op) = &op {
1140 out.push(op.to_value(token.as_ref()));
1141 }
1142 for term in &terms {
1143 out.push(realize_seen(term, open));
1144 }
1145 open.pop();
1146 Value::array(out)
1147 }
1148 Value::Array(entries) => Value::array(
1149 entries
1150 .iter()
1151 .map(|entry| realize_seen(entry, open))
1152 .collect(),
1153 ),
1154 Value::Object(entries) => Value::object(
1155 entries
1156 .iter()
1157 .map(|(key, entry)| (key.clone(), realize_seen(entry, open)))
1158 .collect(),
1159 ),
1160 Value::MapRef(map) => {
1161 let mut out = (**map).clone();
1162 out.value = out
1163 .value
1164 .iter()
1165 .map(|(key, entry)| (key.clone(), realize_seen(entry, open)))
1166 .collect();
1167 Value::MapRef(Arc::new(out))
1168 }
1169 other => other.clone(),
1170 }
1171}
1172
1173pub fn simplify(value: &Value) -> Value {
1180 let mut open: Vec<u64> = Vec::new();
1181 simplify_seen(value, &mut open)
1182}
1183
1184fn simplify_seen(value: &Value, open: &mut Vec<u64>) -> Value {
1185 match value {
1186 Value::ListRef(list) => {
1187 let Some(id) = node_id(value) else {
1188 return Value::array(
1189 list.value
1190 .iter()
1191 .map(|entry| simplify_seen(entry, open))
1192 .collect(),
1193 );
1194 };
1195 if open.contains(&id) {
1196 return Value::String("[CIRCLE]".into());
1197 }
1198 let Some((op, terms)) =
1199 with_node(value, |entry| (entry.op.clone(), entry.terms.clone()))
1200 else {
1201 released_handle(id)
1202 };
1203 open.push(id);
1204 let mut out = Vec::with_capacity(terms.len() + 1);
1205 if let Some(op) = &op {
1206 out.push(Value::String(op.src.clone()));
1209 }
1210 for term in &terms {
1211 if term.is_undefined() {
1214 continue;
1215 }
1216 out.push(simplify_seen(term, open));
1217 }
1218 open.pop();
1219 Value::array(out)
1220 }
1221 Value::Array(entries) if realized_source(entries.first()).is_some() => {
1225 let mut out = Vec::with_capacity(entries.len());
1226 out.push(Value::String(
1227 realized_source(entries.first()).unwrap_or_default(),
1228 ));
1229 for entry in entries.iter().skip(1) {
1230 if entry.is_undefined() {
1231 continue;
1232 }
1233 out.push(simplify_seen(entry, open));
1234 }
1235 Value::array(out)
1236 }
1237 Value::Array(entries) => Value::array(
1238 entries
1239 .iter()
1240 .map(|entry| simplify_seen(entry, open))
1241 .collect(),
1242 ),
1243 Value::Object(entries) => Value::object(
1244 entries
1245 .iter()
1246 .map(|(key, entry)| (key.clone(), simplify_seen(entry, open)))
1247 .collect(),
1248 ),
1249 Value::MapRef(map) => Value::object(
1250 map.value
1251 .iter()
1252 .map(|(key, entry)| (key.clone(), simplify_seen(entry, open)))
1253 .collect(),
1254 ),
1255 Value::Text(text) => Value::String(text.string.clone()),
1256 other => other.clone(),
1257 }
1258}
1259
1260fn realized_source(value: Option<&Value>) -> Option<String> {
1263 match object_get(value?, "src") {
1264 Some(Value::String(src)) if !src.is_empty() => Some(src.clone()),
1265 _ => None,
1266 }
1267}
1268
1269#[derive(Debug, Clone)]
1277pub struct OpRef {
1278 pub op: Arc<Op>,
1279 pub token: Option<Token>,
1280}
1281
1282impl OpRef {
1283 pub fn new(op: Op) -> Self {
1286 OpRef {
1287 op: Arc::new(opify(op)),
1288 token: None,
1289 }
1290 }
1291
1292 fn at(op: &Arc<Op>, token: Option<Token>) -> Self {
1293 OpRef {
1294 op: op.clone(),
1295 token,
1296 }
1297 }
1298
1299 pub fn node(&self, terms: Vec<Value>) -> Value {
1301 new_node(Some(self.op.clone()), self.token.clone(), terms)
1302 }
1303
1304 fn node_under(&self, terms: Vec<Value>, under: &Value) -> Value {
1306 new_node_under(
1307 Some(self.op.clone()),
1308 self.token.clone(),
1309 terms,
1310 Some(under),
1311 )
1312 }
1313}
1314
1315pub fn opify(mut op: Op) -> Op {
1319 if 0 == op.terms {
1320 op.terms = if op.ternary {
1321 3
1322 } else if op.infix {
1323 2
1324 } else {
1325 1
1326 };
1327 }
1328 op
1329}
1330
1331pub fn prattify(expr: &Value, op: &OpRef) -> Value {
1340 let mut out = expr.clone();
1341 let Some(expr_op) = op_of(expr) else {
1342 return out;
1343 };
1344 let new = &op.op;
1345
1346 if new.infix {
1347 if expr_op.suffix || new.left <= expr_op.right {
1348 let prior = dup_node(expr);
1351 update_expr_node(expr, Some(new.clone()), op.token.clone(), vec![prior]);
1352 } else {
1353 let end = expr_op.terms;
1355 let last = term_at(expr, end);
1356 let drill = op_of(&last).is_some_and(|last_op| last_op.right < new.left);
1357 if drill {
1358 out = prattify(&last, op);
1359 } else {
1360 out = op.node_under(vec![last], expr);
1361 set_term(expr, end, out.clone());
1362 }
1363 }
1364 } else if new.prefix {
1365 out = op.node_under(Vec::new(), expr);
1366 set_term(expr, expr_op.terms, out.clone());
1367 } else if new.suffix {
1368 if !expr_op.suffix && expr_op.right <= new.left {
1369 let end = expr_op.terms;
1370 let last = term_at(expr, end);
1371 let drill =
1375 op_of(&last).is_some_and(|last_op| last_op.prefix && last_op.right < new.left);
1376 if drill {
1377 prattify(&last, op);
1378 } else {
1379 set_term(expr, end, op.node_under(vec![last], expr));
1380 }
1381 } else {
1382 let prior = dup_node(expr);
1383 update_expr_node(expr, Some(new.clone()), op.token.clone(), vec![prior]);
1384 }
1385 }
1386
1387 out
1388}
1389
1390fn prior_expr(rule: &mut Rule, prior: Option<&Rc<RuleSnapshot>>, op: &OpRef) -> Value {
1393 let prior_value = prior.map_or(Value::Undefined, |prior| prior.node.borrow().clone());
1394
1395 let node = if is_op(&prior_value) && !op.op.prefix {
1396 let duplicate = dup_node(&prior_value);
1400 update_expr_node(
1401 &prior_value,
1402 Some(op.op.clone()),
1403 op.token.clone(),
1404 vec![duplicate],
1405 );
1406 prior_value
1407 } else {
1408 let terms = if op.op.prefix {
1413 Vec::new()
1414 } else {
1415 vec![prior_value]
1416 };
1417 let fresh = op.node(terms);
1418 if let Some(prior) = prior {
1419 *prior.node.borrow_mut() = fresh.clone();
1424 }
1425 fresh
1426 };
1427
1428 if let Some(prior) = prior {
1430 rule.parent_rule = Some(prior.clone());
1431 rule.parent_node = Some(prior.node.clone());
1432 }
1433
1434 node
1435}
1436
1437#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1443enum EvalKey {
1444 Node(u64),
1445 Shared(usize, usize),
1446}
1447
1448thread_local! {
1449 static EVALUATED: RefCell<Vec<EvalKey>> = const { RefCell::new(Vec::new()) };
1450}
1451
1452fn eval_key(value: &Value) -> Option<EvalKey> {
1453 if let Some(id) = node_id(value) {
1454 return Some(EvalKey::Node(id));
1455 }
1456 match value {
1457 Value::Array(entries) if !entries.is_empty() => Some(EvalKey::Shared(
1458 Arc::as_ptr(entries) as usize,
1459 entries.len(),
1460 )),
1461 Value::Object(entries) if !entries.is_empty() => Some(EvalKey::Shared(
1462 Arc::as_ptr(entries) as usize,
1463 entries.len(),
1464 )),
1465 Value::ListRef(list) => Some(EvalKey::Shared(
1466 Arc::as_ptr(list) as usize,
1467 list.value.len(),
1468 )),
1469 Value::MapRef(map) => Some(EvalKey::Shared(Arc::as_ptr(map) as usize, map.value.len())),
1470 _ => None,
1471 }
1472}
1473
1474fn evaluated_seen(value: &Value) -> bool {
1475 eval_key(value).is_some_and(|key| EVALUATED.with(|set| set.borrow().contains(&key)))
1476}
1477
1478fn evaluated_mark(value: &Value) {
1479 if let Some(key) = eval_key(value) {
1480 EVALUATED.with(|set| {
1481 let mut set = set.borrow_mut();
1482 if !set.contains(&key) {
1483 set.push(key);
1484 }
1485 });
1486 }
1487}
1488
1489pub fn evaluation(site: &mut EvalSite<'_>, value: &Value, evaluate: &Evaluate) -> Value {
1496 if value.is_undefined() || matches!(value, Value::Null) {
1497 return Value::Null;
1498 }
1499 if evaluated_seen(value) {
1500 return value.clone();
1501 }
1502
1503 let out = if is_op(value) {
1504 let Some((Some(op), token, terms)) = with_node(value, |entry| {
1505 (entry.op.clone(), entry.token.clone(), entry.terms.clone())
1506 }) else {
1507 return value.clone();
1508 };
1509 let reduced: Vec<Value> = terms
1510 .iter()
1511 .map(|term| evaluation(&mut site.reborrow(), term, evaluate))
1512 .collect();
1513 let previous = std::mem::replace(&mut site.token, token);
1518 let reduction = evaluate(site, &op, &reduced);
1519 site.token = previous;
1520 reduction
1521 } else if let Value::Array(entries) = value {
1522 Value::array(
1528 entries
1529 .iter()
1530 .map(|entry| evaluation(&mut site.reborrow(), entry, evaluate))
1531 .collect(),
1532 )
1533 } else {
1534 value.clone()
1535 };
1536
1537 evaluated_mark(&out);
1538 out
1539}
1540
1541#[derive(Clone, Copy, PartialEq, Eq)]
1547enum Anyfix {
1548 Prefix,
1549 Suffix,
1550 Infix,
1551 Ternary,
1552}
1553
1554impl Anyfix {
1555 fn name(self) -> &'static str {
1556 match self {
1557 Anyfix::Prefix => "prefix",
1558 Anyfix::Suffix => "suffix",
1559 Anyfix::Infix => "infix",
1560 Anyfix::Ternary => "ternary",
1561 }
1562 }
1563
1564 fn selects(self, def: &OpDef) -> bool {
1565 match self {
1566 Anyfix::Prefix => def.prefix,
1567 Anyfix::Suffix => def.suffix,
1568 Anyfix::Infix => def.infix,
1569 Anyfix::Ternary => def.ternary,
1570 }
1571 }
1572
1573 fn terms(self) -> usize {
1574 match self {
1575 Anyfix::Ternary => 3,
1576 Anyfix::Infix => 2,
1577 _ => 1,
1578 }
1579 }
1580}
1581
1582fn operator_tin(parser: &mut Tabnas, src: &str) -> (Tin, String) {
1591 if let Some(tin) = parser.fixed(src) {
1592 let name = parser.token_name(tin);
1593 return (tin, name);
1594 }
1595 let name = format!("#E{src}");
1596 let tin = parser.token_with_source(name.clone(), src);
1597 (tin, name)
1598}
1599
1600fn binding_power(power: Option<i64>, unset: i64) -> i64 {
1610 match power {
1611 Some(0) | None => unset,
1612 Some(power) => power,
1613 }
1614}
1615
1616fn make_op_map(
1619 parser: &mut Tabnas,
1620 ops: &IndexMap<String, Option<OpDef>>,
1621 anyfix: Anyfix,
1622) -> IndexMap<Tin, Arc<Op>> {
1623 let mut map: IndexMap<Tin, Arc<Op>> = IndexMap::new();
1624 for (name, def) in ops {
1625 let Some(def) = def else { continue };
1626 if !anyfix.selects(def) {
1627 continue;
1628 }
1629 let src = def.src.first().cloned().unwrap_or_default();
1630 let (tin, tkn) = operator_tin(parser, &src);
1631
1632 let suffix = format!("-{}", anyfix.name());
1633 let op = Op {
1634 src: src.clone(),
1635 left: binding_power(def.left, MIN_SAFE_INTEGER),
1636 right: binding_power(def.right, MAX_SAFE_INTEGER),
1637 name: if name.ends_with(&suffix) {
1638 name.clone()
1639 } else {
1640 format!("{name}{suffix}")
1641 },
1642 infix: Anyfix::Infix == anyfix,
1643 prefix: Anyfix::Prefix == anyfix,
1644 suffix: Anyfix::Suffix == anyfix,
1645 ternary: Anyfix::Ternary == anyfix,
1646 tkn,
1647 tin,
1648 terms: anyfix.terms(),
1649 use_data: def.use_data.clone(),
1650 ..Default::default()
1651 };
1652
1653 if Anyfix::Ternary == anyfix {
1654 let second = def.src.get(1).cloned().unwrap_or_default();
1657 let (second_tin, second_tkn) = operator_tin(parser, &second);
1658
1659 let mut first = op.clone();
1660 first.ternary_index = Some(0);
1661 map.insert(tin, Arc::new(first));
1662
1663 let mut last = op;
1664 last.src = second;
1665 last.ternary_index = Some(1);
1666 last.tkn = second_tkn;
1667 last.tin = second_tin;
1668 map.insert(second_tin, Arc::new(last));
1669 } else {
1670 map.insert(tin, Arc::new(op));
1671 }
1672 }
1673 map
1674}
1675
1676fn make_paren_map(
1679 parser: &mut Tabnas,
1680 ops: &IndexMap<String, Option<OpDef>>,
1681) -> IndexMap<Tin, Arc<Op>> {
1682 let mut map: IndexMap<Tin, Arc<Op>> = IndexMap::new();
1683 for (name, def) in ops {
1684 let Some(def) = def else { continue };
1685 if !def.paren {
1686 continue;
1687 }
1688 let (otin, otkn) = operator_tin(parser, &def.osrc);
1689 let (ctin, ctkn) = operator_tin(parser, &def.csrc);
1690 let op = Op {
1691 name: format!("{name}-paren"),
1692 osrc: def.osrc.clone(),
1693 csrc: def.csrc.clone(),
1694 otkn,
1695 otin,
1696 ctkn,
1697 ctin,
1698 preval: def.preval.clone().unwrap_or_default(),
1699 paren: true,
1700 src: def.osrc.clone(),
1701 terms: 1,
1702 use_data: def.use_data.clone(),
1703 ..Default::default()
1704 };
1705 map.insert(otin, Arc::new(op));
1706 }
1707 map
1708}
1709
1710struct Grammar {
1713 prefix: IndexMap<Tin, Arc<Op>>,
1714 suffix: IndexMap<Tin, Arc<Op>>,
1715 infix: IndexMap<Tin, Arc<Op>>,
1716 ternary: IndexMap<Tin, Arc<Op>>,
1717 paren_open: IndexMap<Tin, Arc<Op>>,
1718 paren_close: IndexMap<Tin, Arc<Op>>,
1719 tin_prefix: Vec<Tin>,
1720 tin_suffix: Vec<Tin>,
1721 tin_infix: Vec<Tin>,
1722 tin_tern0: Vec<Tin>,
1723 tin_tern1: Vec<Tin>,
1724 tin_open: Vec<Tin>,
1725 tin_close: Vec<Tin>,
1726 evaluate: Option<Evaluate>,
1727}
1728
1729const VAL_TINS: [Tin; 4] = [TIN_TX, TIN_NR, TIN_ST, TIN_VL];
1732
1733impl Grammar {
1734 fn has_prefix(&self) -> bool {
1735 !self.tin_prefix.is_empty()
1736 }
1737
1738 fn has_infix(&self) -> bool {
1739 !self.tin_infix.is_empty()
1740 }
1741
1742 fn has_suffix(&self) -> bool {
1743 !self.tin_suffix.is_empty()
1744 }
1745
1746 fn has_ternary(&self) -> bool {
1747 !self.tin_tern0.is_empty() && !self.tin_tern1.is_empty()
1748 }
1749
1750 fn has_paren(&self) -> bool {
1751 !self.tin_open.is_empty() && !self.tin_close.is_empty()
1752 }
1753
1754 fn op_use(map: &IndexMap<Tin, Arc<Op>>, token: Option<&Token>) -> Option<OpRef> {
1757 let token = token?;
1758 map.get(&token.tin)
1759 .map(|op| OpRef::at(op, Some(token.clone())))
1760 }
1761}
1762
1763fn counter(rule: &Rule, name: &str) -> i32 {
1769 rule.n.get(name).copied().unwrap_or(0)
1770}
1771
1772fn local_number(rule: &Rule, name: &str) -> i64 {
1774 match rule.u.get(name) {
1775 Some(Value::Number(number)) => *number as i64,
1776 _ => 0,
1777 }
1778}
1779
1780fn set_local_number(rule: &mut Rule, name: &str, value: i64) {
1781 rule.u_mut()
1782 .insert(name.to_string(), Value::Number(value as f64));
1783}
1784
1785fn set_node(rule: &mut Rule, value: Value) {
1791 rule.node = Rc::new(RefCell::new(value));
1792}
1793
1794fn node_of(rule: &Rule) -> Value {
1795 rule.node.borrow().clone()
1796}
1797
1798const ATTACH: &str = "expr_attach";
1802
1803fn publish_expr(rule: &mut Rule, attach: Value) {
1817 set_node(rule, attach.clone());
1818 rule.u_mut().insert(ATTACH.to_string(), attach);
1819}
1820
1821fn publish(rule: &mut Rule, value: Value) {
1823 *rule.node.borrow_mut() = value;
1824}
1825
1826fn expression_root(rule: &Rule) -> Value {
1833 root_node(&node_of(rule))
1834}
1835
1836fn linked_node(link: Option<&Rc<RuleSnapshot>>) -> Value {
1844 let Some(link) = link else {
1845 return Value::Undefined;
1846 };
1847 if let Some(attach) = link.u.get(ATTACH) {
1848 if is_op(attach) {
1849 return attach.clone();
1850 }
1851 }
1852 link.node.borrow().clone()
1853}
1854
1855fn write_linked_node(link: Option<&Rc<RuleSnapshot>>, value: Value) {
1856 if let Some(link) = link {
1857 *link.node.borrow_mut() = value;
1858 }
1859}
1860
1861fn counters(pairs: &[(&str, i32)]) -> HashMap<String, i32> {
1862 pairs
1863 .iter()
1864 .map(|(name, value)| ((*name).to_string(), *value))
1865 .collect()
1866}
1867
1868fn locals(pairs: &[(&str, Value)]) -> HashMap<String, Value> {
1869 pairs
1870 .iter()
1871 .map(|(name, value)| ((*name).to_string(), value.clone()))
1872 .collect()
1873}
1874
1875fn on(tins: &[Tin]) -> AltSpec {
1877 AltSpec {
1878 s: vec![tins.to_vec()],
1879 ..Default::default()
1880 }
1881}
1882
1883fn on2(first: &[Tin], second: &[Tin]) -> AltSpec {
1885 AltSpec {
1886 s: vec![first.to_vec(), second.to_vec()],
1887 ..Default::default()
1888 }
1889}
1890
1891fn always() -> AltSpec {
1893 AltSpec::default()
1894}
1895
1896fn group_has(tags: &str, tag: &str) -> bool {
1897 tags.split(',').any(|entry| entry.trim() == tag)
1898}
1899
1900fn prepend_open_all(spec: &mut RuleSpec, alts: Vec<AltSpec>) {
1904 for alt in alts.into_iter().rev() {
1905 spec.prepend_open(alt);
1906 }
1907}
1908
1909fn prepend_close_all(spec: &mut RuleSpec, alts: Vec<AltSpec>) {
1910 for alt in alts.into_iter().rev() {
1911 spec.prepend_close(alt);
1912 }
1913}
1914
1915pub fn expr(parser: &mut Tabnas, options: &ExprOptions) -> Result<(), PluginError> {
1925 let rules = parser.rule_names();
1926
1927 if rules.iter().any(|name| "expr" == name) {
1931 return Ok(());
1932 }
1933
1934 if !rules.iter().any(|name| "val" == name) {
1938 return Err(PluginError(
1939 "tabnas-expr: the instance carries no `val` rule. This plugin layers on the \
1940 jsonic base grammar; install that first (tabnas_jsonic::jsonic, or \
1941 tabnas_expr::make)."
1942 .into(),
1943 ));
1944 }
1945
1946 let ops = resolve_options(options);
1947
1948 let prefix = make_op_map(parser, &ops, Anyfix::Prefix);
1949 let suffix = make_op_map(parser, &ops, Anyfix::Suffix);
1950 let infix = make_op_map(parser, &ops, Anyfix::Infix);
1951 let ternary = make_op_map(parser, &ops, Anyfix::Ternary);
1952 let paren_open = make_paren_map(parser, &ops);
1953 let paren_close: IndexMap<Tin, Arc<Op>> = paren_open
1954 .values()
1955 .map(|op| (op.ctin, op.clone()))
1956 .collect();
1957
1958 let grammar = Arc::new(Grammar {
1959 tin_prefix: prefix.keys().copied().collect(),
1960 tin_suffix: suffix.keys().copied().collect(),
1961 tin_infix: infix.keys().copied().collect(),
1962 tin_tern0: ternary
1963 .values()
1964 .filter(|op| Some(0) == op.ternary_index)
1965 .map(|op| op.tin)
1966 .collect(),
1967 tin_tern1: ternary
1968 .values()
1969 .filter(|op| Some(1) == op.ternary_index)
1970 .map(|op| op.tin)
1971 .collect(),
1972 tin_open: paren_open.values().map(|op| op.otin).collect(),
1973 tin_close: paren_close.values().map(|op| op.ctin).collect(),
1974 prefix,
1975 suffix,
1976 infix,
1977 ternary,
1978 paren_open,
1979 paren_close,
1980 evaluate: options.evaluate.clone(),
1981 });
1982
1983 comment_before_fixed(parser, &grammar);
1984
1985 parser.parse_prepare(|_context: &mut Context| release_arena());
1990
1991 bound_expression_size(parser);
1992
1993 install_val(parser, &grammar);
1994 install_list(parser, &grammar);
1995 install_map(parser, &grammar);
1996 install_elem(parser, &grammar);
1997 install_pair(parser, &grammar);
1998 install_expr(parser, &grammar);
1999 if grammar.has_paren() {
2000 install_paren(parser, &grammar);
2001 }
2002 if grammar.has_ternary() {
2003 install_ternary(parser, &grammar);
2004 }
2005
2006 Ok(())
2007}
2008
2009fn comment_before_fixed(parser: &mut Tabnas, grammar: &Grammar) {
2035 let options = parser.config();
2036 let markers: Vec<String> = options
2037 .comment
2038 .definitions
2039 .values()
2040 .filter(|def| def.lex)
2041 .map(|def| def.start.clone())
2042 .filter(|start| !start.is_empty())
2043 .collect();
2044 if markers.is_empty() {
2045 return;
2046 }
2047
2048 let sources: Vec<String> = grammar
2049 .prefix
2050 .values()
2051 .chain(grammar.suffix.values())
2052 .chain(grammar.infix.values())
2053 .chain(grammar.ternary.values())
2054 .map(|op| op.src.clone())
2055 .chain(
2056 grammar
2057 .paren_open
2058 .values()
2059 .flat_map(|op| [op.osrc.clone(), op.csrc.clone()]),
2060 )
2061 .filter(|src| !src.is_empty())
2062 .collect();
2063
2064 let contested: Vec<String> = markers
2065 .into_iter()
2066 .filter(|marker| {
2067 sources
2068 .iter()
2069 .any(|src| src.len() < marker.len() && marker.starts_with(src.as_str()))
2070 })
2071 .collect();
2072 if contested.is_empty() {
2073 return;
2074 }
2075
2076 parser.lex_check_ref(COMMENT_FIRST, move |remaining: &str| {
2077 if contested
2078 .iter()
2079 .any(|marker| remaining.starts_with(marker.as_str()))
2080 {
2081 tabnas::LexCheckResult::Skip
2082 } else {
2083 tabnas::LexCheckResult::Continue
2084 }
2085 });
2086 let _ = parser.grammar_json(COMMENT_FIRST_DOCUMENT);
2087}
2088
2089fn bound_expression_size(parser: &mut Tabnas) {
2096 let budget = parser.config().parse.budget.clone();
2097 let existing = budget.on_check.clone();
2098 let every = match budget.check_every_n {
2099 0 => 32,
2100 set => set.min(32),
2101 };
2102 parser.parse_budget(every, move |context: &Context| {
2103 if OVER_LIMIT.with(Cell::get) {
2104 return false;
2105 }
2106 if context.rule_stack.len() > RULE_LIMIT {
2107 return false;
2108 }
2109 existing.as_ref().is_none_or(|check| check(context))
2110 });
2111}
2112
2113const COMMENT_FIRST: &str = "@expr-comment-before-fixed";
2114const COMMENT_FIRST_DOCUMENT: &str =
2115 r#"{"options":{"fixed":{"check":"@expr-comment-before-fixed"}}}"#;
2116
2117fn install_val(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
2122 let grammar = grammar.clone();
2123 parser.define_rule("val", move |spec| {
2124 if grammar.has_ternary() && grammar.tin_tern1.contains(&TIN_CL) {
2127 for alt in spec.open.iter_mut().filter(|alt| group_has(&alt.g, "pair")) {
2128 let previous = alt.c_fn.clone();
2129 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, context: &mut Context| {
2130 previous
2131 .as_ref()
2132 .is_none_or(|condition| condition(rule, context))
2133 && 0 == counter(rule, "expr_ternary")
2134 }));
2135 }
2136 }
2137
2138 let mut open: Vec<AltSpec> = Vec::new();
2139
2140 if grammar.has_prefix() {
2142 let mut alt = on(&grammar.tin_prefix);
2143 alt.b = 1;
2144 alt.n = counters(&[("expr_prefix", 1), ("expr_suffix", 0)]);
2145 alt.p = Some("expr".into());
2146 alt.g = "expr,expr-prefix".into();
2147 alt.add_action(detach_node);
2148 open.push(alt);
2149 }
2150
2151 if grammar.has_paren() {
2153 let mut alt = on2(&VAL_TINS, &grammar.tin_open);
2154 alt.b = 1;
2155 alt.p = Some("expr".into());
2156 let condition = grammar.clone();
2157 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, context: &mut Context| {
2158 let Some(pdef) = rule
2159 .o1()
2160 .and_then(|token| condition.paren_open.get(&token.tin))
2161 .cloned()
2162 else {
2163 return false;
2164 };
2165 if !pdef.preval.active {
2166 return false;
2167 }
2168 let Some(allow) = &pdef.preval.allow else {
2169 return true;
2170 };
2171 let preval = rule.resolve_open_value(0, context);
2172 allow.contains(&value_string(Some(&preval)))
2173 }));
2174 alt.u = locals(&[("paren_preval", Value::Bool(true))]);
2175 alt.g = "expr,expr-paren,expr-paren-preval".into();
2176 alt.add_action(|rule: &mut Rule, context: &mut Context| {
2177 let preval = rule.resolve_open_value(0, context);
2178 set_node(rule, preval);
2179 });
2180 open.push(alt);
2181 }
2182
2183 if grammar.has_paren() {
2186 let mut alt = on(&grammar.tin_open);
2187 alt.b = 1;
2188 alt.p = Some("expr".into());
2189 let condition = grammar.clone();
2190 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, _context: &mut Context| {
2191 rule.o0()
2192 .and_then(|token| condition.paren_open.get(&token.tin))
2193 .is_some_and(|pdef| !pdef.preval.required)
2194 }));
2195 alt.g = "expr,expr-paren".into();
2196 alt.add_action(detach_node);
2197 open.push(alt);
2198 }
2199
2200 prepend_open_all(spec, open);
2201
2202 let mut close: Vec<AltSpec> = Vec::new();
2203
2204 if grammar.has_infix() {
2211 let mut alt = on(&grammar.tin_infix);
2212 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2213 0 < counter(rule, "no_comma_op")
2214 && rule.c0().is_some_and(|token| "," == token.src.as_str())
2215 }));
2216 alt.b = 1;
2217 alt.g = "expr,no-comma-op-bail".into();
2218 close.push(alt);
2219 }
2220
2221 if grammar.has_ternary() {
2222 let mut alt = on(&grammar.tin_tern0);
2223 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2224 0 == counter(rule, "expr")
2225 }));
2226 alt.b = 1;
2227 alt.r = Some("ternary".into());
2228 alt.g = "expr,expr-ternary".into();
2229 close.push(alt);
2230 }
2231
2232 if grammar.has_infix() {
2234 let mut alt = on(&grammar.tin_infix);
2235 alt.b = 1;
2236 alt.n = counters(&[("expr_prefix", 0), ("expr_suffix", 0)]);
2237 alt.r_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2238 (0 == counter(rule, "expr")).then(|| "expr".to_string())
2239 }));
2240 alt.g = "expr,expr-infix".into();
2241 close.push(alt);
2242 }
2243
2244 if grammar.has_suffix() {
2246 let mut alt = on(&grammar.tin_suffix);
2247 alt.b = 1;
2248 alt.n = counters(&[("expr_prefix", 0), ("expr_suffix", 1)]);
2249 alt.r_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2250 (0 == counter(rule, "expr")).then(|| "expr".to_string())
2251 }));
2252 alt.g = "expr,expr-suffix".into();
2253 close.push(alt);
2254 }
2255
2256 if grammar.has_paren() {
2258 let mut alt = on(&grammar.tin_close);
2259 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2260 0 != counter(rule, "expr_paren")
2261 }));
2262 alt.b = 1;
2263 alt.g = "expr,expr-paren".into();
2264 close.push(alt);
2265 }
2266
2267 if grammar.has_paren() {
2281 let mut alt = on(&grammar.tin_open);
2282 alt.b = 1;
2283 let condition = grammar.clone();
2284 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, _context: &mut Context| {
2285 let Some(pdef) = rule
2286 .c0()
2287 .and_then(|token| condition.paren_open.get(&token.tin))
2288 .cloned()
2289 else {
2290 return false;
2291 };
2292 let node = node_of(rule);
2293 if !pdef.preval.active || node.is_undefined() {
2294 return false;
2295 }
2296 let Some(allow) = &pdef.preval.allow else {
2297 return true;
2298 };
2299 allow.contains(&value_string(Some(&node)))
2300 }));
2301 alt.p = Some("expr".into());
2302 alt.u = locals(&[("paren_preval", Value::Bool(true))]);
2303 alt.g = "expr,expr-paren,expr-paren-preval-chain".into();
2304 close.push(alt);
2305 }
2306
2307 if grammar.has_ternary() {
2308 let mut alt = on(&grammar.tin_tern1);
2309 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2310 0 != counter(rule, "expr_ternary")
2311 }));
2312 alt.b = 1;
2313 alt.g = "expr,expr-ternary".into();
2314 close.push(alt);
2315 }
2316
2317 let mut comma = on(&[TIN_CA]);
2320 comma.c_fn = Some(Arc::new(no_implicit_in_expr));
2321 comma.b = 1;
2322 comma.g = "expr,list,val,imp,comma,top".into();
2323 close.push(comma);
2324
2325 let mut space = on(&VAL_TINS);
2328 space.c_fn = Some(Arc::new(no_implicit_in_expr));
2329 space.b = 1;
2330 space.g = "expr,list,val,imp,space,top".into();
2331 close.push(space);
2332
2333 prepend_close_all(spec, close);
2334 });
2335}
2336
2337fn detach_node(rule: &mut Rule, _context: &mut Context) {
2347 let node = node_of(rule);
2348 set_node(rule, node);
2349}
2350
2351fn no_implicit_in_expr(rule: &mut Rule, _context: &mut Context) -> bool {
2352 (1 == rule.d && (1 <= counter(rule, "expr") || 1 <= counter(rule, "expr_ternary")))
2353 || (1 <= counter(rule, "expr_ternary") && 1 <= counter(rule, "expr_paren"))
2354}
2355
2356fn clear_expr_counters(rule: &mut Rule) {
2361 let counters = rule.n_mut();
2362 counters.insert("expr".into(), 0);
2363 counters.insert("expr_prefix".into(), 0);
2364 counters.insert("expr_suffix".into(), 0);
2365 counters.insert("expr_paren".into(), 0);
2366 counters.insert("expr_ternary".into(), 0);
2367}
2368
2369fn install_list(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
2370 let grammar = grammar.clone();
2371 parser.define_rule("list", move |spec| {
2372 spec.prepend_bo(|rule: &mut Rule, _context: &mut Context| {
2373 let implicit = rule
2376 .prev_rule
2377 .as_ref()
2378 .is_some_and(|prev| matches!(prev.u.get("implist"), Some(Value::Bool(true))));
2379 if !implicit {
2380 clear_expr_counters(rule);
2381 }
2382 });
2383
2384 if grammar.has_paren() {
2385 let mut alt = on(&grammar.tin_close);
2386 alt.b_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2389 let square = rule.c0().is_some_and(|token| TIN_CS == token.tin);
2390 if square && 0 == counter(rule, "expr_paren") {
2391 0
2392 } else {
2393 1
2394 }
2395 }));
2396 alt.g = "expr".into();
2397 prepend_close_all(spec, vec![alt]);
2398
2399 spec.add_ac(|rule: &mut Rule, _context: &mut Context| {
2400 propagate_to_paren(rule);
2401 });
2402 }
2403 });
2404}
2405
2406fn install_map(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
2407 let grammar = grammar.clone();
2408 parser.define_rule("map", move |spec| {
2409 spec.prepend_bo(|rule: &mut Rule, _context: &mut Context| clear_expr_counters(rule));
2411
2412 if grammar.has_paren() {
2413 let mut alt = on(&grammar.tin_close);
2414 alt.b_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2417 let brace = rule.c0().is_some_and(|token| TIN_CB == token.tin);
2418 if brace && 0 == counter(rule, "expr_paren") {
2419 0
2420 } else {
2421 1
2422 }
2423 }));
2424 alt.g = "expr".into();
2425 prepend_close_all(spec, vec![alt]);
2426 }
2427 });
2428}
2429
2430fn install_elem(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
2431 let grammar = grammar.clone();
2432 parser.define_rule("elem", move |spec| {
2433 if !grammar.has_paren() {
2434 return;
2435 }
2436 let mut close: Vec<AltSpec> = Vec::new();
2437
2438 let mut alt = on(&grammar.tin_close);
2440 alt.b = 1;
2441 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2442 0 != counter(rule, "expr_paren")
2443 }));
2444 alt.g = "expr,expr-paren,imp,close,list".into();
2445 close.push(alt);
2446
2447 let mut alt = on(&grammar.tin_open);
2449 alt.b = 1;
2450 alt.r = Some("elem".into());
2451 alt.g = "expr,expr-paren,imp,open,list".into();
2452 close.push(alt);
2453
2454 prepend_close_all(spec, close);
2455
2456 spec.add_ac(|rule: &mut Rule, _context: &mut Context| {
2462 propagate_to_paren(rule);
2463 });
2464 });
2465}
2466
2467fn propagate_to_paren(rule: &mut Rule) {
2469 if 0 == counter(rule, "expr_paren") {
2470 return;
2471 }
2472 let node = node_of(rule);
2473 let mut cursor = rule.parent_rule.clone();
2474 while let Some(current) = cursor {
2475 if "paren" == current.name.as_ref() {
2476 *current.node.borrow_mut() = node;
2477 return;
2478 }
2479 cursor = current.parent_rule.clone();
2480 }
2481}
2482
2483fn install_pair(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
2484 let grammar = grammar.clone();
2485 parser.define_rule("pair", move |spec| {
2486 if !grammar.has_paren() {
2487 return;
2488 }
2489 let mut alt = on(&grammar.tin_close);
2491 alt.b = 1;
2492 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2493 0 != counter(rule, "expr_paren") || 0 < counter(rule, "pk")
2494 }));
2495 alt.g = "expr,expr-paren,imp,map".into();
2496 prepend_close_all(spec, vec![alt]);
2497 });
2498}
2499
2500fn expr_root(rule: &Rule) -> Value {
2513 let parent = linked_node(rule.parent_rule.as_ref());
2514 if rule.parent_rule.is_some() && is_op(&parent) {
2515 return parent;
2516 }
2517
2518 let mut root: Option<Value> = None;
2521 if "expr" == rule.name.as_ref() {
2522 let node = node_of(rule);
2523 if is_op(&node) {
2524 root = Some(node);
2525 }
2526 }
2527 let mut cursor = rule.prev_rule.clone();
2528 while let Some(current) = cursor {
2529 if "expr" == current.name.as_ref() {
2530 let node = current.node.borrow().clone();
2531 if is_op(&node) {
2532 root = Some(node);
2533 }
2534 }
2535 cursor = current.prev_rule.clone();
2536 }
2537
2538 root.unwrap_or_else(|| node_of(rule))
2539}
2540
2541fn top_list(rule: &mut Rule) -> Value {
2549 let list = Value::array(vec![expr_root(rule)]);
2550
2551 if rule.parent_rule.is_some() {
2552 write_linked_node(rule.parent_rule.as_ref(), list.clone());
2553 return list;
2554 }
2555
2556 set_node(rule, list.clone());
2562 let mut cursor = rule.prev_rule.clone();
2563 while let Some(current) = cursor {
2564 *current.node.borrow_mut() = list.clone();
2565 cursor = current.prev_rule.clone();
2566 }
2567
2568 list
2569}
2570
2571fn implicit_list(mut matched: AltMatch, rule: &mut Rule, context: &mut Context) -> AltMatch {
2574 let mut paren: Option<Rc<RuleSnapshot>> = None;
2579 let mut paren_index = 0usize;
2580 for index in (0..context.rule_stack.len()).rev() {
2581 let frame = &context.rule_stack[index];
2582 let name = frame.name.as_ref();
2583 if "paren" == name {
2584 paren = Some(frame.clone());
2585 paren_index = index;
2586 break;
2587 }
2588 if "map" == name || "list" == name {
2589 return matched;
2590 }
2591 }
2592
2593 let Some(paren) = paren else {
2594 return matched;
2595 };
2596
2597 let expr_node = node_of(rule);
2603 let expr_node = if is_op(&expr_node) {
2604 expression_root(rule)
2605 } else {
2606 expr_node
2607 };
2608
2609 let paren_node = paren.node.borrow().clone();
2619 if matches!(&paren_node, Value::Array(members) if !members.is_empty()) {
2620 return matched;
2624 }
2625
2626 *paren.node.borrow_mut() = Value::array(vec![expr_node.clone()]);
2627 matched.r = Some("elem".into());
2628 matched.b = 0;
2629
2630 let list = paren.node.borrow().clone();
2631 set_node(rule, list.clone());
2632
2633 write_linked_node(rule.parent_rule.as_ref(), list.clone());
2639
2640 for index in (paren_index + 1)..context.rule_stack.len() {
2656 let frame = context.rule_stack[index].clone();
2657 let name = frame.name.as_ref().to_string();
2658 let node = frame.node.borrow().clone();
2659 let carries = "expr" == name
2660 || ("val" == name
2661 && (node.is_undefined()
2662 || matches!(node, Value::Null)
2663 || same_node(&node, &expr_node)
2664 || is_op(&node)));
2665 if carries {
2666 *frame.node.borrow_mut() = list.clone();
2667 }
2668 }
2669
2670 matched
2671}
2672
2673fn same_node(left: &Value, right: &Value) -> bool {
2675 match (node_id(left), node_id(right)) {
2676 (Some(left), Some(right)) => left == right,
2677 _ => false,
2678 }
2679}
2680
2681fn install_expr(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
2682 let grammar = grammar.clone();
2683 parser.define_rule("expr", move |spec| {
2684 let mut open: Vec<AltSpec> = Vec::new();
2685
2686 if grammar.has_paren() {
2688 let mut alt = on(&grammar.tin_open);
2689 alt.p = Some("paren".into());
2690 alt.b = 1;
2691 alt.g = "expr,expr-paren,expr-start".into();
2692 open.push(alt);
2693 }
2694
2695 if grammar.has_prefix() {
2696 let mut alt = on(&grammar.tin_prefix);
2697 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2698 0 != counter(rule, "expr_prefix")
2699 }));
2700 alt.n = counters(&[("expr", 1), ("dlist", 1), ("dmap", 1)]);
2701 alt.p = Some("val".into());
2702 alt.g = "expr,expr-prefix".into();
2703 let ops = grammar.clone();
2704 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
2705 let Some(op) = Grammar::op_use(&ops.prefix, rule.o0()) else {
2706 return;
2707 };
2708 let parent = linked_node(rule.parent_rule.as_ref());
2709 if is_op(&parent) && !is_ternary_op(&parent) && !is_paren_op(&parent) {
2717 let attach = prattify(&parent, &op);
2718 publish_expr(rule, attach);
2719 } else {
2720 let prior = rule.parent_rule.clone();
2721 let node = prior_expr(rule, prior.as_ref(), &op);
2722 publish_expr(rule, node);
2723 }
2724 });
2725 open.push(alt);
2726 }
2727
2728 if grammar.has_infix() {
2729 let mut alt = on(&grammar.tin_infix);
2730 alt.p = Some("val".into());
2731 alt.n = counters(&[("expr", 1), ("expr_prefix", 0), ("dlist", 1), ("dmap", 1)]);
2732 alt.g = "expr,expr-infix".into();
2733 let ops = grammar.clone();
2734 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
2735 let Some(op) = Grammar::op_use(&ops.infix, rule.o0()) else {
2736 return;
2737 };
2738 let parent = linked_node(rule.parent_rule.as_ref());
2739 let previous = linked_node(rule.prev_rule.as_ref());
2740
2741 if is_op(&parent) && !is_ternary_op(&parent) {
2743 let attach = prattify(&parent, &op);
2744 publish_expr(rule, attach);
2745 }
2746 else if is_op(&previous) {
2748 let attach = prattify(&previous, &op);
2749 if let Some(prev) = rule.prev_rule.clone() {
2750 rule.parent_node = Some(prev.node.clone());
2751 rule.parent_rule = Some(prev);
2752 }
2753 publish_expr(rule, attach);
2754 }
2755 else {
2757 let prior = rule.prev_rule.clone();
2758 let node = prior_expr(rule, prior.as_ref(), &op);
2759 publish_expr(rule, node);
2760 }
2761 });
2762 open.push(alt);
2763 }
2764
2765 if grammar.has_suffix() {
2766 let mut alt = on(&grammar.tin_suffix);
2767 alt.n = counters(&[("expr", 1), ("expr_prefix", 0), ("dlist", 1), ("dmap", 1)]);
2768 alt.g = "expr,expr-suffix".into();
2769 let ops = grammar.clone();
2770 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
2771 let Some(op) = Grammar::op_use(&ops.suffix, rule.o0()) else {
2772 return;
2773 };
2774 let previous = linked_node(rule.prev_rule.as_ref());
2775 if is_op(&previous) {
2776 let attach = prattify(&previous, &op);
2777 publish_expr(rule, attach);
2778 } else {
2779 let prior = rule.prev_rule.clone();
2780 let node = prior_expr(rule, prior.as_ref(), &op);
2781 publish_expr(rule, node);
2782 }
2783 });
2784 open.push(alt);
2785 }
2786
2787 prepend_open_all(spec, open);
2788
2789 spec.add_bc(|rule: &mut Rule, _context: &mut Context| {
2791 let node = node_of(rule);
2792 let Some(op) = op_of(&node) else {
2793 return;
2794 };
2795 let child = rule.child_node.clone();
2796 if term_count(&node) < op.terms && !same_node(&node, &child) {
2797 push_term(&node, child);
2798 }
2799 });
2800
2801 let mut close: Vec<AltSpec> = Vec::new();
2802
2803 let mut alt = always();
2804 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2805 rule.child_rule
2806 .as_ref()
2807 .is_some_and(|child| "paren" == child.name.as_ref())
2808 }));
2809 alt.n = counters(&[("expr", 0)]);
2810 alt.g = "expr,expr-end,expr-paren-end".into();
2811 close.push(alt);
2812
2813 if grammar.has_infix() {
2819 let mut alt = on(&grammar.tin_infix);
2820 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2821 0 < counter(rule, "no_comma_op")
2822 && rule.c0().is_some_and(|token| "," == token.src.as_str())
2823 }));
2824 alt.b = 1;
2825 alt.n = counters(&[("expr", 0)]);
2826 alt.g = "expr,no-comma-op-bail".into();
2827 close.push(alt);
2828 }
2829
2830 if grammar.has_infix() {
2831 let mut alt = on(&grammar.tin_infix);
2833 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2834 0 == counter(rule, "expr_prefix")
2835 }));
2836 alt.b = 1;
2837 alt.r = Some("expr".into());
2838 alt.g = "expr,expr-infix,expr-prefix".into();
2839 close.push(alt);
2840
2841 let mut alt = on(&grammar.tin_infix);
2842 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2843 0 != counter(rule, "expr_prefix")
2844 }));
2845 alt.b = 1;
2846 alt.g = "expr,expr-infix".into();
2847 close.push(alt);
2848 }
2849
2850 if grammar.has_suffix() {
2851 let mut alt = on(&grammar.tin_suffix);
2852 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2853 0 == counter(rule, "expr_prefix")
2854 }));
2855 alt.b = 1;
2856 alt.r = Some("expr".into());
2857 alt.g = "expr,expr-suffix,expr-prefix".into();
2858 close.push(alt);
2859 }
2860
2861 if grammar.has_paren() {
2862 let mut alt = on(&grammar.tin_close);
2863 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2864 0 != counter(rule, "expr_paren")
2865 }));
2866 alt.b = 1;
2867 alt.g = "expr".into();
2868 close.push(alt);
2869 }
2870
2871 if grammar.has_ternary() {
2872 let mut alt = on(&grammar.tin_tern0);
2873 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2874 0 == counter(rule, "expr_prefix")
2875 }));
2876 alt.b = 1;
2877 alt.r = Some("ternary".into());
2878 alt.g = "expr,expr-ternary".into();
2879 close.push(alt);
2880 }
2881
2882 let mut alt = on(&[TIN_CA]);
2884 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2885 0 == rule.d
2886 }));
2887 alt.n = counters(&[("expr", 0)]);
2888 alt.r = Some("elem".into());
2889 alt.add_action(|rule: &mut Rule, _context: &mut Context| {
2890 let list = top_list(rule);
2891 set_node(rule, list);
2892 });
2893 alt.g = "expr,comma,list,top".into();
2894 close.push(alt);
2895
2896 let mut alt = on(&VAL_TINS);
2898 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2899 0 == rule.d
2900 }));
2901 alt.n = counters(&[("expr", 0)]);
2902 alt.b = 1;
2903 alt.r = Some("elem".into());
2904 alt.add_action(|rule: &mut Rule, _context: &mut Context| {
2905 let list = top_list(rule);
2906 set_node(rule, list);
2907 });
2908 alt.g = "expr,space,list,top".into();
2909 close.push(alt);
2910
2911 let mut alt = on(&[TIN_CA]);
2913 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
2914 rule.lte("pk", 0)
2915 }));
2916 alt.n = counters(&[("expr", 0)]);
2917 alt.b = 1;
2918 alt.h_match = Some(Arc::new(|matched, rule, context, _next| {
2919 implicit_list(matched, rule, context)
2920 }));
2921 alt.g = "expr,list,val,imp,comma".into();
2922 close.push(alt);
2923
2924 let mut alt = always();
2935 let suffix_tins = grammar.tin_suffix.clone();
2936 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, context: &mut Context| {
2937 rule.lte("pk", 0)
2938 && rule.lte("expr_suffix", 0)
2939 && !context
2940 .t0()
2941 .is_some_and(|token| suffix_tins.contains(&token.tin))
2942 }));
2943 alt.n = counters(&[("expr", 0)]);
2944 alt.h_match = Some(Arc::new(|matched, rule, context, _next| {
2945 implicit_list(matched, rule, context)
2946 }));
2947 alt.g = "expr,list,val,imp,space".into();
2948 close.push(alt);
2949
2950 let mut alt = always();
2952 alt.n = counters(&[("expr", 0)]);
2953 alt.g = "expr,expr-end".into();
2954 close.push(alt);
2955
2956 prepend_close_all(spec, close);
2957
2958 spec.add_ac(|rule: &mut Rule, _context: &mut Context| {
2965 if is_op(&node_of(rule)) {
2966 let root = expression_root(rule);
2967 set_node(rule, root);
2968 }
2969 });
2970
2971 if let Some(evaluate) = grammar.evaluate.clone() {
2973 spec.add_ac(move |rule: &mut Rule, context: &mut Context| {
2974 if 0 != counter(rule, "expr") {
2975 return;
2976 }
2977 let Some(parent) = rule.parent_rule.clone() else {
2978 return;
2979 };
2980 let parent_node = parent.node.borrow().clone();
2981
2982 if let Value::Array(members) = &parent_node {
2995 let mut site = EvalSite::new(Some(parent.clone()), context);
2996 let reduced: Vec<Value> = members
2997 .iter()
2998 .map(|member| evaluation(&mut site.reborrow(), member, &evaluate))
2999 .collect();
3000 let reduced = Value::array(reduced);
3001 *parent.node.borrow_mut() = reduced.clone();
3002 publish(rule, reduced);
3007 return;
3008 }
3009
3010 let out = {
3012 let mut site = EvalSite::new(Some(parent.clone()), context);
3013 evaluation(&mut site, &parent_node, &evaluate)
3014 };
3015 *parent.node.borrow_mut() = out.clone();
3016
3017 publish(rule, out);
3024 });
3025 }
3026 });
3027}
3028
3029fn paren_depth(name: &str) -> String {
3034 format!("expr_paren_depth_{name}")
3035}
3036
3037fn install_paren(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
3038 let grammar = grammar.clone();
3039 parser.define_rule("paren", move |spec| {
3040 spec.add_bo(|rule: &mut Rule, _context: &mut Context| {
3042 let counters = rule.n_mut();
3043 counters.insert("dmap".into(), 0);
3044 counters.insert("dlist".into(), 0);
3045 counters.insert("pk".into(), 0);
3046 });
3047
3048 let mut open: Vec<AltSpec> = Vec::new();
3049
3050 let mut alt = on2(&grammar.tin_open, &grammar.tin_close);
3052 alt.b = 1;
3053 alt.g = "expr,expr-paren,empty".into();
3054 let condition = grammar.clone();
3055 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, _context: &mut Context| {
3056 let open = rule
3057 .o0()
3058 .and_then(|token| condition.paren_open.get(&token.tin));
3059 let close = rule
3060 .o1()
3061 .and_then(|token| condition.paren_close.get(&token.tin));
3062 match (open, close) {
3063 (Some(open), Some(close)) => open.name == close.name,
3064 _ => false,
3065 }
3066 }));
3067 let ops = grammar.clone();
3068 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
3069 open_paren(&ops, rule);
3070 });
3071 open.push(alt);
3072
3073 let mut alt = on(&grammar.tin_open);
3075 alt.p = Some("val".into());
3076 alt.n = counters(&[
3077 ("expr_paren", 1),
3078 ("expr", 0),
3079 ("expr_prefix", 0),
3080 ("expr_suffix", 0),
3081 ]);
3082 alt.g = "expr,expr-paren,open".into();
3083 let ops = grammar.clone();
3084 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
3085 open_paren(&ops, rule);
3086 });
3087 open.push(alt);
3088
3089 prepend_open_all(spec, open);
3090
3091 let mut alt = on(&grammar.tin_close);
3092 let condition = grammar.clone();
3093 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, _context: &mut Context| {
3094 let Some(pdef) = rule
3095 .c0()
3096 .and_then(|token| condition.paren_close.get(&token.tin))
3097 .cloned()
3098 else {
3099 return false;
3100 };
3101 0 != counter(rule, &paren_depth(&pdef.name))
3102 }));
3103 let ops = grammar.clone();
3104 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
3105 close_paren(&ops, rule);
3106 });
3107 alt.g = "expr,expr-paren,close".into();
3108 prepend_close_all(spec, vec![alt]);
3109
3110 spec.add_ac(|rule: &mut Rule, _context: &mut Context| {
3111 let node = node_of(rule);
3112 let parent = rule.parent_rule.clone();
3113 write_linked_node(parent.as_ref(), node.clone());
3114 let grandparent = parent.and_then(|parent| parent.parent_rule.clone());
3115 write_linked_node(grandparent.as_ref(), node);
3116 });
3117 });
3118}
3119
3120fn open_paren(grammar: &Grammar, rule: &mut Rule) {
3121 let Some(op) = Grammar::op_use(&grammar.paren_open, rule.o0()) else {
3122 return;
3123 };
3124 let depth = paren_depth(&op.op.name);
3125 rule.u_mut().insert(depth.clone(), Value::Number(1.0));
3126 rule.n_mut().insert(depth, 1);
3127 set_node(rule, Value::Undefined);
3128}
3129
3130fn close_paren(grammar: &Grammar, rule: &mut Rule) {
3131 let child = rule.child_node.clone();
3132 let mut node = node_of(rule);
3133 if node.is_undefined() {
3146 node = child;
3147 }
3148
3149 let Some(op) = Grammar::op_use(&grammar.paren_close, rule.c0()) else {
3150 set_node(rule, node);
3151 return;
3152 };
3153 let depth = paren_depth(&op.op.name);
3154
3155 if local_number(rule, &depth) == i64::from(counter(rule, &depth)) {
3157 let mut terms: Vec<Value> = Vec::new();
3158
3159 let grandparent = rule
3160 .parent_rule
3161 .as_ref()
3162 .and_then(|parent| parent.parent_rule.clone());
3163 if let Some(grandparent) = &grandparent {
3164 let preval = grandparent.node.borrow().clone();
3165 if matches!(grandparent.u.get("paren_preval"), Some(Value::Bool(true)))
3166 && !preval.is_undefined()
3167 {
3168 terms.push(preval);
3169 }
3170 }
3171
3172 if !node.is_undefined() {
3173 terms.push(node);
3174 }
3175
3176 set_node(rule, op.node(terms));
3177 } else {
3178 set_node(rule, node);
3179 }
3180}
3181
3182fn install_ternary(parser: &mut Tabnas, grammar: &Arc<Grammar>) {
3187 let grammar = grammar.clone();
3188 parser.define_rule("ternary", move |spec| {
3189 let mut open: Vec<AltSpec> = Vec::new();
3190
3191 let mut alt = on(&grammar.tin_tern0);
3192 alt.p = Some("val".into());
3193 alt.n = counters(&[
3194 ("expr_ternary", 1),
3195 ("expr", 0),
3196 ("expr_prefix", 0),
3197 ("expr_suffix", 0),
3198 ]);
3199 alt.u = locals(&[("expr_ternary_step", Value::Number(1.0))]);
3200 alt.g = "expr,expr-ternary,open".into();
3201 let ops = grammar.clone();
3202 alt.add_action(move |rule: &mut Rule, _context: &mut Context| {
3203 let Some(op) = Grammar::op_use(&ops.ternary, rule.o0()) else {
3204 return;
3205 };
3206 rule.u_mut().insert(
3207 "expr_ternary_name".into(),
3208 Value::String(op.op.name.clone()),
3209 );
3210
3211 let previous = linked_node(rule.prev_rule.as_ref());
3212 let node = if is_op(&previous) {
3213 let duplicate = dup_node(&previous);
3214 update_expr_node(
3215 &previous,
3216 Some(op.op.clone()),
3217 op.token.clone(),
3218 vec![duplicate],
3219 );
3220 previous
3221 } else {
3222 let node = op.node(vec![previous]);
3223 write_linked_node(rule.prev_rule.as_ref(), node.clone());
3224 node
3225 };
3226 set_node(rule, node);
3227
3228 let paren = if 0 != counter(rule, "expr_paren") {
3229 i64::from(counter(rule, "expr_paren"))
3230 } else {
3231 rule.prev_rule
3232 .as_ref()
3233 .map_or(0, |prev| snapshot_number(prev, "expr_ternary_paren"))
3234 };
3235 rule.u_mut()
3236 .insert("expr_ternary_paren".into(), Value::Number(paren as f64));
3237 rule.n_mut().insert("expr_paren".into(), 0);
3238 });
3239 open.push(alt);
3240
3241 let mut alt = always();
3242 alt.p = Some("val".into());
3243 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
3244 rule.prev_rule
3245 .as_ref()
3246 .is_some_and(|prev| 2 == snapshot_number(prev, "expr_ternary_step"))
3247 }));
3248 alt.add_action(|rule: &mut Rule, _context: &mut Context| {
3249 let (step, paren) = rule.prev_rule.as_ref().map_or((0, 0), |prev| {
3250 (
3251 snapshot_number(prev, "expr_ternary_step"),
3252 snapshot_number(prev, "expr_ternary_paren"),
3253 )
3254 });
3255 set_local_number(rule, "expr_ternary_step", step);
3256 set_local_number(rule, "expr_ternary_paren", paren);
3257 rule.n_mut().insert("expr_paren".into(), paren as i32);
3258 });
3259 alt.g = "expr,expr-ternary,step".into();
3260 open.push(alt);
3261
3262 prepend_open_all(spec, open);
3263
3264 let mut close: Vec<AltSpec> = Vec::new();
3265
3266 let mut alt = on(&grammar.tin_tern1);
3267 let condition = grammar.clone();
3268 alt.c_fn = Some(Arc::new(move |rule: &mut Rule, _context: &mut Context| {
3269 if 1 != local_number(rule, "expr_ternary_step") {
3270 return false;
3271 }
3272 let Some(op) = rule
3273 .c0()
3274 .and_then(|token| condition.ternary.get(&token.tin))
3275 .cloned()
3276 else {
3277 return false;
3278 };
3279 matches!(rule.u.get("expr_ternary_name"), Some(Value::String(name)) if name == &op.name)
3280 }));
3281 alt.r = Some("ternary".into());
3282 alt.add_action(|rule: &mut Rule, _context: &mut Context| {
3283 let step = local_number(rule, "expr_ternary_step");
3284 set_local_number(rule, "expr_ternary_step", step + 1);
3285 let node = node_of(rule);
3286 push_term(&node, rule.child_node.clone());
3287 });
3288 alt.g = "expr,expr-ternary,step".into();
3289 close.push(alt);
3290
3291 let mut tins = vec![TIN_CA];
3295 tins.extend(grammar.tin_close.iter().copied());
3296 let mut alt = on(&tins);
3297 alt.c_fn = Some(Arc::new(implicit_ternary_cond));
3298 let closers = grammar.tin_close.clone();
3299 alt.b_fn = Some(Arc::new(move |_rule: &mut Rule, context: &mut Context| {
3300 usize::from(next_is_close(context, &closers))
3301 }));
3302 let closers = grammar.tin_close.clone();
3303 alt.r_fn = Some(Arc::new(move |rule: &mut Rule, context: &mut Context| {
3304 let to_elem = !next_is_close(context, &closers)
3305 && (0 == rule.d
3306 || (rule
3307 .prev_rule
3308 .as_ref()
3309 .is_some_and(|prev| 0 != snapshot_number(prev, "expr_ternary_paren"))
3310 && 0 == node_length(&linked_node(rule.parent_rule.as_ref()))));
3311 to_elem.then(|| "elem".to_string())
3312 }));
3313 alt.add_action_with_match(|rule: &mut Rule, _context: &mut Context, matched| {
3314 implicit_ternary_action(rule, matched);
3315 None
3316 });
3317 alt.g = "expr,expr-ternary,list,val,imp,comma".into();
3318 close.push(alt);
3319
3320 let mut alt = always();
3323 alt.c_fn = Some(Arc::new(implicit_ternary_cond));
3324 let closers = grammar.tin_close.clone();
3325 alt.r_fn = Some(Arc::new(move |rule: &mut Rule, context: &mut Context| {
3326 let ended = context.t0().is_some_and(|token| TIN_ZZ == token.tin);
3327 let to_elem = (0 == rule.d
3328 || !next_is_close(context, &closers)
3329 || rule
3330 .prev_rule
3331 .as_ref()
3332 .is_some_and(|prev| 0 != snapshot_number(prev, "expr_ternary_paren")))
3333 && 0 == node_length(&linked_node(rule.parent_rule.as_ref()))
3334 && !ended;
3335 to_elem.then(|| "elem".to_string())
3336 }));
3337 alt.add_action_with_match(|rule: &mut Rule, _context: &mut Context, matched| {
3338 implicit_ternary_action(rule, matched);
3339 None
3340 });
3341 alt.g = "expr,expr-ternary,list,val,imp,space".into();
3342 close.push(alt);
3343
3344 let mut alt = always();
3346 alt.c_fn = Some(Arc::new(|rule: &mut Rule, _context: &mut Context| {
3347 0 < rule.d && 2 == local_number(rule, "expr_ternary_step")
3348 }));
3349 alt.add_action(|rule: &mut Rule, _context: &mut Context| {
3350 let node = node_of(rule);
3351 push_term(&node, rule.child_node.clone());
3352 });
3353 alt.g = "expr,expr-ternary,close".into();
3354 close.push(alt);
3355
3356 prepend_close_all(spec, close);
3357
3358 if let Some(evaluate) = grammar.evaluate.clone() {
3367 spec.add_ac(move |rule: &mut Rule, context: &mut Context| {
3368 if rule
3369 .next_rule_name
3370 .as_ref()
3371 .is_some_and(|name| "ternary" == name.as_ref())
3372 {
3373 return;
3374 }
3375 let node = node_of(rule);
3376 if !is_op(&node) {
3377 return;
3378 }
3379 if node_length(&node) < 4 {
3382 return;
3383 }
3384 let out = {
3385 let site_rule = rule.snapshot();
3389 let mut site = EvalSite::new(Some(site_rule), context);
3390 evaluation(&mut site, &node, &evaluate)
3391 };
3392 publish(rule, out.clone());
3393 let mut cursor = rule.prev_rule.clone();
3394 while let Some(current) = cursor {
3395 *current.node.borrow_mut() = out.clone();
3396 cursor = current.prev_rule.clone();
3397 }
3398 write_linked_node(rule.parent_rule.as_ref(), out);
3399 });
3400 }
3401 });
3402}
3403
3404fn snapshot_number(snapshot: &RuleSnapshot, name: &str) -> i64 {
3405 match snapshot.u.get(name) {
3406 Some(Value::Number(number)) => *number as i64,
3407 _ => 0,
3408 }
3409}
3410
3411fn next_is_close(context: &mut Context, closers: &[Tin]) -> bool {
3412 context
3413 .t0()
3414 .is_some_and(|token| closers.contains(&token.tin))
3415}
3416
3417fn implicit_ternary_cond(rule: &mut Rule, _context: &mut Context) -> bool {
3418 (0 == rule.d || 1 <= counter(rule, "expr_paren"))
3419 && 0 == counter(rule, "pk")
3420 && 2 == local_number(rule, "expr_ternary_step")
3421}
3422
3423fn implicit_ternary_action(rule: &mut Rule, matched: &AltMatch) {
3424 let paren = rule
3425 .prev_rule
3426 .as_ref()
3427 .map_or(0, |prev| snapshot_number(prev, "expr_ternary_paren"));
3428 rule.n_mut().insert("expr_paren".into(), paren as i32);
3429
3430 let node = node_of(rule);
3431 push_term(&node, rule.child_node.clone());
3432
3433 if matched.r.as_deref() != Some("elem") {
3434 return;
3435 }
3436
3437 let list = Value::array(vec![node]);
3444 publish(rule, list.clone());
3445 if 1 <= counter(rule, "expr_paren") {
3446 let mut cursor = rule.parent_rule.clone();
3447 while let Some(current) = cursor {
3448 if "paren" == current.name.as_ref() {
3449 *current.node.borrow_mut() = list;
3450 break;
3451 }
3452 cursor = current.parent_rule.clone();
3453 }
3454 }
3455}
3456
3457pub fn plugin() -> Plugin {
3481 Plugin::new(PLUGIN_NAME, |parser: &mut Tabnas, options: &Value| {
3482 expr(parser, &ExprOptions::from_value(options))
3483 })
3484 .with_defaults(defaults())
3485}
3486
3487pub fn plugin_with(options: ExprOptions) -> Plugin {
3494 Plugin::new(PLUGIN_NAME, move |parser: &mut Tabnas, _options: &Value| {
3495 expr(parser, &options)
3496 })
3497}
3498
3499pub fn apply(parser: &mut Tabnas, options: ExprOptions) -> Result<(), PluginError> {
3502 parser.use_plugin(plugin_with(options), None).map(|_| ())
3503}
3504
3505pub fn make() -> Tabnas {
3518 make_with(ExprOptions::new())
3519}
3520
3521pub fn make_with(options: ExprOptions) -> Tabnas {
3523 let mut parser = tabnas_jsonic::make();
3524 parser
3525 .use_plugin(plugin_with(options), None)
3526 .expect("the expression grammar installs on the jsonic base");
3527 parser
3528}
3529
3530static DEFAULT_PARSER: OnceLock<Tabnas> = OnceLock::new();
3537
3538pub fn parse(src: &str) -> Result<Value, TabnasError> {
3549 parse_with(DEFAULT_PARSER.get_or_init(make), src)
3550}
3551
3552pub fn parse_with(parser: &Tabnas, src: &str) -> Result<Value, TabnasError> {
3559 let _guard = ArenaGuard::enter();
3560 let value = parser.parse(src)?;
3561 Ok(realize(&value))
3562}
3563
3564pub fn parse_scope<R>(
3601 parser: &Tabnas,
3602 src: &str,
3603 use_value: impl FnOnce(Value) -> R,
3604) -> Result<R, TabnasError> {
3605 let _guard = ArenaGuard::enter();
3606 let value = parser.parse(src)?;
3607 Ok(use_value(value))
3608}
3609
3610pub fn parse_simplified(parser: &Tabnas, src: &str) -> Result<Value, TabnasError> {
3613 let _guard = ArenaGuard::enter();
3614 let value = parser.parse(src)?;
3615 Ok(simplify(&value))
3616}