Skip to main content

litex/parse/
parse_obj.rs

1use crate::prelude::*;
2use std::collections::HashMap;
3
4impl Runtime {
5    pub fn parse_obj(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
6        self.parse_obj_hierarchy0(tb)
7    }
8
9    /// Infix `name` (one backtick before the function name) is loosest; then `+-`, `*/%`, `^`, `[]`, `...`, primary.
10    fn parse_obj_hierarchy0(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
11        let left = self.parse_obj_hierarchy1(tb)?;
12        if tb.exceed_end_of_head() {
13            return Ok(left);
14        }
15        if tb.current_token_is_equal_to(INFIX_FN_NAME_SIGN) {
16            tb.skip()?; // consume the infix delimiter, then read the name
17            let fn_name = self.parse_identifier_or_identifier_with_mod(tb)?;
18            let right = self.parse_obj(tb)?;
19
20            if is_key_symbol_or_keyword(&fn_name.to_string()) {
21                return match fn_name.to_string().as_str() {
22                    UNION => Ok(Union::new(left, right).into()),
23                    INTERSECT => Ok(Intersect::new(left, right).into()),
24                    SET_MINUS => Ok(SetMinus::new(left, right).into()),
25                    SET_DIFF => Ok(SetDiff::new(left, right).into()),
26                    RANGE => Ok(Range::new(left, right).into()),
27                    CLOSED_RANGE => Ok(ClosedRange::new(left, right).into()),
28                    PROJ => Ok(Proj::new(left, right).into()),
29                    _ => Err(RuntimeError::from(ParseRuntimeError(
30                        RuntimeErrorStruct::new_with_msg_and_line_file(
31                            format!("{} does not support infix function syntax", fn_name),
32                            tb.line_file.clone(),
33                        ),
34                    ))),
35                };
36            }
37
38            let body = vec![vec![Box::new(left), Box::new(right)]];
39
40            let head = FnObjHead::given_an_atom_return_a_fn_obj_head(fn_name).ok_or_else(|| {
41                RuntimeError::from(ParseRuntimeError(RuntimeErrorStruct::new_with_msg_and_line_file("infix (backtick) expects an identifier or single field-access name for the function"
42                        .to_string(), tb.line_file.clone())))
43            })?;
44            Ok(FnObj::new(head, body).into())
45        } else {
46            Ok(left)
47        }
48    }
49
50    /// + - 优先级最低,左结合,可连续 2 + 3 - 4
51    fn parse_obj_hierarchy1(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
52        let mut left = self.parse_obj_hierarchy2(tb)?;
53        loop {
54            if tb.exceed_end_of_head() {
55                return Ok(left);
56            }
57            if tb.current_token_is_equal_to(ADD) {
58                tb.skip()?;
59                let right = self.parse_obj_hierarchy2(tb)?;
60
61                left = Add::new(left, right).into();
62            } else if tb.current_token_is_equal_to(SUB) {
63                tb.skip()?;
64                let right = self.parse_obj_hierarchy2(tb)?;
65                left = Sub::new(left, right).into();
66            } else {
67                return Ok(left);
68            }
69        }
70    }
71
72    /// * / % 高于 + -,左结合
73    fn parse_obj_hierarchy2(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
74        let mut left = self.parse_obj_hierarchy3(tb)?;
75        loop {
76            if tb.exceed_end_of_head() {
77                return Ok(left);
78            }
79            if tb.current_token_is_equal_to(MUL) {
80                tb.skip()?;
81                let right = self.parse_obj_hierarchy3(tb)?;
82                left = Mul::new(left, right).into();
83            } else if tb.current_token_is_equal_to(DIV) {
84                tb.skip()?;
85                let right = self.parse_obj_hierarchy3(tb)?;
86                left = Div::new(left, right).into();
87            } else if tb.current_token_is_equal_to(MOD) {
88                tb.skip()?;
89                let right = self.parse_obj_hierarchy3(tb)?;
90                left = Mod::new(left, right).into();
91            } else if tb.current_token_is_equal_to(MATRIX_SCALAR_MUL) {
92                tb.skip()?;
93                let right = self.parse_obj_hierarchy3(tb)?;
94                left = MatrixScalarMul::new(left, right).into();
95            } else {
96                return Ok(left);
97            }
98        }
99    }
100
101    /// ^ 高于 * / %,右结合:2^3^2 = 2^(3^2)
102    fn parse_obj_hierarchy3(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
103        let left = self.parse_obj_hierarchy4(tb)?;
104        if tb.exceed_end_of_head() {
105            return Ok(left);
106        }
107        if tb.current_token_is_equal_to(POW) {
108            tb.skip()?;
109            let right = self.parse_obj_hierarchy3(tb)?; // 右结合:右侧可继续接 ^
110            Ok(Pow::new(left, right).into())
111        } else if tb.current_token_is_equal_to(MATRIX_POW) {
112            tb.skip()?;
113            let right = self.parse_obj_hierarchy3(tb)?;
114            Ok(MatrixPow::new(left, right).into())
115        } else if tb.current_token_is_equal_to(MATRIX_MUL) {
116            tb.skip()?;
117            let right = self.parse_obj_hierarchy3(tb)?;
118            Ok(MatrixMul::new(left, right).into())
119        } else if tb.current_token_is_equal_to(MATRIX_SUB) {
120            tb.skip()?;
121            let right = self.parse_obj_hierarchy3(tb)?;
122            Ok(MatrixSub::new(left, right).into())
123        } else if tb.current_token_is_equal_to(MATRIX_ADD) {
124            tb.skip()?;
125            let right = self.parse_obj_hierarchy3(tb)?;
126            Ok(MatrixAdd::new(left, right).into())
127        } else {
128            Ok(left)
129        }
130    }
131
132    /// Subscript `[]`, tighter than `^`.
133    fn parse_obj_hierarchy4(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
134        let mut left = self.parse_obj_hierarchy5(tb)?;
135        loop {
136            if tb.current_token_is_equal_to(LEFT_BRACKET) {
137                tb.skip_token(LEFT_BRACKET)?;
138                let obj = self.parse_obj(tb)?;
139                tb.skip_token(RIGHT_BRACKET)?;
140                left = ObjAtIndex::new(left, obj).into();
141            } else {
142                return Ok(left);
143            }
144        }
145    }
146
147    /// Infix closed interval `...` (`closed_range`); same band as `[]`, applied after subscripts.
148    fn parse_obj_hierarchy5(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
149        let left = self.parse_obj_hierarchy6(tb)?;
150
151        if tb.current_token_is_equal_to(DOT_DOT_DOT) {
152            tb.skip_token(DOT_DOT_DOT)?;
153            let right = self.parse_obj_hierarchy1(tb)?;
154            Ok(ClosedRange::new(left, right).into())
155        } else {
156            Ok(left)
157        }
158    }
159
160    /// Primary: `{ }`, `fn`, numbers, `()`, keywords, atoms.
161    fn parse_obj_hierarchy6(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
162        if tb.current_token_is_equal_to(LEFT_CURLY_BRACE) {
163            self.parse_set_builder_or_set_list(tb)
164        } else if tb.current_token_is_equal_to(LEFT_BRACKET) {
165            tb.skip_token(LEFT_BRACKET)?;
166            if tb.current_token_is_equal_to(LEFT_BRACKET) {
167                let mut rows: Vec<Vec<Obj>> = vec![];
168                loop {
169                    tb.skip_token(LEFT_BRACKET)?;
170                    let mut row: Vec<Obj> = vec![];
171                    if !tb.current_token_is_equal_to(RIGHT_BRACKET) {
172                        row.push(self.parse_obj(tb)?);
173                        while tb.current_token_is_equal_to(COMMA) {
174                            tb.skip_token(COMMA)?;
175                            row.push(self.parse_obj(tb)?);
176                        }
177                    }
178                    tb.skip_token(RIGHT_BRACKET)?;
179                    rows.push(row);
180                    if tb.current_token_is_equal_to(COMMA) {
181                        tb.skip_token(COMMA)?;
182                        if !tb.current_token_is_equal_to(LEFT_BRACKET) {
183                            return Err(RuntimeError::from(ParseRuntimeError(
184                                RuntimeErrorStruct::new_with_msg_and_line_file(
185                                    "matrix literal: expected `[` after `,` between rows"
186                                        .to_string(),
187                                    tb.line_file.clone(),
188                                ),
189                            )));
190                        }
191                    } else if tb.current_token_is_equal_to(RIGHT_BRACKET) {
192                        tb.skip_token(RIGHT_BRACKET)?;
193                        return Ok(MatrixListObj::new(rows).into());
194                    } else {
195                        return Err(RuntimeError::from(ParseRuntimeError(
196                            RuntimeErrorStruct::new_with_msg_and_line_file(
197                                "matrix literal: expected `,` or closing `]`".to_string(),
198                                tb.line_file.clone(),
199                            ),
200                        )));
201                    }
202                }
203            } else if tb.current_token_is_equal_to(RIGHT_BRACKET) {
204                tb.skip_token(RIGHT_BRACKET)?;
205                let list = FiniteSeqListObj::new(vec![]);
206                let mut result: Obj = list.clone().into();
207                let head = FnObjHead::FiniteSeqListObj(list);
208                let mut body_vectors: Vec<Vec<Box<Obj>>> = vec![];
209                while !tb.exceed_end_of_head() && tb.current()? == LEFT_BRACE {
210                    let args = self.parse_fn_obj_arg_group(tb)?;
211                    let group: Vec<Box<Obj>> = args.into_iter().map(Box::new).collect();
212                    body_vectors.push(group);
213                }
214                if !body_vectors.is_empty() {
215                    result = FnObj::new(head, body_vectors).into();
216                }
217                Ok(result)
218            } else {
219                let mut objs = vec![self.parse_obj(tb)?];
220                while tb.current_token_is_equal_to(COMMA) {
221                    tb.skip_token(COMMA)?;
222                    objs.push(self.parse_obj(tb)?);
223                }
224                tb.skip_token(RIGHT_BRACKET)?;
225                let list = FiniteSeqListObj::new(objs);
226                let mut result: Obj = list.clone().into();
227                let head = FnObjHead::FiniteSeqListObj(list);
228                let mut body_vectors: Vec<Vec<Box<Obj>>> = vec![];
229                while !tb.exceed_end_of_head() && tb.current()? == LEFT_BRACE {
230                    let args = self.parse_fn_obj_arg_group(tb)?;
231                    let group: Vec<Box<Obj>> = args.into_iter().map(Box::new).collect();
232                    body_vectors.push(group);
233                }
234                if !body_vectors.is_empty() {
235                    result = FnObj::new(head, body_vectors).into();
236                }
237                Ok(result)
238            }
239        } else if tb.current_token_is_equal_to(FN_LOWER_CASE) {
240            tb.skip_token(FN_LOWER_CASE)?;
241            Ok(self.parse_fn_set(tb)?.into())
242        } else if tb.current_token_is_equal_to(ANONYMOUS_FN_PREFIX) {
243            let mut result = self.parse_anonymous_fn(tb)?;
244            if let Obj::AnonymousFn(anon) = &result {
245                let mut body_vectors: Vec<Vec<Box<Obj>>> = vec![];
246                while !tb.exceed_end_of_head() && tb.current()? == LEFT_BRACE {
247                    let args = self.parse_fn_obj_arg_group(tb)?;
248                    let group: Vec<Box<Obj>> = args.into_iter().map(Box::new).collect();
249                    body_vectors.push(group);
250                }
251                if !body_vectors.is_empty() {
252                    let head = FnObjHead::AnonymousFnLiteral(Box::new(anon.clone()));
253                    result = FnObj::new(head, body_vectors).into();
254                }
255            }
256            Ok(result)
257        } else {
258            self.parse_number_or_primary_obj_or_fn_obj_with_minus_prefix(tb)
259        }
260    }
261
262    /// `'` + `(param sets [: dom])` + return set + `{ body }`, or `'` + set + `(names)` + `{ body }`.
263    ///
264    /// After a comma-separated name list, if the next token is `:` (domain facts) rather than a set
265    /// expression, parameters are taken to be in `R` (same as writing `x, y R : ...`).
266    pub fn parse_anonymous_fn(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
267        tb.skip_token(ANONYMOUS_FN_PREFIX)?;
268        if tb.current_token_is_equal_to(LEFT_BRACE) {
269            let built = self.run_in_local_parsing_time_name_scope(|this| {
270                tb.skip_token(LEFT_BRACE)?;
271                let mut params_def_with_set: Vec<ParamGroupWithSet> = vec![];
272                loop {
273                    let param = parse_synthetically_correct_identifier_string(tb)?;
274                    let mut current_params = vec![param];
275
276                    while tb.current_token_is_equal_to(COMMA) {
277                        tb.skip_token(COMMA)?;
278                        current_params.push(parse_synthetically_correct_identifier_string(tb)?);
279                    }
280
281                    let param_group = if tb.current_token_is_equal_to(COLON) {
282                        ParamGroupWithSet::new(current_params, StandardSet::R.into())
283                    } else {
284                        ParamGroupWithSet::new(current_params, this.parse_obj(tb)?)
285                    };
286                    this.parsing_free_param_collection.begin_scope(
287                        ParamObjType::FnSet,
288                        &param_group.params,
289                        tb.line_file.clone(),
290                    )?;
291
292                    params_def_with_set.push(param_group);
293
294                    if tb.current_token_is_equal_to(COMMA) {
295                        tb.skip_token(COMMA)?;
296                        continue;
297                    } else if tb.current_token_is_equal_to(COLON) {
298                        break;
299                    } else if tb.current_token_is_equal_to(RIGHT_BRACE) {
300                        break;
301                    } else {
302                        return Err(RuntimeError::from(ParseRuntimeError(
303                            RuntimeErrorStruct::new_with_msg_and_line_file("anonymous fn: expected `,`, `:`, or closing `)` after parameter group"
304                                    .to_string(), tb.line_file.clone()),
305                        )));
306                    }
307                }
308
309                let all_fn_names = ParamGroupWithSet::collect_param_names(&params_def_with_set);
310
311                let mut dom_facts = vec![];
312                if tb.current_token_is_equal_to(COLON) {
313                    tb.skip_token(COLON)?;
314                    let cur = this.parse_or_and_chain_atomic_fact(tb)?;
315                    dom_facts.push(cur);
316                    while tb.current_token_is_equal_to(COMMA) {
317                        tb.skip_token(COMMA)?;
318                        let cur = this.parse_or_and_chain_atomic_fact(tb)?;
319                        dom_facts.push(cur);
320                    }
321                }
322
323                tb.skip_token(RIGHT_BRACE)?;
324                // Return sets are non-dependent; parse them outside the function-parameter scope.
325                this.parsing_free_param_collection
326                    .end_scope(ParamObjType::FnSet, &all_fn_names);
327                let ret_set_parsed = this.parse_obj(tb)?;
328                let equal_to = this.parse_in_local_free_param_scope(
329                    ParamObjType::FnSet,
330                    &all_fn_names,
331                    tb.line_file.clone(),
332                    |inner| {
333                        tb.skip_token(LEFT_CURLY_BRACE)?;
334                        let equal_to = inner.parse_obj(tb)?;
335                        tb.skip_token(RIGHT_CURLY_BRACE)?;
336                        Ok(equal_to)
337                    },
338                )?;
339                let built =
340                    this.new_anonymous_fn(params_def_with_set, dom_facts, ret_set_parsed, equal_to)?;
341                Ok(built)
342            })?;
343            Ok(built.into())
344        } else {
345            let set_obj = self.parse_and_reclassify_atom_as_free_param_obj(tb)?;
346            let built = self.run_in_local_parsing_time_name_scope(|this| {
347                tb.skip_token(LEFT_BRACE)?;
348                let mut params = vec![parse_synthetically_correct_identifier_string(tb)?];
349                while tb.current_token_is_equal_to(COMMA) {
350                    tb.skip_token(COMMA)?;
351                    params.push(parse_synthetically_correct_identifier_string(tb)?);
352                }
353                tb.skip_token(RIGHT_BRACE)?;
354                let param_group = ParamGroupWithSet::new(params, set_obj.clone());
355                let param_groups = vec![param_group.clone()];
356                let all_names = ParamGroupWithSet::collect_param_names(&param_groups);
357                this.parsing_free_param_collection.begin_scope(
358                    ParamObjType::FnSet,
359                    &all_names,
360                    tb.line_file.clone(),
361                )?;
362                tb.skip_token(LEFT_CURLY_BRACE)?;
363                let equal_to = this.parse_obj(tb)?;
364                tb.skip_token(RIGHT_CURLY_BRACE)?;
365                this.parsing_free_param_collection
366                    .end_scope(ParamObjType::FnSet, &all_names);
367                this.new_anonymous_fn(vec![param_group], vec![], set_obj, equal_to)
368            })?;
369            Ok(built.into())
370        }
371    }
372
373    pub fn parse_fn_set(&mut self, tb: &mut TokenBlock) -> Result<FnSet, RuntimeError> {
374        let fn_set = self.run_in_local_parsing_time_name_scope(|this| {
375            tb.skip_token(LEFT_BRACE)?;
376            let mut params_def_with_set: Vec<ParamGroupWithSet> = vec![];
377            loop {
378                let param = parse_synthetically_correct_identifier_string(tb)?;
379                let mut current_params = vec![param];
380
381                while tb.current_token_is_equal_to(COMMA) {
382                    tb.skip_token(COMMA)?;
383                    current_params.push(parse_synthetically_correct_identifier_string(tb)?);
384                }
385
386                let param_group = ParamGroupWithSet::new(current_params, this.parse_obj(tb)?);
387                this.parsing_free_param_collection.begin_scope(
388                    ParamObjType::FnSet,
389                    &param_group.params,
390                    tb.line_file.clone(),
391                )?;
392
393                params_def_with_set.push(param_group);
394
395                if tb.current_token_is_equal_to(COMMA) {
396                    tb.skip_token(COMMA)?;
397                    continue;
398                } else if tb.current_token_is_equal_to(COLON) {
399                    break;
400                } else if tb.current_token_is_equal_to(RIGHT_BRACE) {
401                    break;
402                } else {
403                    return Err(RuntimeError::from(ParseRuntimeError(
404                        RuntimeErrorStruct::new_with_msg_and_line_file(
405                            "Expected comma or colon".to_string(),
406                            tb.line_file.clone(),
407                        ),
408                    )));
409                }
410            }
411
412            let all_fn_names = ParamGroupWithSet::collect_param_names(&params_def_with_set);
413
414            let mut dom_facts = vec![];
415            if tb.current_token_is_equal_to(COLON) {
416                tb.skip_token(COLON)?;
417                let cur = this.parse_or_and_chain_atomic_fact(tb)?;
418                dom_facts.push(cur);
419                while tb.current_token_is_equal_to(COMMA) {
420                    tb.skip_token(COMMA)?;
421                    let cur = this.parse_or_and_chain_atomic_fact(tb)?;
422                    dom_facts.push(cur);
423                }
424            }
425
426            tb.skip_token(RIGHT_BRACE)?;
427            // Return sets are non-dependent; parse them outside the function-parameter scope.
428            this.parsing_free_param_collection
429                .end_scope(ParamObjType::FnSet, &all_fn_names);
430            let ret_set_parsed = this.parse_obj(tb)?;
431            let built = this.new_fn_set(params_def_with_set, dom_facts, ret_set_parsed);
432            Ok(FnSetOrFnSetClause::FnSet(built?))
433        });
434        match fn_set {
435            Ok(fn_set) => match fn_set {
436                FnSetOrFnSetClause::FnSet(fn_set) => Ok(fn_set),
437                FnSetOrFnSetClause::FnSetClause(_) => {
438                    panic!("FnSetOrFnSetClause::FnSetClause should not be returned");
439                }
440            },
441            Err(e) => Err(e),
442        }
443    }
444
445    pub fn parse_fn_set_clause(
446        &mut self,
447        tb: &mut TokenBlock,
448    ) -> Result<FnSetClause, RuntimeError> {
449        let clause = self.run_in_local_parsing_time_name_scope(|this| {
450            tb.skip_token(LEFT_BRACE)?;
451            let mut params_def_with_set: Vec<ParamGroupWithSet> = vec![];
452            loop {
453                let param = parse_synthetically_correct_identifier_string(tb)?;
454                let mut current_params = vec![param];
455
456                while tb.current_token_is_equal_to(COMMA) {
457                    tb.skip_token(COMMA)?;
458                    current_params.push(parse_synthetically_correct_identifier_string(tb)?);
459                }
460
461                let param_group = ParamGroupWithSet::new(current_params, this.parse_obj(tb)?);
462                this.parsing_free_param_collection.begin_scope(
463                    ParamObjType::FnSet,
464                    &param_group.params,
465                    tb.line_file.clone(),
466                )?;
467
468                params_def_with_set.push(param_group);
469
470                if tb.current_token_is_equal_to(COMMA) {
471                    tb.skip_token(COMMA)?;
472                    continue;
473                } else if tb.current_token_is_equal_to(COLON) {
474                    break;
475                } else if tb.current_token_is_equal_to(RIGHT_BRACE) {
476                    break;
477                } else {
478                    return Err(RuntimeError::from(ParseRuntimeError(
479                        RuntimeErrorStruct::new_with_msg_and_line_file(
480                            "Expected comma or colon".to_string(),
481                            tb.line_file.clone(),
482                        ),
483                    )));
484                }
485            }
486
487            let all_fn_names = ParamGroupWithSet::collect_param_names(&params_def_with_set);
488
489            let mut dom_facts = vec![];
490            if tb.current_token_is_equal_to(COLON) {
491                tb.skip_token(COLON)?;
492                let cur = this.parse_or_and_chain_atomic_fact(tb)?;
493                dom_facts.push(cur);
494                while tb.current_token_is_equal_to(COMMA) {
495                    tb.skip_token(COMMA)?;
496                    let cur = this.parse_or_and_chain_atomic_fact(tb)?;
497                    dom_facts.push(cur);
498                }
499            }
500
501            tb.skip_token(RIGHT_BRACE)?;
502            // Return sets are non-dependent; parse them outside the function-parameter scope.
503            this.parsing_free_param_collection
504                .end_scope(ParamObjType::FnSet, &all_fn_names);
505            let ret_set_parsed = this.parse_obj(tb)?;
506            let clause_ok = FnSetClause::new(params_def_with_set, dom_facts, ret_set_parsed)?;
507            Ok(FnSetOrFnSetClause::FnSetClause(clause_ok))
508        });
509        match clause {
510            Ok(clause) => match clause {
511                FnSetOrFnSetClause::FnSetClause(clause) => Ok(clause),
512                FnSetOrFnSetClause::FnSet(_) => {
513                    panic!("FnSetOrFnSetClause::FnSet should not be returned");
514                }
515            },
516            Err(e) => Err(e),
517        }
518    }
519
520    pub fn parse_number_or_primary_obj_or_fn_obj_with_minus_prefix(
521        &mut self,
522        tb: &mut TokenBlock,
523    ) -> Result<Obj, RuntimeError> {
524        if tb.current_token_is_equal_to(SUB) {
525            if minus_token_is_standalone_operator_obj(tb) {
526                tb.skip()?;
527                return Ok(Identifier::new(SUB.to_string()).into());
528            }
529            tb.skip()?;
530            let obj = self.parse_number_or_primary_obj_or_fn_obj(tb)?;
531            Ok(Mul::new(Number::new("-1".to_string()).into(), obj).into())
532        } else {
533            self.parse_number_or_primary_obj_or_fn_obj(tb)
534        }
535    }
536
537    /// 若得到 atom,调用方再给其接若干 (args) 变成 FnObj。
538    fn parse_number_or_primary_obj_or_fn_obj(
539        &mut self,
540        tb: &mut TokenBlock,
541    ) -> Result<Obj, RuntimeError> {
542        let token = tb.current()?;
543
544        // 0. (obj) 或 (obj, obj, ...)
545        if token == LEFT_BRACE {
546            tb.skip()?;
547            let obj = self.parse_obj(tb)?;
548
549            if tb.current_token_is_equal_to(COMMA) {
550                let mut args = vec![obj];
551                while tb.current_token_is_equal_to(COMMA) {
552                    tb.skip_token(COMMA)?;
553
554                    args.push(self.parse_obj(tb)?);
555                }
556                tb.skip_token(RIGHT_BRACE)?;
557                return Ok(Tuple::new(args).into());
558            } else {
559                tb.skip_token(RIGHT_BRACE)?;
560                return Ok(obj);
561            }
562        }
563
564        // 1. 数字
565        if starts_with_digit(token) {
566            let number = tb.advance()?;
567            // 若已经到行尾,则直接检查并返回
568            if tb.exceed_end_of_head() {
569                if !is_number(&number) {
570                    return Err(RuntimeError::from(ParseRuntimeError(
571                        RuntimeErrorStruct::new_with_msg_and_line_file(
572                            format!("Invalid number: {}", number),
573                            tb.line_file.clone(),
574                        ),
575                    )));
576                }
577                return Ok(Number::new(number).into());
578            }
579
580            if tb.current()? == DOT_AKA_FIELD_ACCESS_SIGN {
581                tb.skip()?;
582                let fraction = tb.advance()?;
583                let number = format!("{}{}{}", number, DOT_AKA_FIELD_ACCESS_SIGN, fraction);
584                if !is_number(&number) {
585                    return Err(RuntimeError::from(ParseRuntimeError(
586                        RuntimeErrorStruct::new_with_msg_and_line_file(
587                            format!("Invalid number: {}", number),
588                            tb.line_file.clone(),
589                        ),
590                    )));
591                }
592                return Ok(Number::new(number).into());
593            } else {
594                if !is_number(&number) {
595                    return Err(RuntimeError::from(ParseRuntimeError(
596                        RuntimeErrorStruct::new_with_msg_and_line_file(
597                            format!("Invalid number: {}", number),
598                            tb.line_file.clone(),
599                        ),
600                    )));
601                }
602                return Ok(Number::new(number).into());
603            }
604        }
605
606        // 2. 多元关键字、或 atom(内建 `StandardSet` 名在 reclassify 中处理)
607        let mut result = self.parse_primary_obj(tb)?;
608
609        // 3. 若是 atom,后面可以接多组 (args),每组一个 Vec<Obj>,合起来 body: Vec<Vec<Box<Obj>>>
610        let (head, mut body_vectors) = match &result {
611            Obj::Atom(AtomObj::Identifier(i)) => (FnObjHead::Identifier(i.clone()), vec![]),
612            Obj::Atom(AtomObj::IdentifierWithMod(m)) => {
613                (FnObjHead::IdentifierWithMod(m.clone()), vec![])
614            }
615            Obj::Atom(AtomObj::Forall(p)) => (FnObjHead::Forall(p.clone()), vec![]),
616            Obj::Atom(AtomObj::Exist(p)) => (FnObjHead::Exist(p.clone()), vec![]),
617            Obj::Atom(AtomObj::Def(p)) => (FnObjHead::DefHeader(p.clone()), vec![]),
618            Obj::Atom(AtomObj::SetBuilder(p)) => (FnObjHead::SetBuilder(p.clone()), vec![]),
619            Obj::Atom(AtomObj::FnSet(p)) => (FnObjHead::FnSet(p.clone()), vec![]),
620            Obj::Atom(AtomObj::Induc(p)) => (FnObjHead::Induc(p.clone()), vec![]),
621            Obj::Atom(AtomObj::DefAlgo(p)) => (FnObjHead::DefAlgo(p.clone()), vec![]),
622            Obj::Atom(AtomObj::DefStructField(_)) => return Ok(result),
623            Obj::AnonymousFn(anon) => (
624                FnObjHead::AnonymousFnLiteral(Box::new(anon.clone())),
625                vec![],
626            ),
627            Obj::FiniteSeqListObj(list) => (FnObjHead::FiniteSeqListObj(list.clone()), vec![]),
628            Obj::InstantiatedTemplateObj(t) => {
629                (FnObjHead::InstantiatedTemplateObj(t.clone()), vec![])
630            }
631            _ => return Ok(result),
632        };
633        while !tb.exceed_end_of_head() && tb.current()? == LEFT_BRACE {
634            let args = self.parse_fn_obj_arg_group(tb)?;
635            let group: Vec<Box<Obj>> = args.into_iter().map(Box::new).collect();
636            body_vectors.push(group);
637        }
638        if !body_vectors.is_empty() {
639            result = FnObj::new(head, body_vectors).into();
640        }
641        Ok(result)
642    }
643
644    /// 解析「主元」:当前 token 必须是多元关键字、或普通标识符 (atom)(内建 `StandardSet` 名走 atom 路径)。
645    fn parse_primary_obj(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
646        let tok = tb.current()?;
647
648        if tok == STRUCT_VIEW_PREFIX {
649            return self.parse_struct_view_obj(tb);
650        }
651        if tok == TEMPLATE_INSTANCE_PREFIX {
652            return self.parse_instantiated_template_obj(tb);
653        }
654        if tok == ABS {
655            tb.skip()?;
656            tb.skip_token(LEFT_BRACE)?;
657            let arg = self.parse_obj(tb)?;
658            tb.skip_token(RIGHT_BRACE)?;
659            return Ok(Abs::new(arg).into());
660        }
661        if tok == SQRT {
662            tb.skip()?;
663            tb.skip_token(LEFT_BRACE)?;
664            let arg = self.parse_obj(tb)?;
665            tb.skip_token(RIGHT_BRACE)?;
666            return Ok(Sqrt::new(arg).into());
667        }
668        if tok == MAX {
669            tb.skip()?;
670            let args = self.parse_braced_objs(tb)?;
671            if args.len() != 2 {
672                return Err(RuntimeError::from(ParseRuntimeError(
673                    RuntimeErrorStruct::new_with_msg_and_line_file(
674                        "max expects 2 arguments".to_string(),
675                        tb.line_file.clone(),
676                    ),
677                )));
678            }
679            let mut it = args.into_iter();
680            let left = it.next().ok_or_else(|| {
681                RuntimeError::from(ParseRuntimeError(
682                    RuntimeErrorStruct::new_with_msg_and_line_file(
683                        "max expects 2 arguments".to_string(),
684                        tb.line_file.clone(),
685                    ),
686                ))
687            })?;
688            let right = it.next().ok_or_else(|| {
689                RuntimeError::from(ParseRuntimeError(
690                    RuntimeErrorStruct::new_with_msg_and_line_file(
691                        "max expects 2 arguments".to_string(),
692                        tb.line_file.clone(),
693                    ),
694                ))
695            })?;
696            return Ok(Max::new(left, right).into());
697        }
698        if tok == MIN {
699            tb.skip()?;
700            let args = self.parse_braced_objs(tb)?;
701            if args.len() != 2 {
702                return Err(RuntimeError::from(ParseRuntimeError(
703                    RuntimeErrorStruct::new_with_msg_and_line_file(
704                        "min expects 2 arguments".to_string(),
705                        tb.line_file.clone(),
706                    ),
707                )));
708            }
709            let mut it = args.into_iter();
710            let left = it.next().ok_or_else(|| {
711                RuntimeError::from(ParseRuntimeError(
712                    RuntimeErrorStruct::new_with_msg_and_line_file(
713                        "min expects 2 arguments".to_string(),
714                        tb.line_file.clone(),
715                    ),
716                ))
717            })?;
718            let right = it.next().ok_or_else(|| {
719                RuntimeError::from(ParseRuntimeError(
720                    RuntimeErrorStruct::new_with_msg_and_line_file(
721                        "min expects 2 arguments".to_string(),
722                        tb.line_file.clone(),
723                    ),
724                ))
725            })?;
726            return Ok(Min::new(left, right).into());
727        }
728        if tok == LOG {
729            tb.skip()?;
730            let args = self.parse_braced_objs(tb)?;
731            if args.len() != 2 {
732                return Err(RuntimeError::from(ParseRuntimeError(
733                    RuntimeErrorStruct::new_with_msg_and_line_file(
734                        "log expects 2 arguments (base, argument)".to_string(),
735                        tb.line_file.clone(),
736                    ),
737                )));
738            }
739            let mut it = args.into_iter();
740            let base = it.next().ok_or_else(|| {
741                RuntimeError::from(ParseRuntimeError(
742                    RuntimeErrorStruct::new_with_msg_and_line_file(
743                        "log expects 2 arguments (base, argument)".to_string(),
744                        tb.line_file.clone(),
745                    ),
746                ))
747            })?;
748            let arg = it.next().ok_or_else(|| {
749                RuntimeError::from(ParseRuntimeError(
750                    RuntimeErrorStruct::new_with_msg_and_line_file(
751                        "log expects 2 arguments (base, argument)".to_string(),
752                        tb.line_file.clone(),
753                    ),
754                ))
755            })?;
756            return Ok(Log::new(base, arg).into());
757        }
758
759        // 多元关键字:吃关键字 + 括号里若干 obj
760        if tok == UNION {
761            tb.skip()?;
762            let args = self.parse_braced_objs(tb)?;
763            if args.len() != 2 {
764                return Err(RuntimeError::from(ParseRuntimeError(
765                    RuntimeErrorStruct::new_with_msg_and_line_file(
766                        "union expects 2 arguments".to_string(),
767                        tb.line_file.clone(),
768                    ),
769                )));
770            }
771            let mut it = args.into_iter();
772            let left = it.next().ok_or_else(|| {
773                RuntimeError::from(ParseRuntimeError(
774                    RuntimeErrorStruct::new_with_msg_and_line_file(
775                        "union expects 2 arguments".to_string(),
776                        tb.line_file.clone(),
777                    ),
778                ))
779            })?;
780            let right = it.next().ok_or_else(|| {
781                RuntimeError::from(ParseRuntimeError(
782                    RuntimeErrorStruct::new_with_msg_and_line_file(
783                        "union expects 2 arguments".to_string(),
784                        tb.line_file.clone(),
785                    ),
786                ))
787            })?;
788            return Ok(Union::new(left, right).into());
789        }
790        if tok == INTERSECT {
791            tb.skip()?;
792            let args = self.parse_braced_objs(tb)?;
793            if args.len() != 2 {
794                return Err(RuntimeError::from(ParseRuntimeError(
795                    RuntimeErrorStruct::new_with_msg_and_line_file(
796                        "intersect expects 2 arguments".to_string(),
797                        tb.line_file.clone(),
798                    ),
799                )));
800            }
801            let mut it = args.into_iter();
802            let left = it.next().ok_or_else(|| {
803                RuntimeError::from(ParseRuntimeError(
804                    RuntimeErrorStruct::new_with_msg_and_line_file(
805                        "intersect expects 2 arguments".to_string(),
806                        tb.line_file.clone(),
807                    ),
808                ))
809            })?;
810            let right = it.next().ok_or_else(|| {
811                RuntimeError::from(ParseRuntimeError(
812                    RuntimeErrorStruct::new_with_msg_and_line_file(
813                        "intersect expects 2 arguments".to_string(),
814                        tb.line_file.clone(),
815                    ),
816                ))
817            })?;
818            return Ok(Intersect::new(left, right).into());
819        }
820        if tok == SET_MINUS {
821            tb.skip()?;
822            let args = self.parse_braced_objs(tb)?;
823            if args.len() != 2 {
824                return Err(RuntimeError::from(ParseRuntimeError(
825                    RuntimeErrorStruct::new_with_msg_and_line_file(
826                        "set_minus expects 2 arguments".to_string(),
827                        tb.line_file.clone(),
828                    ),
829                )));
830            }
831            let mut it = args.into_iter();
832            let left = it.next().ok_or_else(|| {
833                RuntimeError::from(ParseRuntimeError(
834                    RuntimeErrorStruct::new_with_msg_and_line_file(
835                        "set_minus expects 2 arguments".to_string(),
836                        tb.line_file.clone(),
837                    ),
838                ))
839            })?;
840            let right = it.next().ok_or_else(|| {
841                RuntimeError::from(ParseRuntimeError(
842                    RuntimeErrorStruct::new_with_msg_and_line_file(
843                        "set_minus expects 2 arguments".to_string(),
844                        tb.line_file.clone(),
845                    ),
846                ))
847            })?;
848            return Ok(SetMinus::new(left, right).into());
849        }
850        if tok == SET_DIFF {
851            tb.skip()?;
852            let args = self.parse_braced_objs(tb)?;
853            if args.len() != 2 {
854                return Err(RuntimeError::from(ParseRuntimeError(
855                    RuntimeErrorStruct::new_with_msg_and_line_file(
856                        "disjoint_union expects 2 arguments".to_string(),
857                        tb.line_file.clone(),
858                    ),
859                )));
860            }
861            let mut it = args.into_iter();
862            let left = it.next().ok_or_else(|| {
863                RuntimeError::from(ParseRuntimeError(
864                    RuntimeErrorStruct::new_with_msg_and_line_file(
865                        "disjoint_union expects 2 arguments".to_string(),
866                        tb.line_file.clone(),
867                    ),
868                ))
869            })?;
870            let right = it.next().ok_or_else(|| {
871                RuntimeError::from(ParseRuntimeError(
872                    RuntimeErrorStruct::new_with_msg_and_line_file(
873                        "disjoint_union expects 2 arguments".to_string(),
874                        tb.line_file.clone(),
875                    ),
876                ))
877            })?;
878            return Ok(SetDiff::new(left, right).into());
879        }
880        if tok == CAP {
881            tb.skip()?;
882            let args = self.parse_braced_objs(tb)?;
883            if args.len() != 1 {
884                return Err(RuntimeError::from(ParseRuntimeError(
885                    RuntimeErrorStruct::new_with_msg_and_line_file(
886                        "cap expects 1 argument".to_string(),
887                        tb.line_file.clone(),
888                    ),
889                )));
890            }
891            let mut it = args.into_iter();
892            let value = it.next().ok_or_else(|| {
893                RuntimeError::from(ParseRuntimeError(
894                    RuntimeErrorStruct::new_with_msg_and_line_file(
895                        "cap expects 1 argument".to_string(),
896                        tb.line_file.clone(),
897                    ),
898                ))
899            })?;
900            return Ok(Cap::new(value).into());
901        }
902        if tok == CUP {
903            tb.skip()?;
904            let args = self.parse_braced_objs(tb)?;
905            if args.len() != 1 {
906                return Err(RuntimeError::from(ParseRuntimeError(
907                    RuntimeErrorStruct::new_with_msg_and_line_file(
908                        "cup expects 1 argument".to_string(),
909                        tb.line_file.clone(),
910                    ),
911                )));
912            }
913            let mut it = args.into_iter();
914            let value = it.next().ok_or_else(|| {
915                RuntimeError::from(ParseRuntimeError(
916                    RuntimeErrorStruct::new_with_msg_and_line_file(
917                        "cup expects 1 argument".to_string(),
918                        tb.line_file.clone(),
919                    ),
920                ))
921            })?;
922            return Ok(Cup::new(value).into());
923        }
924        if tok == CHOOSE {
925            tb.skip()?;
926            let args = self.parse_braced_objs(tb)?;
927            if args.len() != 1 {
928                return Err(RuntimeError::from(ParseRuntimeError(
929                    RuntimeErrorStruct::new_with_msg_and_line_file(
930                        "choice expects 1 argument".to_string(),
931                        tb.line_file.clone(),
932                    ),
933                )));
934            }
935            let mut it = args.into_iter();
936            let value = it.next().ok_or_else(|| {
937                RuntimeError::from(ParseRuntimeError(
938                    RuntimeErrorStruct::new_with_msg_and_line_file(
939                        "choice expects 1 argument".to_string(),
940                        tb.line_file.clone(),
941                    ),
942                ))
943            })?;
944            return Ok(Choose::new(value).into());
945        }
946        if tok == PROJ {
947            tb.skip()?;
948            let args = self.parse_braced_objs(tb)?;
949            if args.len() != 2 {
950                return Err(RuntimeError::from(ParseRuntimeError(
951                    RuntimeErrorStruct::new_with_msg_and_line_file(
952                        "proj expects 2 arguments".to_string(),
953                        tb.line_file.clone(),
954                    ),
955                )));
956            }
957            let mut it = args.into_iter();
958            let left = it.next().ok_or_else(|| {
959                RuntimeError::from(ParseRuntimeError(
960                    RuntimeErrorStruct::new_with_msg_and_line_file(
961                        "proj expects 2 arguments".to_string(),
962                        tb.line_file.clone(),
963                    ),
964                ))
965            })?;
966            let right = it.next().ok_or_else(|| {
967                RuntimeError::from(ParseRuntimeError(
968                    RuntimeErrorStruct::new_with_msg_and_line_file(
969                        "proj expects 2 arguments".to_string(),
970                        tb.line_file.clone(),
971                    ),
972                ))
973            })?;
974            return Ok(Proj::new(left, right).into());
975        }
976        if tok == RANGE {
977            tb.skip()?;
978            let args = self.parse_braced_objs(tb)?;
979            if args.len() != 2 {
980                return Err(RuntimeError::from(ParseRuntimeError(
981                    RuntimeErrorStruct::new_with_msg_and_line_file(
982                        "range expects 2 arguments".to_string(),
983                        tb.line_file.clone(),
984                    ),
985                )));
986            }
987            let mut it = args.into_iter();
988            let left = it.next().ok_or_else(|| {
989                RuntimeError::from(ParseRuntimeError(
990                    RuntimeErrorStruct::new_with_msg_and_line_file(
991                        "range expects 2 arguments".to_string(),
992                        tb.line_file.clone(),
993                    ),
994                ))
995            })?;
996            let right = it.next().ok_or_else(|| {
997                RuntimeError::from(ParseRuntimeError(
998                    RuntimeErrorStruct::new_with_msg_and_line_file(
999                        "range expects 2 arguments".to_string(),
1000                        tb.line_file.clone(),
1001                    ),
1002                ))
1003            })?;
1004            return Ok(Range::new(left, right).into());
1005        }
1006        if tok == CLOSED_RANGE {
1007            tb.skip()?;
1008            let args = self.parse_braced_objs(tb)?;
1009            if args.len() != 2 {
1010                return Err(RuntimeError::from(ParseRuntimeError(
1011                    RuntimeErrorStruct::new_with_msg_and_line_file(
1012                        "closed_range expects 2 arguments".to_string(),
1013                        tb.line_file.clone(),
1014                    ),
1015                )));
1016            }
1017            let mut it = args.into_iter();
1018            let left = it.next().ok_or_else(|| {
1019                RuntimeError::from(ParseRuntimeError(
1020                    RuntimeErrorStruct::new_with_msg_and_line_file(
1021                        "closed_range expects 2 arguments".to_string(),
1022                        tb.line_file.clone(),
1023                    ),
1024                ))
1025            })?;
1026            let right = it.next().ok_or_else(|| {
1027                RuntimeError::from(ParseRuntimeError(
1028                    RuntimeErrorStruct::new_with_msg_and_line_file(
1029                        "closed_range expects 2 arguments".to_string(),
1030                        tb.line_file.clone(),
1031                    ),
1032                ))
1033            })?;
1034            return Ok(ClosedRange::new(left, right).into());
1035        }
1036        if tok == FINITE_SEQ {
1037            tb.skip()?;
1038            let args = self.parse_braced_objs(tb)?;
1039            if args.len() != 2 {
1040                return Err(RuntimeError::from(ParseRuntimeError(
1041                    RuntimeErrorStruct::new_with_msg_and_line_file(
1042                        "finite_seq expects 2 arguments".to_string(),
1043                        tb.line_file.clone(),
1044                    ),
1045                )));
1046            }
1047            let mut it = args.into_iter();
1048            let set = it.next().ok_or_else(|| {
1049                RuntimeError::from(ParseRuntimeError(
1050                    RuntimeErrorStruct::new_with_msg_and_line_file(
1051                        "finite_seq expects 2 arguments".to_string(),
1052                        tb.line_file.clone(),
1053                    ),
1054                ))
1055            })?;
1056            let n = it.next().ok_or_else(|| {
1057                RuntimeError::from(ParseRuntimeError(
1058                    RuntimeErrorStruct::new_with_msg_and_line_file(
1059                        "finite_seq expects 2 arguments".to_string(),
1060                        tb.line_file.clone(),
1061                    ),
1062                ))
1063            })?;
1064            return Ok(FiniteSeqSet::new(set, n).into());
1065        }
1066        if tok == SEQ {
1067            tb.skip()?;
1068            let args = self.parse_braced_objs(tb)?;
1069            if args.len() != 1 {
1070                return Err(RuntimeError::from(ParseRuntimeError(
1071                    RuntimeErrorStruct::new_with_msg_and_line_file(
1072                        "seq expects 1 argument".to_string(),
1073                        tb.line_file.clone(),
1074                    ),
1075                )));
1076            }
1077            let set = args.into_iter().next().ok_or_else(|| {
1078                RuntimeError::from(ParseRuntimeError(
1079                    RuntimeErrorStruct::new_with_msg_and_line_file(
1080                        "seq expects 1 argument".to_string(),
1081                        tb.line_file.clone(),
1082                    ),
1083                ))
1084            })?;
1085            return Ok(SeqSet::new(set).into());
1086        }
1087        if tok == MATRIX {
1088            tb.skip()?;
1089            let args = self.parse_braced_objs(tb)?;
1090            if args.len() != 3 {
1091                return Err(RuntimeError::from(ParseRuntimeError(
1092                    RuntimeErrorStruct::new_with_msg_and_line_file(
1093                        "matrix expects 3 arguments".to_string(),
1094                        tb.line_file.clone(),
1095                    ),
1096                )));
1097            }
1098            let mut it = args.into_iter();
1099            let set = it.next().ok_or_else(|| {
1100                RuntimeError::from(ParseRuntimeError(
1101                    RuntimeErrorStruct::new_with_msg_and_line_file(
1102                        "matrix expects 3 arguments".to_string(),
1103                        tb.line_file.clone(),
1104                    ),
1105                ))
1106            })?;
1107            let row_len = it.next().ok_or_else(|| {
1108                RuntimeError::from(ParseRuntimeError(
1109                    RuntimeErrorStruct::new_with_msg_and_line_file(
1110                        "matrix expects 3 arguments".to_string(),
1111                        tb.line_file.clone(),
1112                    ),
1113                ))
1114            })?;
1115            let col_len = it.next().ok_or_else(|| {
1116                RuntimeError::from(ParseRuntimeError(
1117                    RuntimeErrorStruct::new_with_msg_and_line_file(
1118                        "matrix expects 3 arguments".to_string(),
1119                        tb.line_file.clone(),
1120                    ),
1121                ))
1122            })?;
1123            return Ok(MatrixSet::new(set, row_len, col_len).into());
1124        }
1125
1126        if tok == CUP {
1127            tb.skip()?;
1128            let args = self.parse_braced_objs(tb)?;
1129            if args.len() != 1 {
1130                return Err(RuntimeError::from(ParseRuntimeError(
1131                    RuntimeErrorStruct::new_with_msg_and_line_file(
1132                        "cup expects 1 argument".to_string(),
1133                        tb.line_file.clone(),
1134                    ),
1135                )));
1136            }
1137            let mut it = args.into_iter();
1138            let value = it.next().ok_or_else(|| {
1139                RuntimeError::from(ParseRuntimeError(
1140                    RuntimeErrorStruct::new_with_msg_and_line_file(
1141                        "cup expects 1 argument".to_string(),
1142                        tb.line_file.clone(),
1143                    ),
1144                ))
1145            })?;
1146            return Ok(Cup::new(value).into());
1147        }
1148        if tok == POWER_SET {
1149            tb.skip()?;
1150            let args = self.parse_braced_objs(tb)?;
1151            if args.len() != 1 {
1152                return Err(RuntimeError::from(ParseRuntimeError(
1153                    RuntimeErrorStruct::new_with_msg_and_line_file(
1154                        "power_set expects 1 argument".to_string(),
1155                        tb.line_file.clone(),
1156                    ),
1157                )));
1158            }
1159            let mut it = args.into_iter();
1160            let value = it.next().ok_or_else(|| {
1161                RuntimeError::from(ParseRuntimeError(
1162                    RuntimeErrorStruct::new_with_msg_and_line_file(
1163                        "power_set expects 1 argument".to_string(),
1164                        tb.line_file.clone(),
1165                    ),
1166                ))
1167            })?;
1168            return Ok(PowerSet::new(value).into());
1169        }
1170        if tok == CART_DIM {
1171            tb.skip()?;
1172            let args = self.parse_braced_objs(tb)?;
1173            if args.len() != 1 {
1174                return Err(RuntimeError::from(ParseRuntimeError(
1175                    RuntimeErrorStruct::new_with_msg_and_line_file(
1176                        "set_dim expects 1 argument".to_string(),
1177                        tb.line_file.clone(),
1178                    ),
1179                )));
1180            }
1181            let mut it = args.into_iter();
1182            let value = it.next().ok_or_else(|| {
1183                RuntimeError::from(ParseRuntimeError(
1184                    RuntimeErrorStruct::new_with_msg_and_line_file(
1185                        "set_dim expects 1 argument".to_string(),
1186                        tb.line_file.clone(),
1187                    ),
1188                ))
1189            })?;
1190            return Ok(CartDim::new(value).into());
1191        }
1192        if tok == COUNT {
1193            tb.skip()?;
1194            let args = self.parse_braced_objs(tb)?;
1195            if args.len() != 1 {
1196                return Err(RuntimeError::from(ParseRuntimeError(
1197                    RuntimeErrorStruct::new_with_msg_and_line_file(
1198                        "count expects 1 argument".to_string(),
1199                        tb.line_file.clone(),
1200                    ),
1201                )));
1202            }
1203            let mut it = args.into_iter();
1204            let value = it.next().ok_or_else(|| {
1205                RuntimeError::from(ParseRuntimeError(
1206                    RuntimeErrorStruct::new_with_msg_and_line_file(
1207                        "count expects 1 argument".to_string(),
1208                        tb.line_file.clone(),
1209                    ),
1210                ))
1211            })?;
1212            return Ok(Count::new(value).into());
1213        }
1214        if tok == SUM {
1215            tb.skip()?;
1216            let args = self.parse_braced_objs(tb)?;
1217            if args.len() != 3 {
1218                return Err(RuntimeError::from(ParseRuntimeError(
1219                    RuntimeErrorStruct::new_with_msg_and_line_file(
1220                        "sum expects 3 arguments (start, end, function)".to_string(),
1221                        tb.line_file.clone(),
1222                    ),
1223                )));
1224            }
1225            let mut it = args.into_iter();
1226            let start = it.next().ok_or_else(|| {
1227                RuntimeError::from(ParseRuntimeError(
1228                    RuntimeErrorStruct::new_with_msg_and_line_file(
1229                        "sum expects 3 arguments (start, end, function)".to_string(),
1230                        tb.line_file.clone(),
1231                    ),
1232                ))
1233            })?;
1234            let end = it.next().ok_or_else(|| {
1235                RuntimeError::from(ParseRuntimeError(
1236                    RuntimeErrorStruct::new_with_msg_and_line_file(
1237                        "sum expects 3 arguments (start, end, function)".to_string(),
1238                        tb.line_file.clone(),
1239                    ),
1240                ))
1241            })?;
1242            let func = it.next().ok_or_else(|| {
1243                RuntimeError::from(ParseRuntimeError(
1244                    RuntimeErrorStruct::new_with_msg_and_line_file(
1245                        "sum expects 3 arguments (start, end, function)".to_string(),
1246                        tb.line_file.clone(),
1247                    ),
1248                ))
1249            })?;
1250            return Ok(Sum::new(start, end, func).into());
1251        }
1252        if tok == PRODUCT {
1253            tb.skip()?;
1254            let args = self.parse_braced_objs(tb)?;
1255            if args.len() != 3 {
1256                return Err(RuntimeError::from(ParseRuntimeError(
1257                    RuntimeErrorStruct::new_with_msg_and_line_file(
1258                        "product expects 3 arguments (start, end, function)".to_string(),
1259                        tb.line_file.clone(),
1260                    ),
1261                )));
1262            }
1263            let mut it = args.into_iter();
1264            let start = it.next().ok_or_else(|| {
1265                RuntimeError::from(ParseRuntimeError(
1266                    RuntimeErrorStruct::new_with_msg_and_line_file(
1267                        "product expects 3 arguments (start, end, function)".to_string(),
1268                        tb.line_file.clone(),
1269                    ),
1270                ))
1271            })?;
1272            let end = it.next().ok_or_else(|| {
1273                RuntimeError::from(ParseRuntimeError(
1274                    RuntimeErrorStruct::new_with_msg_and_line_file(
1275                        "product expects 3 arguments (start, end, function)".to_string(),
1276                        tb.line_file.clone(),
1277                    ),
1278                ))
1279            })?;
1280            let func = it.next().ok_or_else(|| {
1281                RuntimeError::from(ParseRuntimeError(
1282                    RuntimeErrorStruct::new_with_msg_and_line_file(
1283                        "product expects 3 arguments (start, end, function)".to_string(),
1284                        tb.line_file.clone(),
1285                    ),
1286                ))
1287            })?;
1288            return Ok(Product::new(start, end, func).into());
1289        }
1290        if tok == CART {
1291            tb.skip()?;
1292            let args = self.parse_braced_objs(tb)?;
1293            if args.len() < 2 {
1294                return Err(RuntimeError::from(ParseRuntimeError(
1295                    RuntimeErrorStruct::new_with_msg_and_line_file(
1296                        "cart expects at least 2 arguments".to_string(),
1297                        tb.line_file.clone(),
1298                    ),
1299                )));
1300            }
1301            return Ok(Cart::new(args).into());
1302        }
1303
1304        if tok == TUPLE_DIM {
1305            tb.skip()?;
1306            let args = self.parse_braced_obj(tb)?;
1307            return Ok(TupleDim::new(args).into());
1308        }
1309
1310        if tok == CART_DIM {
1311            tb.skip()?;
1312            let args = self.parse_braced_obj(tb)?;
1313            return Ok(CartDim::new(args).into());
1314        }
1315
1316        // Bare `ident` or `mod::ident`: built-in single-token `StandardSet` names, else free params.
1317        self.parse_and_reclassify_atom_as_free_param_obj(tb)
1318    }
1319
1320    // parse_identifier_or_identifier_with_mod + reclassify (std sets + free params).
1321    fn parse_and_reclassify_atom_as_free_param_obj(
1322        &mut self,
1323        tb: &mut TokenBlock,
1324    ) -> Result<Obj, RuntimeError> {
1325        let atom = self.parse_identifier_or_identifier_with_mod(tb)?;
1326        self.reclassify_atom_as_free_param_obj(atom)
1327    }
1328
1329    fn reclassify_atom_as_free_param_obj(&self, obj: Obj) -> Result<Obj, RuntimeError> {
1330        match obj {
1331            Obj::Atom(AtomObj::Identifier(id)) => {
1332                if let Some(standard) = standard_set_from_bare_identifier_name(&id.name) {
1333                    return Ok(standard);
1334                }
1335                Ok(self
1336                    .parsing_free_param_collection
1337                    .resolve_identifier_to_free_param_obj(&id.name))
1338            }
1339            Obj::Atom(AtomObj::IdentifierWithMod(m)) => {
1340                Ok(Obj::Atom(AtomObj::IdentifierWithMod(m)))
1341            }
1342            _ => Err(RuntimeError::from(ParseRuntimeError(
1343                RuntimeErrorStruct::new_with_just_msg(
1344                    "internal: atom position was not a name form".to_string(),
1345                ),
1346            ))),
1347        }
1348    }
1349
1350    pub fn parse_braced_objs(&mut self, tb: &mut TokenBlock) -> Result<Vec<Obj>, RuntimeError> {
1351        tb.skip_token(LEFT_BRACE)?;
1352        if tb.current_token_is_equal_to(RIGHT_BRACE) {
1353            tb.skip_token(RIGHT_BRACE)?;
1354            return Ok(vec![]);
1355        }
1356        let mut objs = vec![self.parse_obj(tb)?];
1357        while tb.current_token_is_equal_to(COMMA) {
1358            tb.skip_token(COMMA)?;
1359            objs.push(self.parse_obj(tb)?);
1360        }
1361        tb.skip_token(RIGHT_BRACE)?;
1362        Ok(objs)
1363    }
1364
1365    fn parse_fn_obj_arg_group(&mut self, tb: &mut TokenBlock) -> Result<Vec<Obj>, RuntimeError> {
1366        let args = self.parse_braced_objs(tb)?;
1367        if args.is_empty() {
1368            return Err(RuntimeError::from(ParseRuntimeError(
1369                RuntimeErrorStruct::new_with_msg_and_line_file(
1370                    "function application expects at least one argument".to_string(),
1371                    tb.line_file.clone(),
1372                ),
1373            )));
1374        }
1375        Ok(args)
1376    }
1377
1378    pub fn parse_braced_obj(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1379        let mut parsed_args = self.parse_braced_objs(tb)?;
1380        if parsed_args.len() != 1 {
1381            return Err(RuntimeError::from(ParseRuntimeError(
1382                RuntimeErrorStruct::new_with_msg_and_line_file(
1383                    "expected exactly 1 argument".to_string(),
1384                    tb.line_file.clone(),
1385                ),
1386            )));
1387        }
1388        let parsed_obj = parsed_args.remove(0);
1389        Ok(parsed_obj)
1390    }
1391
1392    /// 解析逗号分隔的 obj 列表,直到遇到非 COMMA 的 token(如 COLON)。
1393    pub fn parse_obj_list(&mut self, tb: &mut TokenBlock) -> Result<Vec<Obj>, RuntimeError> {
1394        let mut objs = vec![self.parse_obj(tb)?];
1395        while tb.current_token_is_equal_to(COMMA) {
1396            tb.skip_token(COMMA)?;
1397            objs.push(self.parse_obj(tb)?);
1398        }
1399        Ok(objs)
1400    }
1401
1402    fn parse_set_builder_or_set_list(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1403        tb.skip_token(LEFT_CURLY_BRACE)?;
1404        if tb.current_token_is_equal_to(RIGHT_CURLY_BRACE) {
1405            tb.skip_token(RIGHT_CURLY_BRACE)?;
1406            return Ok(ListSet::new(vec![]).into());
1407        }
1408
1409        let left = self.parse_obj(tb)?;
1410        // Plain identifiers and parsing-time free-param atoms (e.g. forall-bound `x`) must both
1411        // allow `{ x S : ... }` set-builder syntax; only `Identifier` was handled originally.
1412        let name_for_set_builder = match &left {
1413            Obj::Atom(AtomObj::Identifier(a)) => Some(a.name.as_str()),
1414            Obj::Atom(AtomObj::IdentifierWithMod(m)) => Some(m.name.as_str()),
1415            Obj::Atom(AtomObj::Forall(p)) => Some(p.name.as_str()),
1416            Obj::Atom(AtomObj::Def(p)) => Some(p.name.as_str()),
1417            Obj::Atom(AtomObj::Exist(p)) => Some(p.name.as_str()),
1418            Obj::Atom(AtomObj::SetBuilder(p)) => Some(p.name.as_str()),
1419            Obj::Atom(AtomObj::FnSet(p)) => Some(p.name.as_str()),
1420            Obj::Atom(AtomObj::Induc(p)) => Some(p.name.as_str()),
1421            Obj::Atom(AtomObj::DefAlgo(p)) => Some(p.name.as_str()),
1422            _ => None,
1423        };
1424        if let Some(name) = name_for_set_builder {
1425            if tb.current_token_is_equal_to(COMMA) || tb.current()? == RIGHT_CURLY_BRACE {
1426                self.parse_list_set_obj_with_leftmost_obj(tb, left)
1427            } else {
1428                self.parse_set_builder(tb, Identifier::new(name.to_string()))
1429            }
1430        } else {
1431            self.parse_list_set_obj_with_leftmost_obj(tb, left)
1432        }
1433    }
1434
1435    fn parse_instantiated_template_obj(
1436        &mut self,
1437        tb: &mut TokenBlock,
1438    ) -> Result<Obj, RuntimeError> {
1439        tb.skip_token(TEMPLATE_INSTANCE_PREFIX)?;
1440        let template_name = tb.advance()?;
1441        is_valid_litex_name(&template_name).map_err(|msg| {
1442            RuntimeError::from(ParseRuntimeError(
1443                RuntimeErrorStruct::new_with_msg_and_line_file(msg, tb.line_file.clone()),
1444            ))
1445        })?;
1446        tb.skip_token(LEFT_CURLY_BRACE)?;
1447        let mut args = Vec::new();
1448        if !tb.current_token_is_equal_to(RIGHT_CURLY_BRACE) {
1449            args.push(self.parse_obj(tb)?);
1450            while tb.current_token_is_equal_to(COMMA) {
1451                tb.skip_token(COMMA)?;
1452                args.push(self.parse_obj(tb)?);
1453            }
1454        }
1455        tb.skip_token(RIGHT_CURLY_BRACE)?;
1456        Ok(InstantiatedTemplateObj::new(template_name, args).into())
1457    }
1458
1459    /// Parse set builder or list set after the first identifier; wraps body in a name block for the bound variable.
1460    fn parse_set_builder(
1461        &mut self,
1462        tb: &mut TokenBlock,
1463        a: Identifier,
1464    ) -> Result<Obj, RuntimeError> {
1465        self.run_in_local_parsing_time_name_scope(|this| {
1466            let set_builder_param = [a.name.clone()];
1467            this.parsing_free_param_collection.begin_scope(
1468                ParamObjType::SetBuilder,
1469                &set_builder_param,
1470                tb.line_file.clone(),
1471            )?;
1472            let parsed = (|| -> Result<Obj, RuntimeError> {
1473                let second = this.parse_obj(tb)?;
1474                if tb.current()? == COLON {
1475                    tb.skip_token(COLON)?;
1476
1477                    let user_names = vec![a.name.clone()];
1478                    this.validate_user_fn_param_names_for_parse(&user_names, tb.line_file.clone())?;
1479                    let empty: HashMap<String, Obj> = HashMap::new();
1480                    let second_inst = this.inst_obj(&second, &empty, ParamObjType::SetBuilder)?;
1481
1482                    let mut facts_inst = Vec::new();
1483                    while tb.current()? != RIGHT_CURLY_BRACE {
1484                        let f = this.parse_or_and_chain_atomic_fact(tb)?;
1485                        facts_inst.push(this.inst_or_and_chain_atomic_fact(
1486                            &f,
1487                            &empty,
1488                            ParamObjType::SetBuilder,
1489                            None,
1490                        )?);
1491                    }
1492                    tb.skip_token(RIGHT_CURLY_BRACE)?;
1493
1494                    Ok(SetBuilder::new(a.name.clone(), second_inst, facts_inst)?.into())
1495                } else {
1496                    Err(RuntimeError::from(ParseRuntimeError(
1497                        RuntimeErrorStruct::new_with_msg_and_line_file(
1498                            "expected colon after first argument".to_string(),
1499                            tb.line_file.clone(),
1500                        ),
1501                    )))
1502                }
1503            })();
1504            this.parsing_free_param_collection
1505                .end_scope(ParamObjType::SetBuilder, &set_builder_param);
1506            parsed
1507        })
1508    }
1509
1510    /// ListSet: { a b c } 或 { 1, 0, 2 };遇逗号先 skip 再解析下一项
1511    fn parse_list_set_obj_with_leftmost_obj(
1512        &mut self,
1513        tb: &mut TokenBlock,
1514        left_most_obj: Obj,
1515    ) -> Result<Obj, RuntimeError> {
1516        let mut objs = vec![left_most_obj];
1517        while tb.current()? != RIGHT_CURLY_BRACE {
1518            if tb.current_token_is_equal_to(COMMA) {
1519                tb.skip_token(COMMA)?;
1520            }
1521            objs.push(self.parse_obj(tb)?);
1522        }
1523        tb.skip_token(RIGHT_CURLY_BRACE)?;
1524        Ok(ListSet::new(objs).into())
1525    }
1526
1527    pub fn parse_list_set_obj(&mut self, tb: &mut TokenBlock) -> Result<ListSet, RuntimeError> {
1528        let mut objs = vec![];
1529        tb.skip_token(LEFT_CURLY_BRACE)?;
1530        while tb.current()? != RIGHT_CURLY_BRACE {
1531            objs.push(self.parse_obj(tb)?);
1532            if tb.current_token_is_equal_to(COMMA) {
1533                tb.skip_token(COMMA)?;
1534            }
1535        }
1536        tb.skip_token(RIGHT_CURLY_BRACE)?;
1537        Ok(ListSet::new(objs))
1538    }
1539
1540    pub fn parse_identifier(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1541        let left = parse_synthetically_correct_identifier_string(tb)?;
1542        Ok(Identifier::new(left).into())
1543    }
1544
1545    fn parse_mod_qualified_atom(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1546        let left = parse_synthetically_correct_identifier_string(tb)?;
1547        tb.skip_token(MOD_SIGN)?;
1548        let right = parse_synthetically_correct_identifier_string(tb)?;
1549        if !tb.exceed_end_of_head() && tb.current()? == DOT_AKA_FIELD_ACCESS_SIGN {
1550            return Err(RuntimeError::from(ParseRuntimeError(
1551                RuntimeErrorStruct::new_with_msg_and_line_file(
1552                    "unexpected `.` after module-qualified name".to_string(),
1553                    tb.line_file.clone(),
1554                ),
1555            )));
1556        }
1557        Ok(IdentifierWithMod::new(left, right).into())
1558    }
1559
1560    /// Unqualified or `::`-qualified name / field name; returns a name-shaped [`Obj`].
1561    pub fn parse_identifier_or_identifier_with_mod(
1562        &mut self,
1563        tb: &mut TokenBlock,
1564    ) -> Result<Obj, RuntimeError> {
1565        let next_is_mod = tb.token_at_add_index(1) == MOD_SIGN;
1566        if next_is_mod {
1567            self.parse_mod_qualified_atom(tb)
1568        } else {
1569            self.parse_identifier(tb)
1570        }
1571    }
1572
1573    pub fn parse_predicate(&mut self, tb: &mut TokenBlock) -> Result<AtomicName, RuntimeError> {
1574        self.parse_atomic_name(tb)
1575    }
1576
1577    pub fn parse_struct_view_obj(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1578        tb.skip_token(STRUCT_VIEW_PREFIX)?;
1579        let name = self.parse_name_with_or_without_mod(tb)?;
1580        let params = if !tb.exceed_end_of_head() && tb.current()? == LEFT_BRACE {
1581            self.parse_braced_objs(tb)?
1582        } else {
1583            vec![]
1584        };
1585        let struct_obj = StructObj::new(name, params);
1586
1587        if tb.exceed_end_of_head() || tb.current()? != LEFT_CURLY_BRACE {
1588            return Ok(struct_obj.into());
1589        }
1590
1591        tb.skip_token(LEFT_CURLY_BRACE)?;
1592        let obj = self.parse_obj(tb)?;
1593        tb.skip_token(RIGHT_CURLY_BRACE)?;
1594        tb.skip_token(DOT_AKA_FIELD_ACCESS_SIGN)?;
1595        let field_name = parse_synthetically_correct_identifier_string(tb)?;
1596        Ok(ObjAsStructInstanceWithFieldAccess::new(struct_obj, obj, field_name).into())
1597    }
1598
1599    fn parse_name_with_or_without_mod(
1600        &mut self,
1601        tb: &mut TokenBlock,
1602    ) -> Result<NameWithOrWithoutMod, RuntimeError> {
1603        let name = self.parse_atomic_name(tb)?;
1604        Ok(match name {
1605            AtomicName::WithoutMod(name) => NameWithOrWithoutMod::WithoutMod(name),
1606            AtomicName::WithMod(mod_name, name) => NameWithOrWithoutMod::WithMod(mod_name, name),
1607        })
1608    }
1609
1610    /// `ident` or `mod::ident` as a predicate/atomic name in parse position.
1611    pub fn parse_atomic_name(&mut self, tb: &mut TokenBlock) -> Result<AtomicName, RuntimeError> {
1612        let left = parse_synthetically_correct_identifier_string(tb)?;
1613        if !tb.exceed_end_of_head() && tb.current()? == MOD_SIGN {
1614            tb.skip()?;
1615            let right = parse_synthetically_correct_identifier_string(tb)?;
1616            Ok(AtomicName::WithMod(left, right))
1617        } else {
1618            Ok(AtomicName::WithoutMod(left))
1619        }
1620    }
1621}
1622
1623fn starts_with_digit(s: &str) -> bool {
1624    s.chars()
1625        .next()
1626        .map(|c| c.is_ascii_digit())
1627        .unwrap_or(false)
1628}
1629
1630fn minus_token_is_standalone_operator_obj(tb: &TokenBlock) -> bool {
1631    let next = tb.token_at_add_index(1);
1632    next == FACT_PREFIX
1633        || next == EQUAL
1634        || next == NOT_EQUAL
1635        || next == LESS
1636        || next == GREATER
1637        || next == LESS_EQUAL
1638        || next == GREATER_EQUAL
1639}
1640
1641fn is_number(s: &str) -> bool {
1642    if s.is_empty() {
1643        return false;
1644    }
1645
1646    let mut dot_count = 0;
1647
1648    for c in s.chars() {
1649        if c == '.' {
1650            dot_count += 1;
1651            if dot_count > 1 {
1652                return false;
1653            }
1654        } else if !c.is_ascii_digit() {
1655            return false;
1656        }
1657    }
1658
1659    s != "."
1660}
1661
1662enum FnSetOrFnSetClause {
1663    FnSet(FnSet),
1664    FnSetClause(FnSetClause),
1665}
1666
1667fn parse_synthetically_correct_identifier_string(
1668    tb: &mut TokenBlock,
1669) -> Result<String, RuntimeError> {
1670    let cur = tb.advance()?;
1671
1672    if cur == SET || cur == NONEMPTY_SET || cur == FINITE_SET {
1673        return Err(RuntimeError::from(ParseRuntimeError(
1674            RuntimeErrorStruct::new_with_msg_and_line_file(
1675                format!("{} is not a valid identifier", cur),
1676                tb.line_file.clone(),
1677            ),
1678        )));
1679    }
1680
1681    Ok(cur)
1682}
1683
1684// Maps a built-in one-token standard-set symbol to Obj::StandardSet; see reclassify_atom_as_free_param_obj.
1685fn standard_set_from_bare_identifier_name(name: &str) -> Option<Obj> {
1686    match name {
1687        N_POS => Some(StandardSet::NPos.into()),
1688        N => Some(StandardSet::N.into()),
1689        Q => Some(StandardSet::Q.into()),
1690        Z => Some(StandardSet::Z.into()),
1691        R => Some(StandardSet::R.into()),
1692        Q_POS => Some(StandardSet::QPos.into()),
1693        R_POS => Some(StandardSet::RPos.into()),
1694        Q_NEG => Some(StandardSet::QNeg.into()),
1695        Z_NEG => Some(StandardSet::ZNeg.into()),
1696        R_NEG => Some(StandardSet::RNeg.into()),
1697        Q_NZ => Some(StandardSet::QNz.into()),
1698        Z_NZ => Some(StandardSet::ZNz.into()),
1699        R_NZ => Some(StandardSet::RNz.into()),
1700        _ => None,
1701    }
1702}