Skip to main content

decl_lang/
parse.rs

1//! CST -> AST lowering over the compiled tree-sitter grammar (parse.ts).
2use crate::ast::*;
3use crate::semantics::Value;
4use num_bigint::BigInt;
5use num_traits::Num;
6use std::rc::Rc;
7use tree_sitter::{Language, Node, Parser};
8use tree_sitter_language::LanguageFn;
9
10extern "C" {
11    fn tree_sitter_decl() -> *const ();
12}
13pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_decl) };
14
15#[derive(Clone)]
16pub struct ParseResult {
17    pub decls: Vec<Decl>,
18    pub errors: Vec<(usize, usize)>,
19}
20
21// the same text parses to the same result: the session and the language
22// server re-load the unchanged modules of a universe on every question,
23// and the AST is never mutated after lowering (a small bounded cache; a
24// clone shares the expression nodes, whose addresses are their identity)
25thread_local! {
26    static PARSE_CACHE: std::cell::RefCell<Vec<(String, ParseResult)>> = const { std::cell::RefCell::new(Vec::new()) };
27}
28
29struct Lower<'a> {
30    src: &'a [u8],
31}
32
33pub fn parse_source(src: &str) -> ParseResult {
34    if let Some(hit) = PARSE_CACHE.with(|c| {
35        c.borrow()
36            .iter()
37            .find(|(k, _)| k == src)
38            .map(|(_, r)| r.clone())
39    }) {
40        return hit;
41    }
42    let r = parse_source_uncached(src);
43    PARSE_CACHE.with(|c| {
44        let mut c = c.borrow_mut();
45        if c.len() >= 64 {
46            c.remove(0);
47        }
48        c.push((src.to_string(), r.clone()));
49    });
50    r
51}
52fn parse_source_uncached(src: &str) -> ParseResult {
53    let mut parser = Parser::new();
54    let lang: Language = LANGUAGE.into();
55    parser.set_language(&lang).expect("grammar");
56    let tree = parser.parse(src, None).expect("parse");
57    let root = tree.root_node();
58    let mut errors = Vec::new();
59    collect_errors(root, &mut errors);
60    let lw = Lower {
61        src: src.as_bytes(),
62    };
63    let mut decls = Vec::new();
64    let mut cur = root.walk();
65    for c in root.named_children(&mut cur) {
66        if c.kind() == "ERROR" {
67            continue;
68        }
69        match lw.decl(c) {
70            Ok(Some(mut d)) => {
71                let export_kw = c.prev_sibling().filter(|p| lw.text(*p) == "export");
72                let exported = export_kw.is_some() || matches!(d.body, DeclBody::ReExport { .. });
73                d.exported = exported;
74                // the declaration's source range: the `export` keyword, when
75                // present, is the previous sibling and is included
76                let start = export_kw
77                    .map(|p| p.start_position())
78                    .unwrap_or_else(|| c.start_position());
79                let start_byte = export_kw
80                    .map(|p| p.start_byte())
81                    .unwrap_or_else(|| c.start_byte());
82                d.loc = Some(Loc {
83                    sl: start.row,
84                    sc: lw.col16(start_byte),
85                    el: c.end_position().row,
86                    ec: lw.col16(c.end_byte()),
87                });
88                decls.push(d);
89            }
90            Ok(None) => {}
91            Err(_) => {
92                if errors.is_empty() {
93                    errors.push((c.start_position().row, c.start_position().column));
94                }
95            }
96        }
97    }
98    ParseResult { decls, errors }
99}
100
101fn collect_errors(n: Node, out: &mut Vec<(usize, usize)>) {
102    if n.kind() == "ERROR" || n.is_missing() {
103        out.push((n.start_position().row, n.start_position().column));
104    }
105    if n.has_error() {
106        let mut cur = n.walk();
107        for c in n.children(&mut cur) {
108            collect_errors(c, out);
109        }
110    }
111}
112
113type LR<T> = Result<T, String>;
114
115impl<'a> Lower<'a> {
116    fn text(&self, n: Node) -> String {
117        n.utf8_text(self.src).unwrap_or("").to_string()
118    }
119    fn field<'b>(&self, n: Node<'b>, name: &str) -> Option<Node<'b>> {
120        n.child_by_field_name(name)
121    }
122    fn req<'b>(&self, n: Node<'b>, name: &str) -> LR<Node<'b>> {
123        n.child_by_field_name(name)
124            .ok_or_else(|| format!("missing field {name}"))
125    }
126    fn named<'b>(&self, n: Node<'b>) -> Vec<Node<'b>> {
127        let mut cur = n.walk();
128        n.named_children(&mut cur).collect()
129    }
130    fn all<'b>(&self, n: Node<'b>) -> Vec<Node<'b>> {
131        let mut cur = n.walk();
132        n.children(&mut cur).collect()
133    }
134    fn kids<'b>(&self, n: Node<'b>, kind: &str) -> Vec<Node<'b>> {
135        self.named(n)
136            .into_iter()
137            .filter(|c| c.kind() == kind)
138            .collect()
139    }
140    fn kid<'b>(&self, n: Node<'b>, kind: &str) -> Option<Node<'b>> {
141        self.named(n).into_iter().find(|c| c.kind() == kind)
142    }
143    // `true` / `false` / `null` are anonymous keyword tokens in the grammar:
144    // an operand position may hold one, so operands are the named children
145    // plus those literals (never the operator or punctuation tokens)
146    fn is_lit_keyword(&self, c: Node) -> bool {
147        !c.is_named() && ["true", "false", "null"].contains(&self.text(c).as_str())
148    }
149    fn operands<'b>(&self, n: Node<'b>) -> Vec<Node<'b>> {
150        self.all(n)
151            .into_iter()
152            .filter(|c| c.is_named() || self.is_lit_keyword(*c))
153            .collect()
154    }
155    // checked child access: a tree with errors may lack the children the
156    // grammar promises, and lowering must fail (E2001), never panic
157    fn first<'b>(&self, n: Node<'b>) -> LR<Node<'b>> {
158        self.named(n)
159            .into_iter()
160            .next()
161            .ok_or_else(|| format!("{}: missing child", n.kind()))
162    }
163    fn first_operand<'b>(&self, n: Node<'b>) -> LR<Node<'b>> {
164        self.operands(n)
165            .into_iter()
166            .next()
167            .ok_or_else(|| format!("{}: missing operand", n.kind()))
168    }
169    fn at<'b>(&self, v: &[Node<'b>], i: usize) -> LR<Node<'b>> {
170        v.get(i)
171            .copied()
172            .ok_or_else(|| format!("missing operand {i}"))
173    }
174    fn json_string(&self, n: Node) -> LR<String> {
175        json_unquote(&self.text(n).replace('\n', "\\n"))
176    }
177
178    // ---------------- declarations ----------------
179    fn decl(&self, n: Node) -> LR<Option<Decl>> {
180        let body = match n.kind() {
181            "type_declaration" => {
182                let params = match self.kid(n, "type_parameters") {
183                    Some(ps) => self
184                        .kids(ps, "type_parameter")
185                        .into_iter()
186                        .map(|p| {
187                            let nc = self.named(p);
188                            Ok(Param {
189                                name: self.text(self.at(&nc, 0)?),
190                                ty: if nc.len() > 1 {
191                                    Some(self.ty(nc[1])?)
192                                } else {
193                                    None
194                                },
195                            })
196                        })
197                        .collect::<LR<Vec<_>>>()?,
198                    None => vec![],
199                };
200                DeclBody::Type {
201                    name: self.text(self.req(n, "name")?),
202                    params,
203                    ty: self.ty(self.req(n, "type")?)?,
204                    tail: self.maybe_tail(n)?,
205                }
206            }
207            "const_declaration" => DeclBody::Const {
208                name: self.text(self.req(n, "name")?),
209                ty: match self.field(n, "type") {
210                    Some(t) => Some(self.ty(t)?),
211                    None => None,
212                },
213                expr: self.expr(self.req(n, "value")?)?,
214            },
215            "func_declaration" => DeclBody::Func {
216                name: self.text(self.req(n, "name")?),
217                params: self.params(n)?,
218                ret: match self.field(n, "return_type") {
219                    Some(t) => Some(self.ty(t)?),
220                    None => None,
221                },
222                body: self.expr(self.req(n, "body")?)?,
223            },
224            "output_declaration" => DeclBody::Output {
225                name: self.text(self.req(n, "name")?),
226                ty: self.ty(self.req(n, "type")?)?,
227                expr: self.expr(self.req(n, "value")?)?,
228            },
229            "input_declaration" => DeclBody::Input {
230                name: self.text(self.req(n, "name")?),
231                ty: self.ty(self.req(n, "type")?)?,
232                fallback: match self.field(n, "fallback") {
233                    Some(f) => Some(self.expr(f)?),
234                    None => None,
235                },
236            },
237            "diagnostic_declaration" => DeclBody::Diagnostic {
238                name: self.text(self.req(n, "name")?),
239                params: self.params(n)?,
240                severity: self.text(self.kid(n, "severity").ok_or("severity")?),
241                template: self.template_parts(self.kid(n, "template_string").ok_or("template")?)?,
242            },
243            "dimension_declaration" => DeclBody::Dimension {
244                name: self.text(self.req(n, "name")?),
245                terms: self
246                    .kid(n, "dimension_expression")
247                    .map(|e| self.dim_expr(e)),
248            },
249            "unit_declaration" => match self.field(n, "dimension") {
250                Some(d) => DeclBody::Unit {
251                    name: self.text(self.req(n, "name")?),
252                    dim: Some(self.text(d)),
253                    factor: None,
254                    base: None,
255                },
256                None => DeclBody::Unit {
257                    name: self.text(self.req(n, "name")?),
258                    dim: None,
259                    factor: Some(self.expr(self.req(n, "factor")?)?),
260                    base: Some(self.text(self.req(n, "base")?)),
261                },
262            },
263            "import_declaration" => {
264                let from = self.json_string(self.kid(n, "string").ok_or("from")?)?;
265                match self.kid(n, "named_imports") {
266                    Some(ni) => DeclBody::Import {
267                        from,
268                        names: Some(self.import_items(ni)?),
269                        ns: None,
270                    },
271                    None => DeclBody::Import {
272                        from,
273                        names: None,
274                        ns: Some(self.text(self.kid(n, "identifier").ok_or("ns")?)),
275                    },
276                }
277            }
278            "re_export_declaration" => DeclBody::ReExport {
279                from: self.json_string(self.kid(n, "string").ok_or("from")?)?,
280                names: self.import_items(n)?,
281            },
282            _ => return Ok(None),
283        };
284        Ok(Some(Decl {
285            body,
286            exported: false,
287            loc: None,
288        }))
289    }
290    fn params(&self, n: Node) -> LR<Vec<Param>> {
291        self.kids(n, "parameter")
292            .into_iter()
293            .map(|p| {
294                let nc = self.named(p);
295                Ok(Param {
296                    name: self.text(self.at(&nc, 0)?),
297                    ty: Some(self.ty(self.at(&nc, 1)?)?),
298                })
299            })
300            .collect()
301    }
302    fn import_items(&self, n: Node) -> LR<Vec<ImportItem>> {
303        self.kids(n, "import_item")
304            .into_iter()
305            .map(|it| {
306                let ids = self.named(it);
307                Ok(ImportItem {
308                    name: self.text(self.at(&ids, 0)?),
309                    alias: ids.get(1).map(|a| self.text(*a)),
310                })
311            })
312            .collect()
313    }
314    fn maybe_tail(&self, n: Node) -> LR<Option<Tail>> {
315        match self.kid(n, "else_clause") {
316            Some(t) => Ok(Some(self.tail(t)?)),
317            None => Ok(None),
318        }
319    }
320    fn tail(&self, n: Node) -> LR<Tail> {
321        if let Some(sev) = self.kid(n, "severity") {
322            return Ok(Tail::Inline {
323                severity: self.text(sev),
324                template: self.template_parts(self.kid(n, "template_string").ok_or("tmpl")?)?,
325            });
326        }
327        let name = self.text(self.kid(n, "qualified_name").ok_or("name")?);
328        let args = self
329            .named(n)
330            .into_iter()
331            .filter(|c| c.kind() != "qualified_name")
332            .map(|c| self.expr(c))
333            .collect::<LR<Vec<_>>>()?;
334        Ok(Tail::Ref { name, args })
335    }
336    fn template_parts(&self, n: Node) -> LR<Vec<TPart>> {
337        let mut parts = Vec::new();
338        for c in self.named(n) {
339            match c.kind() {
340                "template_chars" => parts.push(TPart::Text(self.text(c))),
341                "template_escape" => {
342                    let t = self.text(c);
343                    let s = match t.as_str() {
344                        "\\n" => "\n",
345                        "\\t" => "\t",
346                        "\\r" => "\r",
347                        other => &other[1..],
348                    };
349                    parts.push(TPart::Text(s.to_string()));
350                }
351                "interpolation" => parts.push(TPart::Expr(self.expr(self.first_operand(c)?)?)),
352                _ => {}
353            }
354        }
355        Ok(parts)
356    }
357
358    /// the source range of a node, columns in UTF-16 units (the reference's)
359    fn col16(&self, byte: usize) -> usize {
360        let start = self.src[..byte]
361            .iter()
362            .rposition(|&b| b == b'\n')
363            .map(|i| i + 1)
364            .unwrap_or(0);
365        String::from_utf8_lossy(&self.src[start..byte])
366            .encode_utf16()
367            .count()
368    }
369    fn loc_of(&self, n: Node) -> Loc {
370        Loc {
371            sl: n.start_position().row,
372            sc: self.col16(n.start_byte()),
373            el: n.end_position().row,
374            ec: self.col16(n.end_byte()),
375        }
376    }
377
378    // ---------------- types ----------------
379    fn ty(&self, n: Node) -> LR<TypeAst> {
380        let mut t = self.ty0(n)?;
381        t.set_loc(self.loc_of(n));
382        Ok(t)
383    }
384    fn ty0(&self, n: Node) -> LR<TypeAst> {
385        Ok(match n.kind() {
386            "union_type" => TypeAst::Union {
387                arms: self
388                    .named(n)
389                    .into_iter()
390                    .map(|c| self.ty(c))
391                    .collect::<LR<_>>()?,
392                loc: None,
393            },
394            "intersection_type" => TypeAst::Isect {
395                arms: self
396                    .named(n)
397                    .into_iter()
398                    .map(|c| self.ty(c))
399                    .collect::<LR<_>>()?,
400                loc: None,
401            },
402            "nullable_type" => TypeAst::Union {
403                arms: vec![
404                    self.ty(self.first(n)?)?,
405                    TypeAst::Prim {
406                        name: "null".into(),
407                        loc: None,
408                    },
409                ],
410                loc: None,
411            },
412            "array_type" => {
413                let elem = Box::new(self.ty(self.first(n)?)?);
414                let range = self.kid(n, "array_size_range").or_else(|| {
415                    self.field(n, "size")
416                        .filter(|s| s.kind() == "range_expression")
417                });
418                if let Some(r) = range {
419                    let ends: Vec<Value> = self
420                        .named(r)
421                        .into_iter()
422                        .map(|c| self.const_num(c))
423                        .collect::<LR<_>>()?;
424                    let excl = self
425                        .all(r)
426                        .iter()
427                        .any(|c| !c.is_named() && self.text(*c) == "..<");
428                    let lo = num_or_name(ends.first().ok_or("range endpoint")?);
429                    let hi = num_or_name(ends.get(1).ok_or("range endpoint")?);
430                    return Ok(match hi {
431                        Value::Int(h) => TypeAst::Array {
432                            elem,
433                            lo: Some(lo),
434                            hi: Some(Value::Int(if excl { h - 1 } else { h })),
435                            excl: false,
436                            loc: None,
437                        },
438                        other => TypeAst::Array {
439                            elem,
440                            lo: Some(lo),
441                            hi: Some(other),
442                            excl,
443                            loc: None,
444                        },
445                    });
446                }
447                if let Some(size) = self.field(n, "size") {
448                    let v = num_or_name(&self.const_num(size)?);
449                    return Ok(TypeAst::Array {
450                        elem,
451                        lo: Some(v.clone()),
452                        hi: Some(v),
453                        excl: false,
454                        loc: None,
455                    });
456                }
457                TypeAst::Array {
458                    elem,
459                    lo: None,
460                    hi: None,
461                    excl: false,
462                    loc: None,
463                }
464            }
465            "range_type" => {
466                let nc = self.named(n);
467                TypeAst::Range {
468                    lo: self.const_num(self.at(&nc, 0)?)?,
469                    hi: self.const_num(self.at(&nc, 1)?)?,
470                    excl: self.text(n).contains("..<"),
471                    loc: None,
472                }
473            }
474            "number_literal" => TypeAst::Lit {
475                v: self.const_num(n)?,
476                loc: None,
477            },
478            "string" => TypeAst::Lit {
479                v: Value::Str(self.json_string(n)?),
480                loc: None,
481            },
482            "pattern" => {
483                let t = self.text(n);
484                TypeAst::Pattern {
485                    re: t[1..t.len() - 1].to_string(),
486                    loc: None,
487                }
488            }
489            "paren_type" => self.ty(self.first(n)?)?,
490            "record_type" => {
491                let mut open = false;
492                let mut members = Vec::new();
493                for c in self.named(n) {
494                    if c.kind() == "open_marker" {
495                        open = true;
496                        continue;
497                    }
498                    if let Some(m) = self.member(c)? {
499                        members.push(m);
500                    }
501                }
502                TypeAst::Record {
503                    members,
504                    open,
505                    loc: None,
506                }
507            }
508            "map_type" => TypeAst::Map {
509                key: Box::new(self.ty(self.req(n, "key")?)?),
510                val: Box::new(self.ty(self.req(n, "value")?)?),
511                loc: None,
512            },
513            "function_type" => {
514                let mut cs: Vec<TypeAst> = self
515                    .named(n)
516                    .into_iter()
517                    .map(|c| self.ty(c))
518                    .collect::<LR<_>>()?;
519                let ret = cs.pop().ok_or("func type")?;
520                TypeAst::Func {
521                    params: cs,
522                    ret: Box::new(ret),
523                    loc: None,
524                }
525            }
526            "named_type" => {
527                let name = self.text(self.kid(n, "qualified_name").ok_or("name")?);
528                let args = match self.kid(n, "type_arguments") {
529                    Some(a) => self
530                        .named(a)
531                        .into_iter()
532                        .map(|c| self.ty(c))
533                        .collect::<LR<_>>()?,
534                    None => vec![],
535                };
536                let preds = match self.field(n, "predicates") {
537                    Some(p) => Some(
538                        self.named(p)
539                            .into_iter()
540                            .map(|c| self.expr(c))
541                            .collect::<LR<_>>()?,
542                    ),
543                    None => None,
544                };
545                let ext = match self.field(n, "extension") {
546                    Some(e) => Some(Box::new(self.ty(e)?)),
547                    None => None,
548                };
549                if ["int", "uint", "float", "bool", "string"].contains(&name.as_str())
550                    && args.is_empty()
551                    && preds.is_none()
552                    && ext.is_none()
553                {
554                    return Ok(TypeAst::Prim { name, loc: None });
555                }
556                TypeAst::Named {
557                    name,
558                    args,
559                    preds,
560                    ext,
561                    loc: None,
562                }
563            }
564            _ => match self.text(n).as_str() {
565                "true" => TypeAst::Lit {
566                    v: Value::Bool(true),
567                    loc: None,
568                },
569                "false" => TypeAst::Lit {
570                    v: Value::Bool(false),
571                    loc: None,
572                },
573                "null" => TypeAst::Prim {
574                    name: "null".into(),
575                    loc: None,
576                },
577                other => return Err(format!("lower_type: unhandled {} '{}'", n.kind(), other)),
578            },
579        })
580    }
581    fn dim_expr(&self, n: Node) -> Vec<(String, i32)> {
582        let mut out = Vec::new();
583        let mut sign = 1;
584        for c in self.all(n) {
585            if !c.is_named() {
586                match self.text(c).as_str() {
587                    "/" => sign = -1,
588                    "*" => sign = 1,
589                    _ => {}
590                }
591                continue;
592            }
593            if c.kind() == "dimension_term" {
594                let nc = self.named(c);
595                let Some(ident) = nc.iter().find(|x| x.kind() == "identifier") else {
596                    continue;
597                };
598                let num = nc.iter().find(|x| x.kind() == "int");
599                let mut exp: i32 = num.map(|x| self.text(*x).parse().unwrap_or(1)).unwrap_or(1);
600                if self
601                    .all(c)
602                    .iter()
603                    .any(|x| !x.is_named() && self.text(*x) == "-")
604                {
605                    exp = -exp;
606                }
607                out.push((self.text(*ident), exp * sign));
608                sign = 1;
609            }
610        }
611        out
612    }
613    fn const_num(&self, n: Node) -> LR<Value> {
614        match n.kind() {
615            "number_literal" => {
616                let neg = self.text(n).trim_start().starts_with('-');
617                let v = self.const_num(self.first(n)?)?;
618                Ok(if neg { neg_value(v) } else { v })
619            }
620            "int" => Ok(Value::Int(parse_int(&self.text(n))?)),
621            "float" => Ok(Value::Float(
622                self.text(n)
623                    .replace('_', "")
624                    .parse::<f64>()
625                    .map_err(|e| e.to_string())?,
626            )),
627            "qualified_name" | "identifier" => Ok(Value::Str(self.text(n))),
628            k => Err(format!("const_num: {k}")),
629        }
630    }
631
632    // ---------------- members ----------------
633    fn member(&self, n: Node) -> LR<Option<MemberAst>> {
634        let mut m = self.member0(n)?;
635        if let Some(m) = m.as_mut() {
636            m.set_loc(self.loc_of(n));
637        }
638        Ok(m)
639    }
640    fn member0(&self, n: Node) -> LR<Option<MemberAst>> {
641        Ok(Some(match n.kind() {
642            // member kinds by syntax (D4, v0.3): `?` — input may supply it; `= e` —
643            // the schema computes it. Both: defaulted; `= e` alone: derived
644            "value_member" => {
645                let name_n = self.req(n, "name")?;
646                let name = if name_n.kind() == "string" {
647                    self.json_string(name_n)?
648                } else {
649                    self.text(name_n)
650                };
651                let opt = self.field(n, "optional").is_some();
652                let dflt = match self.field(n, "default") {
653                    Some(d) => Some(self.expr(d)?),
654                    None => None,
655                };
656                match dflt {
657                    Some(expr) if !opt => MemberAst::Derived {
658                        name,
659                        ty: Some(self.ty(self.req(n, "type")?)?),
660                        expr,
661                        hidden: false,
662                        loc: None,
663                    },
664                    dflt => MemberAst::Value {
665                        name,
666                        opt,
667                        ty: self.ty(self.req(n, "type")?)?,
668                        dflt,
669                        loc: None,
670                    },
671                }
672            }
673            "derived_member" => {
674                let name_n = self.req(n, "name")?;
675                MemberAst::Derived {
676                    name: if name_n.kind() == "string" {
677                        self.json_string(name_n)?
678                    } else {
679                        self.text(name_n)
680                    },
681                    ty: None,
682                    expr: self.expr(self.req(n, "value")?)?,
683                    hidden: false,
684                    loc: None,
685                }
686            }
687            // `x$ [: T] = e` — computed for the schema's own use, never part of the value (D34)
688            "hidden_member" => MemberAst::Derived {
689                name: self.text(self.req(n, "name")?),
690                ty: match self.field(n, "type") {
691                    Some(t) => Some(self.ty(t)?),
692                    None => None,
693                },
694                expr: self.expr(self.req(n, "value")?)?,
695                hidden: true,
696                loc: None,
697            },
698            "context_declaration" => MemberAst::Context {
699                variable: self.text(self.req(n, "variable")?),
700                ty: self.ty(self.req(n, "type")?)?,
701                loc: None,
702            },
703            "assert_member" => MemberAst::Assert {
704                name: self.text(self.req(n, "name")?),
705                cond: self.expr(self.req(n, "condition")?)?,
706                tail: self.maybe_tail(n)?,
707                loc: None,
708            },
709            "when_member" => {
710                let mut body = Vec::new();
711                for c in self.named(n).into_iter().skip(1) {
712                    if let Some(m) = self.member(c)? {
713                        body.push(m);
714                    }
715                }
716                MemberAst::When {
717                    cond: self.expr(self.req(n, "condition")?)?,
718                    body,
719                    loc: None,
720                }
721            }
722            _ => return Ok(None),
723        }))
724    }
725
726    // ---------------- expressions ----------------
727    fn expr(&self, n: Node) -> LR<Rc<Expr>> {
728        let e = Rc::new(self.expr_inner(n)?);
729        set_expr_loc(&e, self.loc_of(n));
730        Ok(e)
731    }
732    fn expr_inner(&self, n: Node) -> LR<Expr> {
733        const BIN: [&str; 13] = [
734            "pipe_expression",
735            "nullish_expression",
736            "binary_expression_or",
737            "binary_expression_and",
738            "bit_or_expression",
739            "bit_xor_expression",
740            "bit_and_expression",
741            "equality_expression",
742            "relational_expression",
743            "range_expression",
744            "shift_expression",
745            "additive_expression",
746            "multiplicative_expression",
747        ];
748        Ok(match n.kind() {
749            "int" => Expr::Lit(Value::Int(parse_int(&self.text(n))?)),
750            "float" => Expr::Lit(Value::Float(
751                self.text(n)
752                    .replace('_', "")
753                    .parse::<f64>()
754                    .map_err(|e| e.to_string())?,
755            )),
756            "unit_literal" => {
757                let t = self.text(n);
758                let re =
759                    regex::Regex::new(r"^([0-9._]+(?:[eE][+-]?[0-9]+)?)([A-Za-z][A-Za-z0-9]*)$")
760                        .unwrap();
761                let caps = re.captures(&t).ok_or("unit literal")?;
762                Expr::UnitLit {
763                    num: caps[1]
764                        .replace('_', "")
765                        .parse::<f64>()
766                        .map_err(|e| e.to_string())?,
767                    unit: caps[2].to_string(),
768                }
769            }
770            "string" => Expr::Lit(Value::Str(self.json_string(n)?)),
771            "template_string" => Expr::Template(self.template_parts(n)?),
772            "identifier" | "hidden_name" => Expr::Name(self.text(n)),
773            "context_variable" => Expr::Ctx(self.text(n)),
774            "referrers_expression" => Expr::Referrers {
775                ty: self.text(self.req(n, "type")?),
776                member: self.json_string(self.req(n, "member")?)?,
777            },
778            "paren_expression" => Expr::Paren(self.expr(self.first_operand(n)?)?),
779            "unary_expression" => Expr::Un {
780                op: self.text(self.all(n).into_iter().next().ok_or("operator")?),
781                x: self.expr(self.first_operand(n)?)?,
782            },
783            "if_expression" => Expr::If {
784                c: self.expr(self.req(n, "condition")?)?,
785                t: self.expr(self.req(n, "then")?)?,
786                f: self.expr(self.req(n, "else")?)?,
787            },
788            "lambda" => Expr::Lambda {
789                params: self
790                    .kids(n, "lambda_parameter")
791                    .into_iter()
792                    .map(|p| self.first(p).map(|c| self.text(c)))
793                    .collect::<LR<_>>()?,
794                body: self.expr(self.req(n, "body")?)?,
795            },
796            "with_expression" => {
797                let nc = self.operands(n);
798                Expr::With {
799                    base: self.expr(self.at(&nc, 0)?)?,
800                    patch: self.expr(self.at(&nc, 1)?)?,
801                }
802            }
803            "member_access" | "safe_access" => {
804                let nc = self.operands(n);
805                let name_n = self.at(&nc, 1)?;
806                Expr::Member {
807                    x: self.expr(self.at(&nc, 0)?)?,
808                    name: if name_n.kind() == "string" {
809                        self.json_string(name_n)?
810                    } else {
811                        self.text(name_n)
812                    },
813                    safe: n.kind() == "safe_access",
814                }
815            }
816            "index_access" => {
817                let nc = self.operands(n);
818                Expr::Index {
819                    x: self.expr(self.at(&nc, 0)?)?,
820                    i: self.expr(self.at(&nc, 1)?)?,
821                }
822            }
823            "call" => {
824                let cs = self.operands(n);
825                Expr::Call {
826                    fun: self.expr(self.at(&cs, 0)?)?,
827                    args: cs
828                        .iter()
829                        .skip(1)
830                        .map(|c| self.expr(*c))
831                        .collect::<LR<_>>()?,
832                }
833            }
834            "object" => {
835                if let Some(comp) = self.kid(n, "map_comprehension") {
836                    return self.expr_inner(comp);
837                }
838                let mut entries = Vec::new();
839                for en in self.kids(n, "object_entry") {
840                    match self.field(en, "key") {
841                        Some(k) => entries.push((
842                            if k.kind() == "string" {
843                                self.json_string(k)?
844                            } else {
845                                self.text(k)
846                            },
847                            self.expr(self.req(en, "value")?)?,
848                        )),
849                        None => entries.push(("...".to_string(), self.expr(self.first(en)?)?)),
850                    }
851                }
852                Expr::Obj(entries)
853            }
854            "map_comprehension" => Expr::MapComp {
855                key: self.expr(self.req(n, "key")?)?,
856                val: self.expr(self.req(n, "value")?)?,
857                clauses: self
858                    .kids(n, "for_clause")
859                    .into_iter()
860                    .map(|c| self.for_clause(c))
861                    .collect::<LR<_>>()?,
862            },
863            "array" => {
864                if let Some(comp) = self.kid(n, "array_comprehension") {
865                    return self.expr_inner(comp);
866                }
867                let mut items = Vec::new();
868                for en in self.kids(n, "array_entry") {
869                    let spread = self.text(en).starts_with("...");
870                    let inner = self
871                        .named(en)
872                        .into_iter()
873                        .next()
874                        .or_else(|| {
875                            self.all(en).into_iter().find(|c| {
876                                ["true", "false", "null"].contains(&self.text(*c).as_str())
877                            })
878                        })
879                        .ok_or("entry")?;
880                    items.push((spread, self.expr(inner)?));
881                }
882                Expr::Arr(items)
883            }
884            "array_comprehension" => Expr::Comp {
885                head: self.expr(self.req(n, "head")?)?,
886                clauses: self
887                    .kids(n, "for_clause")
888                    .into_iter()
889                    .map(|c| self.for_clause(c))
890                    .collect::<LR<_>>()?,
891            },
892            "matches_expression" => {
893                let nc = self.named(n);
894                Expr::Bin {
895                    op: "matches".into(),
896                    l: self.expr(self.at(&nc, 0)?)?,
897                    r: self.expr(self.at(&nc, 1)?)?,
898                }
899            }
900            "pattern" => {
901                let t = self.text(n);
902                Expr::Pattern(t[1..t.len() - 1].to_string())
903            }
904            "match_expression" => {
905                let mut arms = Vec::new();
906                for a in self.kids(n, "match_arm") {
907                    let body = self.req(a, "body")?;
908                    let others: Vec<Node> = self
909                        .named(a)
910                        .into_iter()
911                        .filter(|c| c.id() != body.id())
912                        .collect();
913                    arms.push(MatchArm {
914                        v: self.text(self.at(&others, 0)?),
915                        ty: if others.len() > 1 {
916                            Some(self.ty(others[1])?)
917                        } else {
918                            None
919                        },
920                        body: self.expr(body)?,
921                    });
922                }
923                Expr::Match {
924                    subject: self.expr(self.req(n, "subject")?)?,
925                    arms,
926                }
927            }
928            k if BIN.contains(&k) => {
929                let nc = self.operands(n);
930                // the operator is the one anonymous child that is not an operand
931                let op = self
932                    .all(n)
933                    .into_iter()
934                    .filter(|c| !c.is_named() && !self.is_lit_keyword(*c))
935                    .map(|c| self.text(c))
936                    .find(|t| !t.trim().is_empty())
937                    .ok_or("op")?;
938                Expr::Bin {
939                    op,
940                    l: self.expr(self.at(&nc, 0)?)?,
941                    r: self.expr(self.at(&nc, 1)?)?,
942                }
943            }
944            _ => match self.text(n).as_str() {
945                "true" => Expr::Lit(Value::Bool(true)),
946                "false" => Expr::Lit(Value::Bool(false)),
947                "null" => Expr::Lit(Value::Null),
948                other => return Err(format!("lower_expr: unhandled {} '{}'", n.kind(), other)),
949            },
950        })
951    }
952    fn for_clause(&self, n: Node) -> LR<ForClause> {
953        let mut cur = n.walk();
954        let filters = n
955            .children_by_field_name("filter", &mut cur)
956            .map(|c| self.expr(c))
957            .collect::<LR<Vec<_>>>()?;
958        Ok(ForClause {
959            v: self.text(self.req(n, "variable")?),
960            iter: self.expr(self.req(n, "iterable")?)?,
961            filters,
962        })
963    }
964}
965
966fn num_or_name(v: &Value) -> Value {
967    match v {
968        Value::Float(f) => Value::Int(BigInt::from(*f as i64)),
969        other => other.clone(),
970    }
971}
972fn neg_value(v: Value) -> Value {
973    match v {
974        Value::Int(i) => Value::Int(-i),
975        Value::Float(f) => Value::Float(-f),
976        other => other,
977    }
978}
979pub fn parse_int(text: &str) -> LR<BigInt> {
980    let t = text.replace('_', "");
981    let (radix, digits) = if let Some(h) = t.strip_prefix("0x").or_else(|| t.strip_prefix("0X")) {
982        (16, h.to_string())
983    } else if let Some(o) = t.strip_prefix("0o").or_else(|| t.strip_prefix("0O")) {
984        (8, o.to_string())
985    } else if let Some(b) = t.strip_prefix("0b").or_else(|| t.strip_prefix("0B")) {
986        (2, b.to_string())
987    } else {
988        (10, t.clone())
989    };
990    BigInt::from_str_radix(&digits, radix).map_err(|e| e.to_string())
991}
992
993/// JSON string literal -> its value (the lexer guarantees the form)
994pub fn json_unquote(s: &str) -> LR<String> {
995    let inner = &s[1..s.len() - 1];
996    let mut out = String::new();
997    let mut chars = inner.chars();
998    while let Some(c) = chars.next() {
999        if c != '\\' {
1000            out.push(c);
1001            continue;
1002        }
1003        match chars.next() {
1004            Some('n') => out.push('\n'),
1005            Some('t') => out.push('\t'),
1006            Some('r') => out.push('\r'),
1007            Some('b') => out.push('\u{8}'),
1008            Some('f') => out.push('\u{c}'),
1009            Some('u') => {
1010                let hex: String = chars.by_ref().take(4).collect();
1011                let cp = u32::from_str_radix(&hex, 16).map_err(|e| e.to_string())?;
1012                out.push(char::from_u32(cp).unwrap_or('\u{fffd}'));
1013            }
1014            Some(other) => out.push(other),
1015            None => {}
1016        }
1017    }
1018    Ok(out)
1019}