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_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 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 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(¶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 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(¶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 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(¶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 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 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 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 if starts_with_digit(token) {
533 let number = tb.advance()?;
534 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 let mut result = self.parse_primary_obj(tb)?;
575
576 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 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 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 self.parse_and_reclassify_atom_as_free_param_obj(tb)
1319 }
1320
1321 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 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 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 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 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 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 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
1668fn 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}