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 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()?; 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 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 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 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)?; 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 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 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 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_braced_objs(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 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 ¤t_params,
260 tb.line_file.clone(),
261 )?;
262
263 let set = if tb.current_token_is_equal_to(COLON) {
264 StandardSet::R.into()
265 } else {
266 this.parse_obj(tb)?
267 };
268
269 params_def_with_set.push(ParamGroupWithSet::new(current_params, set));
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(¶ms_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(¶m_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 ¤t_params,
357 tb.line_file.clone(),
358 )?;
359
360 let set = this.parse_obj(tb)?;
361
362 params_def_with_set.push(ParamGroupWithSet::new(current_params, set));
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(¶ms_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 set = this.parse_obj(tb)?;
430
431 params_def_with_set.push(ParamGroupWithSet::new(current_params, set));
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(¶ms_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 tb.skip()?;
493 let obj = self.parse_number_or_primary_obj_or_fn_obj(tb)?;
494 Ok(Mul::new(Number::new("-1".to_string()).into(), obj).into())
495 } else {
496 self.parse_number_or_primary_obj_or_fn_obj(tb)
497 }
498 }
499
500 fn parse_number_or_primary_obj_or_fn_obj(
502 &mut self,
503 tb: &mut TokenBlock,
504 ) -> Result<Obj, RuntimeError> {
505 let token = tb.current()?;
506
507 if token == LEFT_BRACE {
509 tb.skip()?;
510 let obj = self.parse_obj(tb)?;
511
512 if tb.current_token_is_equal_to(COMMA) {
513 let mut args = vec![obj];
514 while tb.current_token_is_equal_to(COMMA) {
515 tb.skip_token(COMMA)?;
516
517 args.push(self.parse_obj(tb)?);
518 }
519 tb.skip_token(RIGHT_BRACE)?;
520 return Ok(Tuple::new(args).into());
521 } else {
522 tb.skip_token(RIGHT_BRACE)?;
523 return Ok(obj);
524 }
525 }
526
527 if starts_with_digit(token) {
529 let number = tb.advance()?;
530 if tb.exceed_end_of_head() {
532 if !is_number(&number) {
533 return Err(RuntimeError::from(ParseRuntimeError(
534 RuntimeErrorStruct::new_with_msg_and_line_file(
535 format!("Invalid number: {}", number),
536 tb.line_file.clone(),
537 ),
538 )));
539 }
540 return Ok(Number::new(number).into());
541 }
542
543 if tb.current()? == DOT_AKA_FIELD_ACCESS_SIGN {
544 tb.skip()?;
545 let fraction = tb.advance()?;
546 let number = format!("{}{}{}", number, DOT_AKA_FIELD_ACCESS_SIGN, fraction);
547 if !is_number(&number) {
548 return Err(RuntimeError::from(ParseRuntimeError(
549 RuntimeErrorStruct::new_with_msg_and_line_file(
550 format!("Invalid number: {}", number),
551 tb.line_file.clone(),
552 ),
553 )));
554 }
555 return Ok(Number::new(number).into());
556 } else {
557 if !is_number(&number) {
558 return Err(RuntimeError::from(ParseRuntimeError(
559 RuntimeErrorStruct::new_with_msg_and_line_file(
560 format!("Invalid number: {}", number),
561 tb.line_file.clone(),
562 ),
563 )));
564 }
565 return Ok(Number::new(number).into());
566 }
567 }
568
569 let mut result = self.parse_primary_obj(tb)?;
571
572 let (head, mut body_vectors) = match &result {
574 Obj::Atom(AtomObj::Identifier(i)) => (FnObjHead::Identifier(i.clone()), vec![]),
575 Obj::Atom(AtomObj::IdentifierWithMod(m)) => {
576 (FnObjHead::IdentifierWithMod(m.clone()), vec![])
577 }
578 Obj::Atom(AtomObj::Forall(p)) => (FnObjHead::Forall(p.clone()), vec![]),
579 Obj::Atom(AtomObj::Exist(p)) => (FnObjHead::Exist(p.clone()), vec![]),
580 Obj::Atom(AtomObj::Def(p)) => (FnObjHead::DefHeader(p.clone()), vec![]),
581 Obj::Atom(AtomObj::SetBuilder(p)) => (FnObjHead::SetBuilder(p.clone()), vec![]),
582 Obj::Atom(AtomObj::FnSet(p)) => (FnObjHead::FnSet(p.clone()), vec![]),
583 Obj::Atom(AtomObj::Induc(p)) => (FnObjHead::Induc(p.clone()), vec![]),
584 Obj::Atom(AtomObj::DefAlgo(p)) => (FnObjHead::DefAlgo(p.clone()), vec![]),
585 Obj::AnonymousFn(anon) => (
586 FnObjHead::AnonymousFnLiteral(Box::new(anon.clone())),
587 vec![],
588 ),
589 _ => return Ok(result),
590 };
591 while !tb.exceed_end_of_head() && tb.current()? == LEFT_BRACE {
592 let args = self.parse_braced_objs(tb)?;
593 let group: Vec<Box<Obj>> = args.into_iter().map(Box::new).collect();
594 body_vectors.push(group);
595 }
596 if !body_vectors.is_empty() {
597 result = FnObj::new(head, body_vectors).into();
598 }
599 Ok(result)
600 }
601
602 fn parse_primary_obj(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
604 let tok = tb.current()?;
605
606 if tok == FAMILY_OBJ_PREFIX {
607 let family = self.parse_family_obj(tb)?;
608 return Ok(Obj::FamilyObj(family));
609 }
610 if tok == ABS {
611 tb.skip()?;
612 tb.skip_token(LEFT_BRACE)?;
613 let arg = self.parse_obj(tb)?;
614 tb.skip_token(RIGHT_BRACE)?;
615 return Ok(Abs::new(arg).into());
616 }
617 if tok == MAX {
618 tb.skip()?;
619 let args = self.parse_braced_objs(tb)?;
620 if args.len() != 2 {
621 return Err(RuntimeError::from(ParseRuntimeError(
622 RuntimeErrorStruct::new_with_msg_and_line_file(
623 "max expects 2 arguments".to_string(),
624 tb.line_file.clone(),
625 ),
626 )));
627 }
628 let mut it = args.into_iter();
629 let left = it.next().ok_or_else(|| {
630 RuntimeError::from(ParseRuntimeError(
631 RuntimeErrorStruct::new_with_msg_and_line_file(
632 "max expects 2 arguments".to_string(),
633 tb.line_file.clone(),
634 ),
635 ))
636 })?;
637 let right = 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 return Ok(Max::new(left, right).into());
646 }
647 if tok == MIN {
648 tb.skip()?;
649 let args = self.parse_braced_objs(tb)?;
650 if args.len() != 2 {
651 return Err(RuntimeError::from(ParseRuntimeError(
652 RuntimeErrorStruct::new_with_msg_and_line_file(
653 "min expects 2 arguments".to_string(),
654 tb.line_file.clone(),
655 ),
656 )));
657 }
658 let mut it = args.into_iter();
659 let left = it.next().ok_or_else(|| {
660 RuntimeError::from(ParseRuntimeError(
661 RuntimeErrorStruct::new_with_msg_and_line_file(
662 "min expects 2 arguments".to_string(),
663 tb.line_file.clone(),
664 ),
665 ))
666 })?;
667 let right = 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 return Ok(Min::new(left, right).into());
676 }
677 if tok == LOG {
678 tb.skip()?;
679 let args = self.parse_braced_objs(tb)?;
680 if args.len() != 2 {
681 return Err(RuntimeError::from(ParseRuntimeError(
682 RuntimeErrorStruct::new_with_msg_and_line_file(
683 "log expects 2 arguments (base, argument)".to_string(),
684 tb.line_file.clone(),
685 ),
686 )));
687 }
688 let mut it = args.into_iter();
689 let base = it.next().ok_or_else(|| {
690 RuntimeError::from(ParseRuntimeError(
691 RuntimeErrorStruct::new_with_msg_and_line_file(
692 "log expects 2 arguments (base, argument)".to_string(),
693 tb.line_file.clone(),
694 ),
695 ))
696 })?;
697 let arg = 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 return Ok(Log::new(base, arg).into());
706 }
707
708 if tok == UNION {
710 tb.skip()?;
711 let args = self.parse_braced_objs(tb)?;
712 if args.len() != 2 {
713 return Err(RuntimeError::from(ParseRuntimeError(
714 RuntimeErrorStruct::new_with_msg_and_line_file(
715 "union expects 2 arguments".to_string(),
716 tb.line_file.clone(),
717 ),
718 )));
719 }
720 let mut it = args.into_iter();
721 let left = it.next().ok_or_else(|| {
722 RuntimeError::from(ParseRuntimeError(
723 RuntimeErrorStruct::new_with_msg_and_line_file(
724 "union expects 2 arguments".to_string(),
725 tb.line_file.clone(),
726 ),
727 ))
728 })?;
729 let right = 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 return Ok(Union::new(left, right).into());
738 }
739 if tok == INTERSECT {
740 tb.skip()?;
741 let args = self.parse_braced_objs(tb)?;
742 if args.len() != 2 {
743 return Err(RuntimeError::from(ParseRuntimeError(
744 RuntimeErrorStruct::new_with_msg_and_line_file(
745 "intersect expects 2 arguments".to_string(),
746 tb.line_file.clone(),
747 ),
748 )));
749 }
750 let mut it = args.into_iter();
751 let left = it.next().ok_or_else(|| {
752 RuntimeError::from(ParseRuntimeError(
753 RuntimeErrorStruct::new_with_msg_and_line_file(
754 "intersect expects 2 arguments".to_string(),
755 tb.line_file.clone(),
756 ),
757 ))
758 })?;
759 let right = 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 return Ok(Intersect::new(left, right).into());
768 }
769 if tok == SET_MINUS {
770 tb.skip()?;
771 let args = self.parse_braced_objs(tb)?;
772 if args.len() != 2 {
773 return Err(RuntimeError::from(ParseRuntimeError(
774 RuntimeErrorStruct::new_with_msg_and_line_file(
775 "set_minus expects 2 arguments".to_string(),
776 tb.line_file.clone(),
777 ),
778 )));
779 }
780 let mut it = args.into_iter();
781 let left = it.next().ok_or_else(|| {
782 RuntimeError::from(ParseRuntimeError(
783 RuntimeErrorStruct::new_with_msg_and_line_file(
784 "set_minus expects 2 arguments".to_string(),
785 tb.line_file.clone(),
786 ),
787 ))
788 })?;
789 let right = 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 return Ok(SetMinus::new(left, right).into());
798 }
799 if tok == SET_DIFF {
800 tb.skip()?;
801 let args = self.parse_braced_objs(tb)?;
802 if args.len() != 2 {
803 return Err(RuntimeError::from(ParseRuntimeError(
804 RuntimeErrorStruct::new_with_msg_and_line_file(
805 "disjoint_union expects 2 arguments".to_string(),
806 tb.line_file.clone(),
807 ),
808 )));
809 }
810 let mut it = args.into_iter();
811 let left = it.next().ok_or_else(|| {
812 RuntimeError::from(ParseRuntimeError(
813 RuntimeErrorStruct::new_with_msg_and_line_file(
814 "disjoint_union expects 2 arguments".to_string(),
815 tb.line_file.clone(),
816 ),
817 ))
818 })?;
819 let right = 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 return Ok(SetDiff::new(left, right).into());
828 }
829 if tok == CAP {
830 tb.skip()?;
831 let args = self.parse_braced_objs(tb)?;
832 if args.len() != 1 {
833 return Err(RuntimeError::from(ParseRuntimeError(
834 RuntimeErrorStruct::new_with_msg_and_line_file(
835 "cap expects 1 argument".to_string(),
836 tb.line_file.clone(),
837 ),
838 )));
839 }
840 let mut it = args.into_iter();
841 let value = it.next().ok_or_else(|| {
842 RuntimeError::from(ParseRuntimeError(
843 RuntimeErrorStruct::new_with_msg_and_line_file(
844 "cap expects 1 argument".to_string(),
845 tb.line_file.clone(),
846 ),
847 ))
848 })?;
849 return Ok(Cap::new(value).into());
850 }
851 if tok == CUP {
852 tb.skip()?;
853 let args = self.parse_braced_objs(tb)?;
854 if args.len() != 1 {
855 return Err(RuntimeError::from(ParseRuntimeError(
856 RuntimeErrorStruct::new_with_msg_and_line_file(
857 "cup expects 1 argument".to_string(),
858 tb.line_file.clone(),
859 ),
860 )));
861 }
862 let mut it = args.into_iter();
863 let value = it.next().ok_or_else(|| {
864 RuntimeError::from(ParseRuntimeError(
865 RuntimeErrorStruct::new_with_msg_and_line_file(
866 "cup expects 1 argument".to_string(),
867 tb.line_file.clone(),
868 ),
869 ))
870 })?;
871 return Ok(Cup::new(value).into());
872 }
873 if tok == CHOOSE {
874 tb.skip()?;
875 let args = self.parse_braced_objs(tb)?;
876 if args.len() != 1 {
877 return Err(RuntimeError::from(ParseRuntimeError(
878 RuntimeErrorStruct::new_with_msg_and_line_file(
879 "choice expects 1 argument".to_string(),
880 tb.line_file.clone(),
881 ),
882 )));
883 }
884 let mut it = args.into_iter();
885 let value = it.next().ok_or_else(|| {
886 RuntimeError::from(ParseRuntimeError(
887 RuntimeErrorStruct::new_with_msg_and_line_file(
888 "choice expects 1 argument".to_string(),
889 tb.line_file.clone(),
890 ),
891 ))
892 })?;
893 return Ok(Choose::new(value).into());
894 }
895 if tok == PROJ {
896 tb.skip()?;
897 let args = self.parse_braced_objs(tb)?;
898 if args.len() != 2 {
899 return Err(RuntimeError::from(ParseRuntimeError(
900 RuntimeErrorStruct::new_with_msg_and_line_file(
901 "proj expects 2 arguments".to_string(),
902 tb.line_file.clone(),
903 ),
904 )));
905 }
906 let mut it = args.into_iter();
907 let left = it.next().ok_or_else(|| {
908 RuntimeError::from(ParseRuntimeError(
909 RuntimeErrorStruct::new_with_msg_and_line_file(
910 "proj expects 2 arguments".to_string(),
911 tb.line_file.clone(),
912 ),
913 ))
914 })?;
915 let right = 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 return Ok(Proj::new(left, right).into());
924 }
925 if tok == RANGE {
926 tb.skip()?;
927 let args = self.parse_braced_objs(tb)?;
928 if args.len() != 2 {
929 return Err(RuntimeError::from(ParseRuntimeError(
930 RuntimeErrorStruct::new_with_msg_and_line_file(
931 "range expects 2 arguments".to_string(),
932 tb.line_file.clone(),
933 ),
934 )));
935 }
936 let mut it = args.into_iter();
937 let left = it.next().ok_or_else(|| {
938 RuntimeError::from(ParseRuntimeError(
939 RuntimeErrorStruct::new_with_msg_and_line_file(
940 "range expects 2 arguments".to_string(),
941 tb.line_file.clone(),
942 ),
943 ))
944 })?;
945 let right = 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 return Ok(Range::new(left, right).into());
954 }
955 if tok == CLOSED_RANGE {
956 tb.skip()?;
957 let args = self.parse_braced_objs(tb)?;
958 if args.len() != 2 {
959 return Err(RuntimeError::from(ParseRuntimeError(
960 RuntimeErrorStruct::new_with_msg_and_line_file(
961 "closed_range expects 2 arguments".to_string(),
962 tb.line_file.clone(),
963 ),
964 )));
965 }
966 let mut it = args.into_iter();
967 let left = it.next().ok_or_else(|| {
968 RuntimeError::from(ParseRuntimeError(
969 RuntimeErrorStruct::new_with_msg_and_line_file(
970 "closed_range expects 2 arguments".to_string(),
971 tb.line_file.clone(),
972 ),
973 ))
974 })?;
975 let right = 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 return Ok(ClosedRange::new(left, right).into());
984 }
985 if tok == FINITE_SEQ {
986 tb.skip()?;
987 let args = self.parse_braced_objs(tb)?;
988 if args.len() != 2 {
989 return Err(RuntimeError::from(ParseRuntimeError(
990 RuntimeErrorStruct::new_with_msg_and_line_file(
991 "finite_seq expects 2 arguments".to_string(),
992 tb.line_file.clone(),
993 ),
994 )));
995 }
996 let mut it = args.into_iter();
997 let set = it.next().ok_or_else(|| {
998 RuntimeError::from(ParseRuntimeError(
999 RuntimeErrorStruct::new_with_msg_and_line_file(
1000 "finite_seq expects 2 arguments".to_string(),
1001 tb.line_file.clone(),
1002 ),
1003 ))
1004 })?;
1005 let n = it.next().ok_or_else(|| {
1006 RuntimeError::from(ParseRuntimeError(
1007 RuntimeErrorStruct::new_with_msg_and_line_file(
1008 "finite_seq expects 2 arguments".to_string(),
1009 tb.line_file.clone(),
1010 ),
1011 ))
1012 })?;
1013 return Ok(FiniteSeqSet::new(set, n).into());
1014 }
1015 if tok == SEQ {
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 "seq expects 1 argument".to_string(),
1022 tb.line_file.clone(),
1023 ),
1024 )));
1025 }
1026 let set = args.into_iter().next().ok_or_else(|| {
1027 RuntimeError::from(ParseRuntimeError(
1028 RuntimeErrorStruct::new_with_msg_and_line_file(
1029 "seq expects 1 argument".to_string(),
1030 tb.line_file.clone(),
1031 ),
1032 ))
1033 })?;
1034 return Ok(SeqSet::new(set).into());
1035 }
1036 if tok == MATRIX {
1037 tb.skip()?;
1038 let args = self.parse_braced_objs(tb)?;
1039 if args.len() != 3 {
1040 return Err(RuntimeError::from(ParseRuntimeError(
1041 RuntimeErrorStruct::new_with_msg_and_line_file(
1042 "matrix expects 3 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 "matrix expects 3 arguments".to_string(),
1052 tb.line_file.clone(),
1053 ),
1054 ))
1055 })?;
1056 let row_len = it.next().ok_or_else(|| {
1057 RuntimeError::from(ParseRuntimeError(
1058 RuntimeErrorStruct::new_with_msg_and_line_file(
1059 "matrix expects 3 arguments".to_string(),
1060 tb.line_file.clone(),
1061 ),
1062 ))
1063 })?;
1064 let col_len = it.next().ok_or_else(|| {
1065 RuntimeError::from(ParseRuntimeError(
1066 RuntimeErrorStruct::new_with_msg_and_line_file(
1067 "matrix expects 3 arguments".to_string(),
1068 tb.line_file.clone(),
1069 ),
1070 ))
1071 })?;
1072 return Ok(MatrixSet::new(set, row_len, col_len).into());
1073 }
1074
1075 if tok == CUP {
1076 tb.skip()?;
1077 let args = self.parse_braced_objs(tb)?;
1078 if args.len() != 1 {
1079 return Err(RuntimeError::from(ParseRuntimeError(
1080 RuntimeErrorStruct::new_with_msg_and_line_file(
1081 "cup expects 1 argument".to_string(),
1082 tb.line_file.clone(),
1083 ),
1084 )));
1085 }
1086 let mut it = args.into_iter();
1087 let value = it.next().ok_or_else(|| {
1088 RuntimeError::from(ParseRuntimeError(
1089 RuntimeErrorStruct::new_with_msg_and_line_file(
1090 "cup expects 1 argument".to_string(),
1091 tb.line_file.clone(),
1092 ),
1093 ))
1094 })?;
1095 return Ok(Cup::new(value).into());
1096 }
1097 if tok == POWER_SET {
1098 tb.skip()?;
1099 let args = self.parse_braced_objs(tb)?;
1100 if args.len() != 1 {
1101 return Err(RuntimeError::from(ParseRuntimeError(
1102 RuntimeErrorStruct::new_with_msg_and_line_file(
1103 "power_set expects 1 argument".to_string(),
1104 tb.line_file.clone(),
1105 ),
1106 )));
1107 }
1108 let mut it = args.into_iter();
1109 let value = it.next().ok_or_else(|| {
1110 RuntimeError::from(ParseRuntimeError(
1111 RuntimeErrorStruct::new_with_msg_and_line_file(
1112 "power_set expects 1 argument".to_string(),
1113 tb.line_file.clone(),
1114 ),
1115 ))
1116 })?;
1117 return Ok(PowerSet::new(value).into());
1118 }
1119 if tok == CART_DIM {
1120 tb.skip()?;
1121 let args = self.parse_braced_objs(tb)?;
1122 if args.len() != 1 {
1123 return Err(RuntimeError::from(ParseRuntimeError(
1124 RuntimeErrorStruct::new_with_msg_and_line_file(
1125 "set_dim expects 1 argument".to_string(),
1126 tb.line_file.clone(),
1127 ),
1128 )));
1129 }
1130 let mut it = args.into_iter();
1131 let value = it.next().ok_or_else(|| {
1132 RuntimeError::from(ParseRuntimeError(
1133 RuntimeErrorStruct::new_with_msg_and_line_file(
1134 "set_dim expects 1 argument".to_string(),
1135 tb.line_file.clone(),
1136 ),
1137 ))
1138 })?;
1139 return Ok(CartDim::new(value).into());
1140 }
1141 if tok == COUNT {
1142 tb.skip()?;
1143 let args = self.parse_braced_objs(tb)?;
1144 if args.len() != 1 {
1145 return Err(RuntimeError::from(ParseRuntimeError(
1146 RuntimeErrorStruct::new_with_msg_and_line_file(
1147 "count expects 1 argument".to_string(),
1148 tb.line_file.clone(),
1149 ),
1150 )));
1151 }
1152 let mut it = args.into_iter();
1153 let value = it.next().ok_or_else(|| {
1154 RuntimeError::from(ParseRuntimeError(
1155 RuntimeErrorStruct::new_with_msg_and_line_file(
1156 "count expects 1 argument".to_string(),
1157 tb.line_file.clone(),
1158 ),
1159 ))
1160 })?;
1161 return Ok(Count::new(value).into());
1162 }
1163 if tok == SUM {
1164 tb.skip()?;
1165 let args = self.parse_braced_objs(tb)?;
1166 if args.len() != 3 {
1167 return Err(RuntimeError::from(ParseRuntimeError(
1168 RuntimeErrorStruct::new_with_msg_and_line_file(
1169 "sum expects 3 arguments (start, end, function)".to_string(),
1170 tb.line_file.clone(),
1171 ),
1172 )));
1173 }
1174 let mut it = args.into_iter();
1175 let start = it.next().ok_or_else(|| {
1176 RuntimeError::from(ParseRuntimeError(
1177 RuntimeErrorStruct::new_with_msg_and_line_file(
1178 "sum expects 3 arguments (start, end, function)".to_string(),
1179 tb.line_file.clone(),
1180 ),
1181 ))
1182 })?;
1183 let end = it.next().ok_or_else(|| {
1184 RuntimeError::from(ParseRuntimeError(
1185 RuntimeErrorStruct::new_with_msg_and_line_file(
1186 "sum expects 3 arguments (start, end, function)".to_string(),
1187 tb.line_file.clone(),
1188 ),
1189 ))
1190 })?;
1191 let func = it.next().ok_or_else(|| {
1192 RuntimeError::from(ParseRuntimeError(
1193 RuntimeErrorStruct::new_with_msg_and_line_file(
1194 "sum expects 3 arguments (start, end, function)".to_string(),
1195 tb.line_file.clone(),
1196 ),
1197 ))
1198 })?;
1199 return Ok(Sum::new(start, end, func).into());
1200 }
1201 if tok == PRODUCT {
1202 tb.skip()?;
1203 let args = self.parse_braced_objs(tb)?;
1204 if args.len() != 3 {
1205 return Err(RuntimeError::from(ParseRuntimeError(
1206 RuntimeErrorStruct::new_with_msg_and_line_file(
1207 "product expects 3 arguments (start, end, function)".to_string(),
1208 tb.line_file.clone(),
1209 ),
1210 )));
1211 }
1212 let mut it = args.into_iter();
1213 let start = it.next().ok_or_else(|| {
1214 RuntimeError::from(ParseRuntimeError(
1215 RuntimeErrorStruct::new_with_msg_and_line_file(
1216 "product expects 3 arguments (start, end, function)".to_string(),
1217 tb.line_file.clone(),
1218 ),
1219 ))
1220 })?;
1221 let end = it.next().ok_or_else(|| {
1222 RuntimeError::from(ParseRuntimeError(
1223 RuntimeErrorStruct::new_with_msg_and_line_file(
1224 "product expects 3 arguments (start, end, function)".to_string(),
1225 tb.line_file.clone(),
1226 ),
1227 ))
1228 })?;
1229 let func = it.next().ok_or_else(|| {
1230 RuntimeError::from(ParseRuntimeError(
1231 RuntimeErrorStruct::new_with_msg_and_line_file(
1232 "product expects 3 arguments (start, end, function)".to_string(),
1233 tb.line_file.clone(),
1234 ),
1235 ))
1236 })?;
1237 return Ok(Product::new(start, end, func).into());
1238 }
1239 if tok == CART {
1240 tb.skip()?;
1241 let args = self.parse_braced_objs(tb)?;
1242 if args.len() < 2 {
1243 return Err(RuntimeError::from(ParseRuntimeError(
1244 RuntimeErrorStruct::new_with_msg_and_line_file(
1245 "cart expects at least 2 arguments".to_string(),
1246 tb.line_file.clone(),
1247 ),
1248 )));
1249 }
1250 return Ok(Cart::new(args).into());
1251 }
1252
1253 if tok == TUPLE_DIM {
1254 tb.skip()?;
1255 let args = self.parse_braced_obj(tb)?;
1256 return Ok(TupleDim::new(args).into());
1257 }
1258
1259 if tok == CART_DIM {
1260 tb.skip()?;
1261 let args = self.parse_braced_obj(tb)?;
1262 return Ok(CartDim::new(args).into());
1263 }
1264
1265 self.parse_and_reclassify_atom_as_free_param_obj(tb)
1267 }
1268
1269 fn parse_and_reclassify_atom_as_free_param_obj(
1271 &mut self,
1272 tb: &mut TokenBlock,
1273 ) -> Result<Obj, RuntimeError> {
1274 let atom = self.parse_identifier_or_identifier_with_mod(tb)?;
1275 self.reclassify_atom_as_free_param_obj(atom)
1276 }
1277
1278 fn reclassify_atom_as_free_param_obj(&self, obj: Obj) -> Result<Obj, RuntimeError> {
1279 match obj {
1280 Obj::Atom(AtomObj::Identifier(id)) => {
1281 if let Some(standard) = standard_set_from_bare_identifier_name(&id.name) {
1282 return Ok(standard);
1283 }
1284 Ok(self
1285 .parsing_free_param_collection
1286 .resolve_identifier_to_free_param_obj(&id.name))
1287 }
1288 Obj::Atom(AtomObj::IdentifierWithMod(m)) => {
1289 Ok(Obj::Atom(AtomObj::IdentifierWithMod(m)))
1290 }
1291 _ => Err(RuntimeError::from(ParseRuntimeError(
1292 RuntimeErrorStruct::new_with_just_msg(
1293 "internal: atom position was not a name form".to_string(),
1294 ),
1295 ))),
1296 }
1297 }
1298
1299 pub fn parse_braced_objs(&mut self, tb: &mut TokenBlock) -> Result<Vec<Obj>, RuntimeError> {
1300 tb.skip_token(LEFT_BRACE)?;
1301 if tb.current_token_is_equal_to(RIGHT_BRACE) {
1302 tb.skip_token(RIGHT_BRACE)?;
1303 return Ok(vec![]);
1304 }
1305 let mut objs = vec![self.parse_obj(tb)?];
1306 while tb.current_token_is_equal_to(COMMA) {
1307 tb.skip_token(COMMA)?;
1308 objs.push(self.parse_obj(tb)?);
1309 }
1310 tb.skip_token(RIGHT_BRACE)?;
1311 Ok(objs)
1312 }
1313
1314 pub fn parse_braced_obj(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1315 let mut parsed_args = self.parse_braced_objs(tb)?;
1316 if parsed_args.len() != 1 {
1317 return Err(RuntimeError::from(ParseRuntimeError(
1318 RuntimeErrorStruct::new_with_msg_and_line_file(
1319 "expected exactly 1 argument".to_string(),
1320 tb.line_file.clone(),
1321 ),
1322 )));
1323 }
1324 let parsed_obj = parsed_args.remove(0);
1325 Ok(parsed_obj)
1326 }
1327
1328 pub fn parse_obj_list(&mut self, tb: &mut TokenBlock) -> Result<Vec<Obj>, RuntimeError> {
1330 let mut objs = vec![self.parse_obj(tb)?];
1331 while tb.current_token_is_equal_to(COMMA) {
1332 tb.skip_token(COMMA)?;
1333 objs.push(self.parse_obj(tb)?);
1334 }
1335 Ok(objs)
1336 }
1337
1338 fn parse_set_builder_or_set_list(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1339 tb.skip_token(LEFT_CURLY_BRACE)?;
1340 if tb.current_token_is_equal_to(RIGHT_CURLY_BRACE) {
1341 tb.skip_token(RIGHT_CURLY_BRACE)?;
1342 return Ok(ListSet::new(vec![]).into());
1343 }
1344
1345 let left = self.parse_obj(tb)?;
1346 let name_for_set_builder = match &left {
1349 Obj::Atom(AtomObj::Identifier(a)) => Some(a.name.as_str()),
1350 Obj::Atom(AtomObj::IdentifierWithMod(m)) => Some(m.name.as_str()),
1351 Obj::Atom(AtomObj::Forall(p)) => Some(p.name.as_str()),
1352 Obj::Atom(AtomObj::Def(p)) => Some(p.name.as_str()),
1353 Obj::Atom(AtomObj::Exist(p)) => Some(p.name.as_str()),
1354 Obj::Atom(AtomObj::SetBuilder(p)) => Some(p.name.as_str()),
1355 Obj::Atom(AtomObj::FnSet(p)) => Some(p.name.as_str()),
1356 Obj::Atom(AtomObj::Induc(p)) => Some(p.name.as_str()),
1357 Obj::Atom(AtomObj::DefAlgo(p)) => Some(p.name.as_str()),
1358 _ => None,
1359 };
1360 if let Some(name) = name_for_set_builder {
1361 if tb.current_token_is_equal_to(COMMA) || tb.current()? == RIGHT_CURLY_BRACE {
1362 self.parse_list_set_obj_with_leftmost_obj(tb, left)
1363 } else {
1364 self.parse_set_builder(tb, Identifier::new(name.to_string()))
1365 }
1366 } else {
1367 self.parse_list_set_obj_with_leftmost_obj(tb, left)
1368 }
1369 }
1370
1371 fn parse_set_builder(
1373 &mut self,
1374 tb: &mut TokenBlock,
1375 a: Identifier,
1376 ) -> Result<Obj, RuntimeError> {
1377 self.run_in_local_parsing_time_name_scope(|this| {
1378 let set_builder_param = [a.name.clone()];
1379 this.parsing_free_param_collection.begin_scope(
1380 ParamObjType::SetBuilder,
1381 &set_builder_param,
1382 tb.line_file.clone(),
1383 )?;
1384 let parsed = (|| -> Result<Obj, RuntimeError> {
1385 let second = this.parse_obj(tb)?;
1386 if tb.current()? == COLON {
1387 tb.skip_token(COLON)?;
1388
1389 let user_names = vec![a.name.clone()];
1390 this.validate_user_fn_param_names_for_parse(&user_names, tb.line_file.clone())?;
1391 let empty: HashMap<String, Obj> = HashMap::new();
1392 let second_inst = this.inst_obj(&second, &empty, ParamObjType::SetBuilder)?;
1393
1394 let mut facts_inst = Vec::new();
1395 while tb.current()? != RIGHT_CURLY_BRACE {
1396 let f = this.parse_or_and_chain_atomic_fact(tb)?;
1397 facts_inst.push(this.inst_or_and_chain_atomic_fact(
1398 &f,
1399 &empty,
1400 ParamObjType::SetBuilder,
1401 None,
1402 )?);
1403 }
1404 tb.skip_token(RIGHT_CURLY_BRACE)?;
1405
1406 Ok(SetBuilder::new(a.name.clone(), second_inst, facts_inst)?.into())
1407 } else {
1408 Err(RuntimeError::from(ParseRuntimeError(
1409 RuntimeErrorStruct::new_with_msg_and_line_file(
1410 "expected colon after first argument".to_string(),
1411 tb.line_file.clone(),
1412 ),
1413 )))
1414 }
1415 })();
1416 this.parsing_free_param_collection
1417 .end_scope(ParamObjType::SetBuilder, &set_builder_param);
1418 parsed
1419 })
1420 }
1421
1422 fn parse_list_set_obj_with_leftmost_obj(
1424 &mut self,
1425 tb: &mut TokenBlock,
1426 left_most_obj: Obj,
1427 ) -> Result<Obj, RuntimeError> {
1428 let mut objs = vec![left_most_obj];
1429 while tb.current()? != RIGHT_CURLY_BRACE {
1430 if tb.current_token_is_equal_to(COMMA) {
1431 tb.skip_token(COMMA)?;
1432 }
1433 objs.push(self.parse_obj(tb)?);
1434 }
1435 tb.skip_token(RIGHT_CURLY_BRACE)?;
1436 Ok(ListSet::new(objs).into())
1437 }
1438
1439 pub fn parse_list_set_obj(&mut self, tb: &mut TokenBlock) -> Result<ListSet, RuntimeError> {
1440 let mut objs = vec![];
1441 tb.skip_token(LEFT_CURLY_BRACE)?;
1442 while tb.current()? != RIGHT_CURLY_BRACE {
1443 objs.push(self.parse_obj(tb)?);
1444 if tb.current_token_is_equal_to(COMMA) {
1445 tb.skip_token(COMMA)?;
1446 }
1447 }
1448 tb.skip_token(RIGHT_CURLY_BRACE)?;
1449 Ok(ListSet::new(objs))
1450 }
1451
1452 pub fn parse_identifier_or_field_access(
1454 &mut self,
1455 tb: &mut TokenBlock,
1456 ) -> Result<Obj, RuntimeError> {
1457 let left = parse_synthetically_correct_identifier_string(tb)?;
1458 if !tb.exceed_end_of_head() && tb.current()? == DOT_AKA_FIELD_ACCESS_SIGN {
1459 return Err(RuntimeError::from(ParseRuntimeError(
1460 RuntimeErrorStruct::new_with_msg_and_line_file(
1461 "field access (`name.field`) is not supported in this version".to_string(),
1462 tb.line_file.clone(),
1463 ),
1464 )));
1465 }
1466 Ok(Identifier::new(left).into())
1467 }
1468
1469 fn parse_mod_qualified_atom(&mut self, tb: &mut TokenBlock) -> Result<Obj, RuntimeError> {
1470 let left = parse_synthetically_correct_identifier_string(tb)?;
1471 tb.skip_token(MOD_SIGN)?;
1472 let right = parse_synthetically_correct_identifier_string(tb)?;
1473 if !tb.exceed_end_of_head() && tb.current()? == DOT_AKA_FIELD_ACCESS_SIGN {
1474 return Err(RuntimeError::from(ParseRuntimeError(
1475 RuntimeErrorStruct::new_with_msg_and_line_file(
1476 "field access on module-qualified names is not supported in this version"
1477 .to_string(),
1478 tb.line_file.clone(),
1479 ),
1480 )));
1481 }
1482 Ok(IdentifierWithMod::new(left, right).into())
1483 }
1484
1485 pub fn parse_identifier_or_identifier_with_mod(
1487 &mut self,
1488 tb: &mut TokenBlock,
1489 ) -> Result<Obj, RuntimeError> {
1490 let next_is_mod = tb.token_at_add_index(1) == MOD_SIGN;
1491 if next_is_mod {
1492 self.parse_mod_qualified_atom(tb)
1493 } else {
1494 self.parse_identifier_or_field_access(tb)
1495 }
1496 }
1497
1498 pub fn parse_predicate(&mut self, tb: &mut TokenBlock) -> Result<AtomicName, RuntimeError> {
1499 self.parse_atomic_name(tb)
1500 }
1501
1502 pub fn parse_family_obj(&mut self, tb: &mut TokenBlock) -> Result<FamilyObj, RuntimeError> {
1503 tb.skip_token(FAMILY_OBJ_PREFIX)?;
1504 let name = self.parse_atomic_name(tb)?;
1505 let params = self.parse_braced_objs(tb)?;
1506 Ok(FamilyObj::new(name, params))
1507 }
1508
1509 pub fn parse_atomic_name(&mut self, tb: &mut TokenBlock) -> Result<AtomicName, RuntimeError> {
1511 let left = parse_synthetically_correct_identifier_string(tb)?;
1512 if !tb.exceed_end_of_head() && tb.current()? == MOD_SIGN {
1513 tb.skip()?;
1514 let right = parse_synthetically_correct_identifier_string(tb)?;
1515 Ok(AtomicName::WithMod(left, right))
1516 } else {
1517 Ok(AtomicName::WithoutMod(left))
1518 }
1519 }
1520}
1521
1522fn starts_with_digit(s: &str) -> bool {
1523 s.chars()
1524 .next()
1525 .map(|c| c.is_ascii_digit())
1526 .unwrap_or(false)
1527}
1528
1529fn is_number(s: &str) -> bool {
1530 if s.is_empty() {
1531 return false;
1532 }
1533
1534 let mut dot_count = 0;
1535
1536 for c in s.chars() {
1537 if c == '.' {
1538 dot_count += 1;
1539 if dot_count > 1 {
1540 return false;
1541 }
1542 } else if !c.is_ascii_digit() {
1543 return false;
1544 }
1545 }
1546
1547 s != "."
1548}
1549
1550enum FnSetOrFnSetClause {
1551 FnSet(FnSet),
1552 FnSetClause(FnSetClause),
1553}
1554
1555fn parse_synthetically_correct_identifier_string(
1556 tb: &mut TokenBlock,
1557) -> Result<String, RuntimeError> {
1558 let cur = tb.advance()?;
1559
1560 if cur == SET || cur == NONEMPTY_SET || cur == FINITE_SET {
1561 return Err(RuntimeError::from(ParseRuntimeError(
1562 RuntimeErrorStruct::new_with_msg_and_line_file(
1563 format!("{} is not a valid identifier", cur),
1564 tb.line_file.clone(),
1565 ),
1566 )));
1567 }
1568
1569 Ok(cur)
1570}
1571
1572fn standard_set_from_bare_identifier_name(name: &str) -> Option<Obj> {
1574 match name {
1575 N_POS => Some(StandardSet::NPos.into()),
1576 N => Some(StandardSet::N.into()),
1577 Q => Some(StandardSet::Q.into()),
1578 Z => Some(StandardSet::Z.into()),
1579 R => Some(StandardSet::R.into()),
1580 Q_POS => Some(StandardSet::QPos.into()),
1581 R_POS => Some(StandardSet::RPos.into()),
1582 Q_NEG => Some(StandardSet::QNeg.into()),
1583 Z_NEG => Some(StandardSet::ZNeg.into()),
1584 R_NEG => Some(StandardSet::RNeg.into()),
1585 Q_NZ => Some(StandardSet::QNz.into()),
1586 Z_NZ => Some(StandardSet::ZNz.into()),
1587 R_NZ => Some(StandardSet::RNz.into()),
1588 _ => None,
1589 }
1590}