1use crate::value::unwrap_arc;
4use crate::value::Value;
5use crate::{Context, Rule};
6use std::collections::HashMap;
7use std::fmt;
8use std::sync::Arc;
9
10type TokenValCallback = dyn Fn(&mut Rule, &mut Context) -> Value + Send + Sync;
11
12pub type Tin = i32;
14
15pub const TIN_BD: Tin = 1; pub const TIN_ZZ: Tin = 2; pub const TIN_UK: Tin = 3; pub const TIN_AA: Tin = 4; pub const TIN_SP: Tin = 5; pub const TIN_LN: Tin = 6; pub const TIN_CM: Tin = 7; pub const TIN_NR: Tin = 8; pub const TIN_ST: Tin = 9; pub const TIN_TX: Tin = 10; pub const TIN_VL: Tin = 11; pub const TIN_OB: Tin = 12; pub const TIN_CB: Tin = 13; pub const TIN_OS: Tin = 14; pub const TIN_CS: Tin = 15; pub const TIN_CL: Tin = 16; pub const TIN_CA: Tin = 17; pub const TIN_MAX: Tin = 18;
33
34pub fn tin_name(tin: Tin) -> &'static str {
35 match tin {
36 TIN_BD => "#BD",
37 TIN_ZZ => "#ZZ",
38 TIN_UK => "#UK",
39 TIN_AA => "#AA",
40 TIN_SP => "#SP",
41 TIN_LN => "#LN",
42 TIN_CM => "#CM",
43 TIN_NR => "#NR",
44 TIN_ST => "#ST",
45 TIN_TX => "#TX",
46 TIN_VL => "#VL",
47 TIN_OB => "#OB",
48 TIN_CB => "#CB",
49 TIN_OS => "#OS",
50 TIN_CS => "#CS",
51 TIN_CL => "#CL",
52 TIN_CA => "#CA",
53 _ => "#UNKNOWN",
54 }
55}
56
57pub fn name_to_tin(name: &str) -> Option<Tin> {
58 match name {
59 "#BD" | "BD" => Some(TIN_BD),
60 "#ZZ" | "ZZ" => Some(TIN_ZZ),
61 "#UK" | "UK" => Some(TIN_UK),
62 "#AA" | "AA" => Some(TIN_AA),
63 "#SP" | "SP" => Some(TIN_SP),
64 "#LN" | "LN" => Some(TIN_LN),
65 "#CM" | "CM" => Some(TIN_CM),
66 "#NR" | "NR" => Some(TIN_NR),
67 "#ST" | "ST" => Some(TIN_ST),
68 "#TX" | "TX" => Some(TIN_TX),
69 "#VL" | "VL" => Some(TIN_VL),
70 "#OB" | "OB" => Some(TIN_OB),
71 "#CB" | "CB" => Some(TIN_CB),
72 "#OS" | "OS" => Some(TIN_OS),
73 "#CS" | "CS" => Some(TIN_CS),
74 "#CL" | "CL" => Some(TIN_CL),
75 "#CA" | "CA" => Some(TIN_CA),
76 _ => None,
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct Site {
99 pub si: usize, pub pos: usize, pub ri: usize, pub ci: usize, }
104
105impl Default for Site {
106 fn default() -> Self {
107 Site {
108 si: 0,
109 pos: 0,
110 ri: 1,
111 ci: 1,
112 }
113 }
114}
115
116impl fmt::Display for Site {
117 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(formatter, "{},{},{}", self.si, self.ri, self.ci)
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
124pub struct Point {
125 pub len: usize, pub site: Site, }
128
129impl fmt::Display for Point {
130 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write!(
132 formatter,
133 "Point[{}/{},{},{}]",
134 self.site.si, self.len, self.site.ri, self.site.ci
135 )
136 }
137}
138
139#[derive(Clone)]
143pub struct TokenValFunc {
144 callback: Arc<TokenValCallback>,
145}
146
147impl TokenValFunc {
148 pub fn new(
149 callback: impl Fn(&mut Rule, &mut Context) -> Value + Send + Sync + 'static,
150 ) -> Self {
151 Self {
152 callback: Arc::new(callback),
153 }
154 }
155
156 pub fn call(&self, rule: &mut Rule, context: &mut Context) -> Value {
157 (self.callback)(rule, context)
158 }
159
160 pub(crate) fn same_callback(&self, other: &Self) -> bool {
161 Arc::ptr_eq(&self.callback, &other.callback)
162 }
163}
164
165impl fmt::Debug for TokenValFunc {
166 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
167 formatter.write_str("TokenValFunc(<function>)")
168 }
169}
170
171impl PartialEq for TokenValFunc {
172 fn eq(&self, other: &Self) -> bool {
173 self.same_callback(other)
174 }
175}
176
177impl Eq for TokenValFunc {}
178
179#[derive(Clone, Default)]
188pub struct TokenText(crate::text::InlineText);
189
190impl TokenText {
191 pub fn as_str(&self) -> &str {
192 self.0.as_str()
193 }
194
195 pub fn is_empty(&self) -> bool {
196 self.as_str().is_empty()
197 }
198
199 fn build(text: &str) -> Self {
200 TokenText(crate::text::InlineText::new(text))
201 }
202}
203
204impl Eq for TokenText {}
205
206impl PartialEq for TokenText {
207 fn eq(&self, other: &Self) -> bool {
208 self.as_str() == other.as_str()
209 }
210}
211
212impl std::hash::Hash for TokenText {
213 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
214 self.as_str().hash(state)
215 }
216}
217
218impl PartialOrd for TokenText {
219 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
220 Some(self.cmp(other))
221 }
222}
223
224impl Ord for TokenText {
225 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
226 self.as_str().cmp(other.as_str())
227 }
228}
229
230impl std::ops::Deref for TokenText {
231 type Target = str;
232
233 fn deref(&self) -> &str {
234 self.as_str()
235 }
236}
237
238impl AsRef<str> for TokenText {
239 fn as_ref(&self) -> &str {
240 self.as_str()
241 }
242}
243
244impl std::borrow::Borrow<str> for TokenText {
245 fn borrow(&self) -> &str {
246 self.as_str()
247 }
248}
249
250impl fmt::Display for TokenText {
251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 f.write_str(self.as_str())
253 }
254}
255
256impl fmt::Debug for TokenText {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 fmt::Debug::fmt(self.as_str(), f)
261 }
262}
263
264impl PartialEq<str> for TokenText {
265 fn eq(&self, other: &str) -> bool {
266 self.as_str() == other
267 }
268}
269
270impl PartialEq<&str> for TokenText {
271 fn eq(&self, other: &&str) -> bool {
272 self.as_str() == *other
273 }
274}
275
276impl PartialEq<String> for TokenText {
277 fn eq(&self, other: &String) -> bool {
278 self.as_str() == other.as_str()
279 }
280}
281
282impl PartialEq<TokenText> for str {
283 fn eq(&self, other: &TokenText) -> bool {
284 self == other.as_str()
285 }
286}
287
288impl PartialEq<TokenText> for &str {
289 fn eq(&self, other: &TokenText) -> bool {
290 *self == other.as_str()
291 }
292}
293
294impl PartialEq<TokenText> for String {
295 fn eq(&self, other: &TokenText) -> bool {
296 self.as_str() == other.as_str()
297 }
298}
299
300impl From<&str> for TokenText {
301 fn from(text: &str) -> Self {
302 TokenText::build(text)
303 }
304}
305
306impl From<String> for TokenText {
307 fn from(text: String) -> Self {
308 TokenText::build(text.as_str())
309 }
310}
311
312impl From<&String> for TokenText {
313 fn from(text: &String) -> Self {
314 TokenText::build(text.as_str())
315 }
316}
317
318impl From<Arc<str>> for TokenText {
319 fn from(text: Arc<str>) -> Self {
320 TokenText(crate::text::InlineText::shared(text))
321 }
322}
323
324impl From<TokenText> for String {
325 fn from(text: TokenText) -> Self {
326 text.as_str().to_string()
327 }
328}
329
330#[derive(Clone, Default)]
345pub struct TokenCode(Option<Box<TokenText>>);
346
347impl TokenCode {
348 pub fn as_str(&self) -> &str {
349 match &self.0 {
350 Some(text) => text.as_str(),
351 None => "",
352 }
353 }
354
355 pub fn is_empty(&self) -> bool {
356 self.0.is_none()
357 }
358
359 fn build(text: &str) -> Self {
360 TokenCode((!text.is_empty()).then(|| Box::new(TokenText::from(text))))
361 }
362}
363
364impl Eq for TokenCode {}
365
366impl PartialEq for TokenCode {
367 fn eq(&self, other: &Self) -> bool {
368 self.as_str() == other.as_str()
369 }
370}
371
372impl std::hash::Hash for TokenCode {
373 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
374 self.as_str().hash(state)
375 }
376}
377
378impl PartialOrd for TokenCode {
379 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
380 Some(self.cmp(other))
381 }
382}
383
384impl Ord for TokenCode {
385 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
386 self.as_str().cmp(other.as_str())
387 }
388}
389
390impl std::ops::Deref for TokenCode {
391 type Target = str;
392
393 fn deref(&self) -> &str {
394 self.as_str()
395 }
396}
397
398impl AsRef<str> for TokenCode {
399 fn as_ref(&self) -> &str {
400 self.as_str()
401 }
402}
403
404impl std::borrow::Borrow<str> for TokenCode {
405 fn borrow(&self) -> &str {
406 self.as_str()
407 }
408}
409
410impl fmt::Display for TokenCode {
411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
412 f.write_str(self.as_str())
413 }
414}
415
416impl fmt::Debug for TokenCode {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 fmt::Debug::fmt(self.as_str(), f)
420 }
421}
422
423impl PartialEq<str> for TokenCode {
424 fn eq(&self, other: &str) -> bool {
425 self.as_str() == other
426 }
427}
428
429impl PartialEq<&str> for TokenCode {
430 fn eq(&self, other: &&str) -> bool {
431 self.as_str() == *other
432 }
433}
434
435impl PartialEq<String> for TokenCode {
436 fn eq(&self, other: &String) -> bool {
437 self.as_str() == other.as_str()
438 }
439}
440
441impl PartialEq<TokenCode> for str {
442 fn eq(&self, other: &TokenCode) -> bool {
443 self == other.as_str()
444 }
445}
446
447impl PartialEq<TokenCode> for &str {
448 fn eq(&self, other: &TokenCode) -> bool {
449 *self == other.as_str()
450 }
451}
452
453impl PartialEq<TokenCode> for String {
454 fn eq(&self, other: &TokenCode) -> bool {
455 self.as_str() == other.as_str()
456 }
457}
458
459impl From<&str> for TokenCode {
460 fn from(text: &str) -> Self {
461 TokenCode::build(text)
462 }
463}
464
465impl From<String> for TokenCode {
466 fn from(text: String) -> Self {
467 TokenCode::build(text.as_str())
468 }
469}
470
471impl From<&String> for TokenCode {
472 fn from(text: &String) -> Self {
473 TokenCode::build(text.as_str())
474 }
475}
476
477impl From<TokenText> for TokenCode {
478 fn from(text: TokenText) -> Self {
479 TokenCode((!text.is_empty()).then(|| Box::new(text)))
480 }
481}
482
483impl From<TokenCode> for String {
484 fn from(text: TokenCode) -> Self {
485 text.as_str().to_string()
486 }
487}
488
489#[derive(Debug, Clone, PartialEq)]
491pub struct Token {
492 pub name: TokenText,
493 pub tin: Tin,
494 pub val: Value,
495 pub src: TokenText,
496 pub len: usize,
498 pub site: Site,
500 pub err: TokenCode,
501 pub why: TokenCode,
502 pub use_data: Option<Box<HashMap<String, Value>>>,
510 pub ignored: Option<Box<Token>>,
513 pub val_fn: Option<TokenValFunc>,
516}
517
518impl Default for Token {
519 fn default() -> Self {
520 Token {
521 name: TokenText::default(),
522 tin: -1,
523 val: Value::Undefined,
524 src: TokenText::default(),
525 len: 0,
526 site: Site::default(),
527 err: TokenCode::default(),
528 why: TokenCode::default(),
529 use_data: None,
530 ignored: None,
531 val_fn: None,
532 }
533 }
534}
535
536impl Token {
537 pub fn new(
538 name: impl AsRef<str>,
539 tin: Tin,
540 val: Value,
541 src: impl Into<TokenText>,
542 pnt: Point,
543 ) -> Self {
544 let src: TokenText = src.into();
545 let len = src.len();
546 Token {
547 name: TokenText::from(name.as_ref()),
548 tin,
549 val,
550 src,
551 len,
552 site: pnt.site,
553 err: TokenCode::default(),
554 why: TokenCode::default(),
555 use_data: None,
556 ignored: None,
557 val_fn: None,
558 }
559 }
560
561 pub fn use_data(&self) -> &HashMap<String, Value> {
563 static EMPTY: std::sync::OnceLock<HashMap<String, Value>> = std::sync::OnceLock::new();
564 match &self.use_data {
565 Some(details) => details,
566 None => EMPTY.get_or_init(HashMap::new),
567 }
568 }
569
570 pub fn use_data_mut(&mut self) -> &mut HashMap<String, Value> {
572 self.use_data.get_or_insert_with(Box::default)
573 }
574
575 pub fn no_token() -> Self {
576 Token {
577 name: TokenText::default(),
580 tin: -1,
581 val: Value::Undefined,
582 src: TokenText::default(),
583 len: 0,
584 site: Site::default(),
585 err: TokenCode::default(),
586 why: TokenCode::default(),
587 use_data: None,
588 ignored: None,
589 val_fn: None,
590 }
591 }
592
593 pub fn is_no_token(&self) -> bool {
594 self.tin == -1
595 }
596
597 pub fn bad(&mut self, err: &str) -> &mut Self {
598 self.err = TokenCode::from(err);
599 self
600 }
601
602 pub fn bad_with_details(
606 &mut self,
607 err: &str,
608 details: impl IntoIterator<Item = (String, Value)>,
609 ) -> &mut Self {
610 self.err = TokenCode::from(err);
611 for (key, value) in details {
612 let details = self.use_data_mut();
613 let previous = details.remove(&key).unwrap_or(Value::Undefined);
614 details.insert(key, merge_detail(previous, value));
615 }
616 self
617 }
618
619 pub fn with_val_func(mut self, callback: TokenValFunc) -> Self {
621 self.val_fn = Some(callback);
622 self
623 }
624
625 pub fn with_lazy_value(
627 self,
628 callback: impl Fn(&mut Rule, &mut Context) -> Value + Send + Sync + 'static,
629 ) -> Self {
630 self.with_val_func(TokenValFunc::new(callback))
631 }
632
633 pub fn resolve_val(&self, rule: &mut Rule, context: &mut Context) -> Value {
635 self.val_fn
636 .as_ref()
637 .map_or_else(|| self.val.clone(), |callback| callback.call(rule, context))
638 }
639}
640
641impl fmt::Display for Token {
642 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
643 write!(
644 formatter,
645 "Token[{}={} {}",
646 self.name,
647 self.tin,
648 snip(&self.src, 5)
649 )?;
650 if !self.val.is_undefined() && !matches!(self.name.as_str(), "#ST" | "#TX") {
651 write!(formatter, "={}", snip(&value_text(&self.val), 5))?;
652 }
653 write!(formatter, " {}", self.site)?;
654 if !self.use_data().is_empty() {
655 let mut entries = self.use_data().iter().collect::<Vec<_>>();
656 entries.sort_by_key(|(key, _)| *key);
657 let details = entries
658 .into_iter()
659 .map(|(key, value)| format!("{key}:{}", detail_json(value)))
660 .collect::<Vec<_>>()
661 .join(",");
662 write!(
663 formatter,
664 " {}",
665 snip(&format!("{{{details}}}").replace('"', ""), 22)
666 )?;
667 }
668 if !self.err.is_empty() {
669 write!(formatter, " {}", self.err)?;
670 }
671 if !self.why.is_empty() {
672 write!(formatter, " {}", snip(&self.why, 22))?;
673 }
674 formatter.write_str("]")
675 }
676}
677
678fn merge_detail(base: Value, overlay: Value) -> Value {
679 match (base, overlay) {
680 (base, Value::Undefined) => base,
681 (Value::Object(base), Value::Object(overlay)) => {
682 let mut base = unwrap_arc(base);
683 for (key, value) in unwrap_arc(overlay) {
684 let previous = base.shift_remove(&key).unwrap_or(Value::Undefined);
685 base.insert(key, merge_detail(previous, value));
686 }
687 Value::object(base)
688 }
689 (Value::Array(base), Value::Array(overlay)) => {
690 let mut base = unwrap_arc(base);
691 let overlay = unwrap_arc(overlay);
692 if base.len() < overlay.len() {
693 base.resize(overlay.len(), Value::Undefined);
694 }
695 for (index, value) in overlay.into_iter().enumerate() {
696 let previous = std::mem::replace(&mut base[index], Value::Undefined);
697 base[index] = merge_detail(previous, value);
698 }
699 Value::array(base)
700 }
701 (_, overlay) => overlay,
702 }
703}
704
705fn value_text(value: &Value) -> String {
706 match value {
707 Value::Undefined => String::new(),
708 Value::Null => "null".into(),
709 Value::Bool(value) => value.to_string(),
710 Value::Number(value) => Value::Number(*value).to_string(),
711 Value::String(value) | Value::Text(crate::Text { string: value, .. }) => value.clone(),
712 Value::Array(values) => values.iter().map(value_text).collect::<Vec<_>>().join(","),
713 Value::ListRef(list) => list
714 .value
715 .iter()
716 .map(value_text)
717 .collect::<Vec<_>>()
718 .join(","),
719 Value::Object(_) | Value::MapRef(_) => "[object Object]".into(),
720 }
721}
722
723fn detail_json(value: &Value) -> String {
724 match value {
725 Value::Undefined | Value::Null => "null".into(),
726 Value::Bool(value) => value.to_string(),
727 Value::Number(value) => Value::Number(*value).to_string(),
728 Value::String(value) | Value::Text(crate::Text { string: value, .. }) => {
729 serde_json::to_string(value).unwrap_or_default()
730 }
731 Value::Array(values) => format!(
732 "[{}]",
733 values.iter().map(detail_json).collect::<Vec<_>>().join(",")
734 ),
735 Value::Object(values) => format!(
736 "{{{}}}",
737 values
738 .iter()
739 .filter(|(_, value)| !value.is_undefined())
742 .map(|(key, value)| format!(
743 "{}:{}",
744 serde_json::to_string(key).unwrap_or_default(),
745 detail_json(value)
746 ))
747 .collect::<Vec<_>>()
748 .join(",")
749 ),
750 Value::ListRef(list) => detail_json(&Value::array(list.value.clone())),
751 Value::MapRef(map) => detail_json(&Value::object(map.value.clone())),
752 }
753}
754
755fn snip(value: &str, max_len: usize) -> String {
756 value
757 .chars()
758 .take(max_len)
759 .map(|character| match character {
760 '\r' | '\n' | '\t' => '.',
761 character => character,
762 })
763 .collect()
764}