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