1use super::term::{Term, Unit};
6
7const INFIX_ORDER: &[&[&str]] = &[
8 &["**"],
9 &["*", "/"],
10 &["+", "-"],
11 &["==", "=/=", "/=", "=:=", "is", ">", ">=", "<", "<="],
12];
13
14#[derive(Debug, PartialEq, Clone)]
15pub enum TreeClause {
16 Fact(Term),
17 Rule(Vec<Term>),
18 MetaRule(Vec<Term>),
19 MetaFact(Term, Term), Directive(Vec<Term>),
21}
22
23pub struct TokenStream {
24 tokens: Vec<String>,
25 index: usize,
26 line: usize,
27}
28
29impl TokenStream {
30 pub fn new(tokens: Vec<String>) -> Self {
31 TokenStream {
32 tokens,
33 index: 0,
34 line: 0,
35 }
36 }
37
38 pub fn next(&mut self) -> Option<&str> {
39 loop {
40 if self.index == self.tokens.len() {
41 return None;
42 }
43 match self.tokens[self.index].as_str() {
44 "\n" => {
45 self.index += 1;
46 self.line += 1
47 }
48 token => {
49 self.index += 1;
50 return Some(token);
51 }
52 }
53 }
54 }
55
56 pub fn peek(&self) -> Option<&str> {
57 let mut index = self.index;
58 loop {
59 if index == self.tokens.len() {
60 return None;
61 }
62 match self.tokens[index].as_str() {
63 "\n" => {
64 index += 1;
65 }
66 token => {
67 return Some(token);
68 }
69 }
70 }
71 }
72}
73
74fn is_operator(token: &str) -> bool {
75 INFIX_ORDER.iter().any(|group| group.contains(&token))
76}
77
78fn infix_order(operator: &str) -> usize {
79 INFIX_ORDER
80 .iter()
81 .position(|ops| ops.contains(&operator))
82 .unwrap()
83}
84
85fn resolve_infix(term_stack: &mut Vec<Term>, op_stack: &mut Vec<String>, max_prescendence: usize) {
86 while let Some(p) = op_stack.last().map(|operator| infix_order(&operator)) {
87 if p > max_prescendence {
88 break;
89 }
90 let op = op_stack.pop().unwrap();
91 let right = term_stack.pop().unwrap();
92 let left = term_stack.pop().unwrap();
93 term_stack.push(Term::Atom(Unit::Constant(op), vec![left, right]));
94 }
95}
96
97impl TokenStream {
98 fn expect(&mut self, value: &str) -> Result<(), String> {
99 match self.next() {
100 Some(token) if token == value => Ok(()),
101 Some(token) => Err(format!("Expected \"{value}\" recieved \"{token}\"")),
102 None => Err(format!("Unexpected end of file in expect {value}")),
103 }
104 }
105
106 fn consume_args(&mut self) -> Result<Vec<Term>, String> {
107 let mut args = Vec::new();
108 loop {
109 args.push(self.parse_expression()?);
110 match self.peek() {
111 Some(")" | "|" | "]" | "}") => return Ok(args), Some(",") => {
113 self.next();
114 }
115 Some(token) => return Err(format!("Unexpected token in arguments: {token}")),
116 None => return Err("Unexpected End of File".into()),
117 }
118 }
119 }
120
121 pub(super) fn parse_term(&mut self) -> Result<Term, String> {
125 match self.peek().ok_or("Unexpected end of file")? {
126 "{" => {
127 self.next();
128 let args = self.consume_args()?;
129 if self.next() == Some("}") {
130 Ok(Term::Set(args))
131 } else {
132 Err("Incorrectly formatted set".into())
133 }
134 }
135 "[" => {
136 self.next();
137 let head = self.consume_args()?;
138 match self.next().ok_or("Unexpected end of file")? {
139 "|" => {
140 let tail = Box::new(self.parse_expression()?);
141 self.expect("]")?;
142 Ok(Term::List(head, tail))
143 }
144 "]" => Ok(Term::List(head, Box::new(Term::EmptyList))),
145 token => return Err(format!("Unexpected token in list: {token}")),
146 }
147 }
148 "[]" => {
149 self.next();
150 Ok(Term::EmptyList)
151 }
152 "{}" => {
153 self.next();
154 Ok(Term::Set(vec![]))
155 }
156 "()" => {
157 self.next();
158 Ok(Term::Tuple(vec![]))
159 }
160 "(" => {
161 self.next();
163 let mut args = self.consume_args()?;
164 self.expect(")")?;
165 if args.len() == 1 {
166 Ok(args.pop().unwrap())
167 } else {
168 Ok(Term::Tuple(args))
169 }
170 }
171 token if is_operator(token) => {
172 let op = self.next().unwrap().to_string();
174 let operand = self.parse_term()?;
175 Ok(Term::Atom(Unit::Constant(op), vec![operand]))
176 }
177 token => {
178 let token = token.to_string();
179 match Unit::parse_unit(self.next().unwrap()) {
180 Some(unit @ (Unit::Constant(_) | Unit::Variable(_))) => {
181 if self.peek() == Some("(") {
182 self.next();
183 let args = self.consume_args()?;
184 self.expect(")")?;
185 Ok(Term::Atom(unit, args))
186 } else {
187 Ok(Term::Unit(unit))
188 }
189 }
190 Some(num @ (Unit::Float(_) | Unit::Int(_))) => Ok(Term::Unit(num)),
191 Some(unit @ Unit::String(_)) => Ok(Term::Unit(unit)),
192 None => unimplemented!("parse_expression: unhandled token '{token}'"),
193 }
194 }
195 }
196 }
197
198 pub(super) fn parse_expression(&mut self) -> Result<Term, String> {
199 let mut op_stack = Vec::<String>::new();
200 let mut term_stack = Vec::<Term>::new();
201 loop {
202 if self.peek() == Some("(") {
204 self.next();
206 let mut args = self.consume_args()?;
207 self.expect(")")?;
208 if args.len() == 1 {
209 term_stack.push(args.pop().unwrap());
210 } else {
211 term_stack.push(Term::Tuple(args));
212 }
213 } else {
214 term_stack.push(self.parse_term()?);
215 }
216
217 match self.peek() {
219 Some(operator) if is_operator(operator) => {
220 resolve_infix(&mut term_stack, &mut op_stack, infix_order(operator));
221 op_stack.push(operator.into());
222 self.next();
223 }
224 _ => break,
226 }
227 }
228
229 resolve_infix(&mut term_stack, &mut op_stack, INFIX_ORDER.len());
230 term_stack.pop().ok_or("Empty expression".into())
231 }
232
233 fn parse_body_literals(&mut self) -> Result<Vec<Term>, String> {
234 let mut body = Vec::new();
235 loop {
236 body.push(self.parse_expression()?);
237 match self.next() {
238 Some(",") => continue,
239 Some(".") => break,
240 Some(token) => {
241 return Err(format!(
242 "Unexpected token ({token}) after literal, expected either ',' or '.'"
243 ))
244 }
245 None => return Err("Unexpected end of file".into()),
246 }
247 }
248 Ok(body)
249 }
250
251 pub fn parse_clause(&mut self) -> Result<Option<TreeClause>, String> {
252 match self.peek() {
253 None => return Ok(None),
254 Some(":-") => {
255 self.next();
256 return Ok(Some(TreeClause::Directive(self.parse_body_literals()?)));
257 }
258 Some(_) => {
259 let mut literals = vec![self.parse_expression()?];
260 match self.next() {
261 Some(":-") => {
262 literals.append(&mut self.parse_body_literals()?);
263 let len = literals.len();
264 let meta_rule = match literals.last() {
265 Some(Term::Set(eq_vars)) => {
267 if eq_vars
268 .iter()
269 .any(|eq_var| !matches!(eq_var, Term::Unit(Unit::Variable(_))))
270 {
271 return Err(format!("Incorrectly formatted existentially quantified variables {:?}", eq_vars));
272 }
273 true
274 }
275 Some(Term::List(vars, tail))
277 if matches!(tail.as_ref(), Term::EmptyList) =>
278 {
279 if vars
280 .iter()
281 .any(|v| !matches!(v, Term::Unit(Unit::Variable(_))))
282 {
283 return Err(format!("Unconstrained variable list should only contain variables, got {:?}", vars));
284 }
285 if len >= 2 {
287 if let Term::Set(eq_vars) = &literals[len - 2] {
288 if eq_vars.iter().any(|eq_var| {
289 !matches!(eq_var, Term::Unit(Unit::Variable(_)))
290 }) {
291 return Err(format!("Incorrectly formatted existentially quantified variables {:?}", eq_vars));
292 }
293 }
294 }
295 true
297 }
298 _ => false,
299 };
300 if meta_rule {
301 Ok(Some(TreeClause::MetaRule(literals)))
302 } else {
303 Ok(Some(TreeClause::Rule(literals)))
304 }
305 }
306 Some(",") => {
307 let meta_data = self.parse_expression()?;
309 if let Term::Set(eq_vars) = &meta_data {
310 if eq_vars
311 .iter()
312 .any(|eq_var| !matches!(eq_var, Term::Unit(Unit::Variable(_))))
313 {
314 return Err(format!(
315 "Incorrectly formatted existentially quantified variables {:?}",
316 eq_vars
317 ));
318 }
319 self.expect(".")?;
320 Ok(Some(TreeClause::MetaFact(
321 literals.pop().unwrap(),
322 meta_data,
323 )))
324 } else {
325 Err(format!("Expected set of existentially quantified variables after comma in meta-fact, got {:?}", meta_data))
326 }
327 }
328 Some(".") => Ok(Some(TreeClause::Fact(literals[0].clone()))),
329 Some(token) => Err(format!(
330 "Expected \".\", \",\", or \":-\", recieved {token}"
331 )),
332 None => Err("Unexpected end of file".into()),
333 }
334 }
335 }
336 }
337
338 pub fn parse_all(&mut self) -> Result<Vec<TreeClause>, String> {
339 let mut clauses = Vec::<TreeClause>::new();
340 loop {
341 match self.parse_clause() {
342 Ok(Some(clause)) => clauses.push(clause),
343 Ok(None) => return Ok(clauses),
344 Err(msg) => return Err(format!("Line {}: {msg}", self.line)),
345 }
346 }
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use super::{
353 super::tokeniser::tokenise,
354 {Term, TokenStream, TreeClause, Unit},
355 };
356 #[test]
357 fn parse_number_term() {
358 let text = tokenise("10".into()).unwrap();
360 let term = TokenStream::new(text.clone()).parse_term().unwrap();
361 assert_eq!(term, Term::Unit(Unit::Int(10)));
362 let term = TokenStream::new(text).parse_expression().unwrap();
363 assert_eq!(term, Term::Unit(Unit::Int(10)));
364
365 let text = tokenise("-10".into()).unwrap();
367 let term = TokenStream::new(text.clone()).parse_term().unwrap();
368 assert_eq!(term, Term::Unit(Unit::Int(-10)));
369 let term = TokenStream::new(text).parse_expression().unwrap();
370 assert_eq!(term, Term::Unit(Unit::Int(-10)));
371
372 let text = tokenise("1.01".into()).unwrap();
374 let term = TokenStream::new(text.clone()).parse_term().unwrap();
375 assert_eq!(term, Term::Unit(Unit::Float(1.01)));
376 let term = TokenStream::new(text).parse_expression().unwrap();
377 assert_eq!(term, Term::Unit(Unit::Float(1.01)));
378
379 let text = tokenise("-1.01".into()).unwrap();
381 let term = TokenStream::new(text.clone()).parse_term().unwrap();
382 assert_eq!(term, Term::Unit(Unit::Float(-1.01)));
383 let term = TokenStream::new(text).parse_expression().unwrap();
384 assert_eq!(term, Term::Unit(Unit::Float(-1.01)));
385 }
386
387 #[test]
388 fn parse_constant_term() {
389 let text = tokenise("constant".into()).unwrap();
390 let term = TokenStream::new(text.clone()).parse_term().unwrap();
391 assert_eq!(term, Term::Unit(Unit::Constant("constant".into())));
392 let term = TokenStream::new(text).parse_expression().unwrap();
393 assert_eq!(term, Term::Unit(Unit::Constant("constant".into())));
394
395 let text = tokenise("constant_1".into()).unwrap();
396 let term = TokenStream::new(text.clone()).parse_term().unwrap();
397 assert_eq!(term, Term::Unit(Unit::Constant("constant_1".into())));
398 let term = TokenStream::new(text).parse_expression().unwrap();
399 assert_eq!(term, Term::Unit(Unit::Constant("constant_1".into())));
400
401 let text = tokenise("'file/path'".into()).unwrap();
402 let term = TokenStream::new(text.clone()).parse_term().unwrap();
403 assert_eq!(term, Term::Unit(Unit::Constant("file/path".into())));
404 let term = TokenStream::new(text).parse_expression().unwrap();
405 assert_eq!(term, Term::Unit(Unit::Constant("file/path".into())));
406
407 let text = tokenise("'c*o/n\"s-t'".into()).unwrap();
408 let term = TokenStream::new(text.clone()).parse_term().unwrap();
409 assert_eq!(term, Term::Unit(Unit::Constant("c*o/n\"s-t".into())));
410 let term = TokenStream::new(text).parse_expression().unwrap();
411 assert_eq!(term, Term::Unit(Unit::Constant("c*o/n\"s-t".into())));
412 }
413
414 #[test]
415 fn parse_variable_term() {
416 let text = tokenise("Var".into()).unwrap();
417 let term = TokenStream::new(text.clone()).parse_term().unwrap();
418 assert_eq!(term, Term::Unit(Unit::Variable("Var".into())));
419 let term = TokenStream::new(text).parse_expression().unwrap();
420 assert_eq!(term, Term::Unit(Unit::Variable("Var".into())));
421
422 let text = tokenise("VAR_Under".into()).unwrap();
423 let term = TokenStream::new(text.clone()).parse_term().unwrap();
424 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under".into())));
425 let term = TokenStream::new(text).parse_expression().unwrap();
426 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under".into())));
427
428 let text = tokenise("VAR10".into()).unwrap();
429 let term = TokenStream::new(text.clone()).parse_term().unwrap();
430 assert_eq!(term, Term::Unit(Unit::Variable("VAR10".into())));
431 let term = TokenStream::new(text).parse_expression().unwrap();
432 assert_eq!(term, Term::Unit(Unit::Variable("VAR10".into())));
433
434 let text = tokenise("VAR_Under2".into()).unwrap();
435 let term = TokenStream::new(text.clone()).parse_term().unwrap();
436 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under2".into())));
437 let term = TokenStream::new(text).parse_expression().unwrap();
438 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under2".into())));
439 }
440
441 #[test]
442 fn parse_string_term() {
443 let text = tokenise("\"A String\"".into()).unwrap();
444 let term = TokenStream::new(text.clone()).parse_term().unwrap();
445 assert_eq!(term, Term::Unit(Unit::String("\"A String\"".into())));
446 let term = TokenStream::new(text).parse_expression().unwrap();
447 assert_eq!(term, Term::Unit(Unit::String("\"A String\"".into())));
448
449 let text = tokenise("\"A \\\"String\"".into()).unwrap();
450 let term = TokenStream::new(text.clone()).parse_term().unwrap();
451 assert_eq!(term, Term::Unit(Unit::String("\"A \"String\"".into())));
452 let term = TokenStream::new(text).parse_expression().unwrap();
453 assert_eq!(term, Term::Unit(Unit::String("\"A \"String\"".into())));
454
455 let text = tokenise("\"A *+-=: String\"".into()).unwrap();
456 let term = TokenStream::new(text.clone()).parse_term().unwrap();
457 assert_eq!(term, Term::Unit(Unit::String("\"A *+-=: String\"".into())));
458 let term = TokenStream::new(text).parse_expression().unwrap();
459 assert_eq!(term, Term::Unit(Unit::String("\"A *+-=: String\"".into())));
460 }
461
462 #[test]
463 fn parse_atom_term() {
464 let p = Unit::Constant("p".into());
465 let q = Unit::Variable("Q".into());
466 let x = Unit::Variable("X".into());
467 let y = Unit::Variable("Y".into());
468 let a = Unit::Constant("a".into());
469 let b = Unit::Constant("b".into());
470
471 let text = tokenise("p(X,a)".into()).unwrap();
472 let term = TokenStream::new(text.clone()).parse_term().unwrap();
473 assert_eq!(
474 term,
475 Term::Atom(
476 p.clone(),
477 vec![Term::Unit(x.clone()), Term::Unit(a.clone())]
478 )
479 );
480 let term = TokenStream::new(text).parse_expression().unwrap();
481 assert_eq!(
482 term,
483 Term::Atom(
484 p.clone(),
485 vec![Term::Unit(x.clone()), Term::Unit(a.clone())]
486 )
487 );
488
489 let text = tokenise("Q(b,Y)".into()).unwrap();
490 let term = TokenStream::new(text.clone()).parse_term().unwrap();
491 assert_eq!(
492 term,
493 Term::Atom(
494 q.clone(),
495 vec![Term::Unit(b.clone()), Term::Unit(y.clone())]
496 )
497 );
498 let term = TokenStream::new(text).parse_expression().unwrap();
499 assert_eq!(
500 term,
501 Term::Atom(
502 q.clone(),
503 vec![Term::Unit(b.clone()), Term::Unit(y.clone())]
504 )
505 );
506 }
507
508 #[test]
509 fn parse_list_term() {
510 let a = Term::Unit(Unit::Constant("a".into()));
511 let b = Term::Unit(Unit::Constant("b".into()));
512 let c = Term::Unit(Unit::Constant("c".into()));
513 let t = Term::Unit(Unit::Variable("T".into()));
514 let p = Unit::Constant("p".into());
515
516 let text = tokenise("[a,b,c]".into()).unwrap();
517 let term = TokenStream::new(text.clone()).parse_term().unwrap();
518 assert_eq!(
519 term,
520 Term::List(
521 vec![a.clone(), b.clone(), c.clone()],
522 Box::new(Term::EmptyList)
523 )
524 );
525 let term = TokenStream::new(text).parse_expression().unwrap();
526 assert_eq!(
527 term,
528 Term::List(
529 vec![a.clone(), b.clone(), c.clone()],
530 Box::new(Term::EmptyList)
531 )
532 );
533
534 let text = tokenise("[a,b,c|[]]".into()).unwrap();
535 let term = TokenStream::new(text.clone()).parse_term().unwrap();
536 assert_eq!(
537 term,
538 Term::List(
539 vec![a.clone(), b.clone(), c.clone()],
540 Box::new(Term::EmptyList)
541 )
542 );
543 let term = TokenStream::new(text).parse_expression().unwrap();
544 assert_eq!(
545 term,
546 Term::List(
547 vec![a.clone(), b.clone(), c.clone()],
548 Box::new(Term::EmptyList)
549 )
550 );
551
552 let text = tokenise("[a|T]".into()).unwrap();
553 let term = TokenStream::new(text.clone()).parse_term().unwrap();
554 assert_eq!(term, Term::List(vec![a.clone()], Box::new(t.clone())));
555 let term = TokenStream::new(text).parse_expression().unwrap();
556 assert_eq!(term, Term::List(vec![a.clone()], Box::new(t.clone())));
557
558 let text = tokenise("[a,[b,c]]".into()).unwrap();
559 let sub_list = Term::List(vec![b.clone(), c.clone()], Box::new(Term::EmptyList));
560 let term = TokenStream::new(text.clone()).parse_term().unwrap();
561 assert_eq!(
562 term,
563 Term::List(vec![a.clone(), sub_list.clone()], Box::new(Term::EmptyList))
564 );
565 let term = TokenStream::new(text).parse_expression().unwrap();
566 assert_eq!(
567 term,
568 Term::List(vec![a.clone(), sub_list.clone()], Box::new(Term::EmptyList))
569 );
570
571 let text = tokenise("p([a,[b,c|T]])".into()).unwrap();
572 let sub_list = Term::List(vec![b.clone(), c.clone()], Box::new(t.clone()));
573 let list = Term::List(vec![a.clone(), sub_list.clone()], Box::new(Term::EmptyList));
574 let term = TokenStream::new(text.clone()).parse_term().unwrap();
575 assert_eq!(term, Term::Atom(p.clone(), vec![list.clone()]));
576 let term = TokenStream::new(text).parse_expression().unwrap();
577 assert_eq!(term, Term::Atom(p.clone(), vec![list]));
578
579 let text = tokenise("[]".into()).unwrap();
580 let term = TokenStream::new(text.clone()).parse_term().unwrap();
581 assert_eq!(term, Term::EmptyList);
582 let term = TokenStream::new(text).parse_expression().unwrap();
583 assert_eq!(term, Term::EmptyList);
584 }
585
586 #[test]
587 fn parse_set_term() {
588 let a = Term::Unit(Unit::Constant("a".into()));
589 let b = Term::Unit(Unit::Constant("b".into()));
590 let c = Term::Unit(Unit::Constant("c".into()));
591 let p = Unit::Constant("p".into());
592
593 let abc = Term::Set(vec![a.clone(), b.clone(), c.clone()]);
594
595 let text = tokenise("{a,b,c}".into()).unwrap();
596 let term = TokenStream::new(text.clone()).parse_term().unwrap();
597 assert_eq!(term, abc.clone());
598 let term = TokenStream::new(text).parse_expression().unwrap();
599 assert_eq!(term, abc.clone());
600
601 let text = tokenise("p({a,b,c})".into()).unwrap();
602 let term = TokenStream::new(text.clone()).parse_term().unwrap();
603 assert_eq!(term, Term::Atom(p.clone(), vec![abc.clone()]));
604 let term = TokenStream::new(text).parse_expression().unwrap();
605 assert_eq!(term, Term::Atom(p.clone(), vec![abc.clone()]));
606
607 let text = tokenise("{a,{b,c}}".into()).unwrap();
608 let term = TokenStream::new(text.clone()).parse_term().unwrap();
609 assert_eq!(
610 term,
611 Term::Set(vec![a.clone(), Term::Set(vec![b.clone(), c.clone()])])
612 );
613 let term = TokenStream::new(text).parse_expression().unwrap();
614 assert_eq!(
615 term,
616 Term::Set(vec![a.clone(), Term::Set(vec![b.clone(), c.clone()])])
617 );
618
619 let text = tokenise("{a,{}}".into()).unwrap();
620 let term = TokenStream::new(text.clone()).parse_term().unwrap();
621 assert_eq!(term, Term::Set(vec![a.clone(), Term::Set(vec![])]));
622 let term = TokenStream::new(text).parse_expression().unwrap();
623 assert_eq!(term, Term::Set(vec![a.clone(), Term::Set(vec![])]));
624 }
625
626 #[test]
627 fn parse_tuple() {
628 let a = Term::Unit(Unit::Constant("a".into()));
629 let b = Term::Unit(Unit::Constant("b".into()));
630 let c = Term::Unit(Unit::Constant("c".into()));
631 let p = Unit::Constant("p".into());
632
633 let abc = Term::Tuple(vec![a.clone(), b.clone(), c.clone()]);
634 let bc = Term::Tuple(vec![b.clone(), c.clone()]);
635
636 let text = tokenise("(a,b,c)".into()).unwrap();
637 let term = TokenStream::new(text).parse_expression().unwrap();
638 assert_eq!(term, abc.clone());
639
640 let text = tokenise("(a,(b,c))".into()).unwrap();
641 let term = TokenStream::new(text).parse_expression().unwrap();
642 assert_eq!(term, Term::Tuple(vec![a.clone(), bc.clone()]));
643
644 let text = tokenise("(a,())".into()).unwrap();
646 let term = TokenStream::new(text).parse_expression().unwrap();
647 assert_eq!(term, Term::Tuple(vec![a.clone(), Term::Tuple(vec![])]));
648
649 let text = tokenise("p((a,b,c))".into()).unwrap();
650 let term = TokenStream::new(text).parse_expression().unwrap();
651 assert_eq!(term, Term::Atom(p, vec![abc.clone()]));
652 }
653
654 #[test]
656 fn unclosed_atom() {
657 let mut tokens = TokenStream::new(tokenise("p(X,Y".into()).unwrap());
658 match tokens.parse_expression() {
659 Ok(_) => panic!("Should have thrown error"),
660 Err(message) => assert_eq!(message, "Unexpected End of File"),
661 }
662
663 let mut tokens = TokenStream::new(tokenise("p(X,Y.".into()).unwrap());
664 match tokens.parse_expression() {
665 Ok(_) => panic!("Should have thrown error"),
666 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
667 }
668
669 let mut tokens = TokenStream::new(tokenise("p(X,(Y)".into()).unwrap());
670 match tokens.parse_expression() {
671 Ok(_) => panic!("Should have thrown error"),
672 Err(message) => assert_eq!(message, "Unexpected End of File"),
673 }
674
675 let mut tokens = TokenStream::new(tokenise("p(X,(Y).".into()).unwrap());
676 match tokens.parse_expression() {
677 Ok(_) => panic!("Should have thrown error"),
678 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
679 }
680 }
681
682 #[test]
683 fn unclosed_list() {
684 let mut tokens = TokenStream::new(tokenise("[X,Y".into()).unwrap());
685 match tokens.parse_expression() {
686 Ok(_) => panic!("Should have thrown error"),
687 Err(message) => assert_eq!(message, "Unexpected End of File"),
688 }
689
690 let mut tokens = TokenStream::new(tokenise("[X,Y.".into()).unwrap());
691 match tokens.parse_expression() {
692 Ok(_) => panic!("Should have thrown error"),
693 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
694 }
695
696 let mut tokens = TokenStream::new(tokenise("[X,[Y]".into()).unwrap());
697 match tokens.parse_expression() {
698 Ok(_) => panic!("Should have thrown error"),
699 Err(message) => assert_eq!(message, "Unexpected End of File"),
700 }
701
702 let mut tokens = TokenStream::new(tokenise("[X,[Y].".into()).unwrap());
703 match tokens.parse_expression() {
704 Ok(_) => panic!("Should have thrown error"),
705 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
706 }
707 }
708
709 #[test]
710 fn unclosed_set() {
711 let mut tokens = TokenStream::new(tokenise("{X,Y".into()).unwrap());
712 match tokens.parse_expression() {
713 Ok(_) => panic!("Should have thrown error"),
714 Err(message) => assert_eq!(message, "Unexpected End of File"),
715 }
716
717 let mut tokens = TokenStream::new(tokenise("{X,Y.".into()).unwrap());
718 match tokens.parse_expression() {
719 Ok(_) => panic!("Should have thrown error"),
720 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
721 }
722
723 let mut tokens = TokenStream::new(tokenise("{X,{Y}".into()).unwrap());
724 match tokens.parse_expression() {
725 Ok(_) => panic!("Should have thrown error"),
726 Err(message) => assert_eq!(message, "Unexpected End of File"),
727 }
728
729 let mut tokens = TokenStream::new(tokenise("{X,{Y}.".into()).unwrap());
730 match tokens.parse_expression() {
731 Ok(_) => panic!("Should have thrown error"),
732 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
733 }
734 }
735
736 #[test]
737 fn unclosed_tuple() {
738 let mut tokens = TokenStream::new(tokenise("(X,Y".into()).unwrap());
739 match tokens.parse_expression() {
740 Ok(_) => panic!("Should have thrown error"),
741 Err(message) => assert_eq!(message, "Unexpected End of File"),
742 }
743
744 let mut tokens = TokenStream::new(tokenise("(X,Y.".into()).unwrap());
745 match tokens.parse_expression() {
746 Ok(_) => panic!("Should have thrown error"),
747 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
748 }
749
750 let mut tokens = TokenStream::new(tokenise("(X,(Y)".into()).unwrap());
751 match tokens.parse_expression() {
752 Ok(_) => panic!("Should have thrown error"),
753 Err(message) => assert_eq!(message, "Unexpected End of File"),
754 }
755
756 let mut tokens = TokenStream::new(tokenise("(X,(Y).".into()).unwrap());
757 match tokens.parse_expression() {
758 Ok(_) => panic!("Should have thrown error"),
759 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
760 }
761 }
762
763 #[test]
764 fn infix_order() {
765 let x = Term::Unit(Unit::Variable("X".into()));
766 let _y = Term::Unit(Unit::Variable("Y".into()));
767 let one = Term::Unit(Unit::Int(1));
768 let two = Term::Unit(Unit::Int(2));
769 let three = Term::Unit(Unit::Int(3));
770 let one_and_half = Term::Unit(Unit::Float(1.5));
771 let plus = Unit::Constant("+".into());
772 let _minus = Unit::Constant("-".into());
773 let divide = Unit::Constant("/".into());
774 let _times = Unit::Constant("*".into());
775 let power = Unit::Constant("**".into());
776 let eqauls = Unit::Constant("=:=".into());
777
778 let text = tokenise("X =:= 1 + 2 / 1.5**3".into()).unwrap();
779 let term = TokenStream::new(text).parse_expression().unwrap();
780 assert_eq!(
781 term,
782 Term::Atom(
783 eqauls,
784 vec![
785 x.clone(),
786 Term::Atom(
787 plus.clone(),
788 vec![
789 one.clone(),
790 Term::Atom(
791 divide.clone(),
792 vec![
793 two.clone(),
794 Term::Atom(
795 power.clone(),
796 vec![one_and_half.clone(), three.clone()]
797 )
798 ]
799 )
800 ]
801 )
802 ]
803 )
804 );
805 }
806
807 #[test]
808 fn grouped_expression() {
809 let x = Term::Unit(Unit::Variable("X".into()));
810 let _y = Term::Unit(Unit::Variable("Y".into()));
811 let one = Term::Unit(Unit::Int(1));
812 let two = Term::Unit(Unit::Int(2));
813 let three = Term::Unit(Unit::Int(3));
814 let one_and_half = Term::Unit(Unit::Float(1.5));
815 let plus = Unit::Constant("+".into());
816 let _minus = Unit::Constant("-".into());
817 let divide = Unit::Constant("/".into());
818 let _times = Unit::Constant("*".into());
819 let power = Unit::Constant("**".into());
820 let equals = Unit::Constant("=:=".into());
821
822 let text = tokenise("X =:= 1 + (2 / 1.5)**3".into()).unwrap();
823 let term = TokenStream::new(text).parse_expression().unwrap();
824
825 assert_eq!(
826 term,
827 Term::Atom(
828 equals,
829 vec![
830 x,
831 Term::Atom(
832 plus,
833 vec![
834 one,
835 Term::Atom(
836 power,
837 vec![Term::Atom(divide, vec![two, one_and_half]), three]
838 )
839 ]
840 )
841 ]
842 )
843 );
844 }
845
846 #[test]
847 fn tuple_or_grouped_expression() {
848 let x = Term::Unit(Unit::Variable("X".into()));
849 let y = Term::Unit(Unit::Variable("Y".into()));
850 let a = Term::Unit(Unit::Constant("a".into()));
851 let one = Term::Unit(Unit::Int(1));
852 let two = Term::Unit(Unit::Int(2));
853 let three = Term::Unit(Unit::Int(3));
854 let one_and_half = Term::Unit(Unit::Float(1.5));
855 let plus = Unit::Constant("+".into());
856 let _minus = Unit::Constant("-".into());
857 let divide = Unit::Constant("/".into());
858 let _times = Unit::Constant("*".into());
859 let power = Unit::Constant("**".into());
860 let equals = Unit::Constant("=:=".into());
861
862 let text = tokenise("(a,X =:= 1 + (2 / 1.5)**(3,Y))".into()).unwrap();
863 let term = TokenStream::new(text).parse_expression().unwrap();
864
865 assert_eq!(
866 term,
867 Term::Tuple(vec![
868 a,
869 Term::Atom(
870 equals,
871 vec![
872 x,
873 Term::Atom(
874 plus,
875 vec![
876 one,
877 Term::Atom(
878 power,
879 vec![
880 Term::Atom(divide, vec![two, one_and_half]),
881 Term::Tuple(vec![three, y])
882 ]
883 )
884 ]
885 )
886 ]
887 )
888 ])
889 );
890 }
891
892 #[test]
893 fn parse_rule() {
894 let mut token_stream = TokenStream::new(tokenise("gt1(X):-X>1.".into()).unwrap());
895 let clause = token_stream.parse_clause().unwrap().unwrap();
896 let head = Term::Atom(
897 Unit::Constant("gt1".into()),
898 vec![Term::Unit(Unit::Variable("X".into()))],
899 );
900 let body = Term::Atom(
901 Unit::Constant(">".into()),
902 vec![
903 Term::Unit(Unit::Variable("X".into())),
904 Term::Unit(Unit::Int(1)),
905 ],
906 );
907
908 assert_eq!(clause, TreeClause::Rule(vec![head, body]));
909 }
911
912 #[test]
913 fn parse_fact() {
914 let mut token_stream = TokenStream::new(tokenise("man(plato).".into()).unwrap());
915 let clause = token_stream.parse_clause().unwrap().unwrap();
916 let head = Term::Atom(
917 Unit::Constant("man".into()),
918 vec![Term::Unit(Unit::Constant("plato".into()))],
919 );
920
921 assert_eq!(clause, TreeClause::Fact(head));
922 assert_eq!(token_stream.parse_clause().unwrap(), None);
923 }
924
925 #[test]
926 fn parse_meta_rule() {
927 let mut token_stream = TokenStream::new(tokenise("P(X,Y):-Q(X,Y),{P,Q}.".into()).unwrap());
928 let clause = token_stream.parse_clause().unwrap().unwrap();
929 let head = Term::Atom(
930 Unit::Variable("P".into()),
931 vec![
932 Term::Unit(Unit::Variable("X".into())),
933 Term::Unit(Unit::Variable("Y".into())),
934 ],
935 );
936 let body = Term::Atom(
937 Unit::Variable("Q".into()),
938 vec![
939 Term::Unit(Unit::Variable("X".into())),
940 Term::Unit(Unit::Variable("Y".into())),
941 ],
942 );
943 let meta_data = Term::Set(vec![
944 Term::Unit(Unit::Variable("P".into())),
945 Term::Unit(Unit::Variable("Q".into())),
946 ]);
947
948 assert_eq!(clause, TreeClause::MetaRule(vec![head, body, meta_data]));
949 assert_eq!(token_stream.parse_clause().unwrap(), None);
950 }
951
952 #[test]
953 fn parse_meta_rule_with_unconstrained_list() {
954 let mut token_stream =
956 TokenStream::new(tokenise("edge(El,Q1,Q2):-q(Q1),q(Q2),{El},[Q1,Q2].".into()).unwrap());
957 let clause = token_stream.parse_clause().unwrap().unwrap();
958 let head = Term::Atom(
959 Unit::Constant("edge".into()),
960 vec![
961 Term::Unit(Unit::Variable("El".into())),
962 Term::Unit(Unit::Variable("Q1".into())),
963 Term::Unit(Unit::Variable("Q2".into())),
964 ],
965 );
966 let body1 = Term::Atom(
967 Unit::Constant("q".into()),
968 vec![Term::Unit(Unit::Variable("Q1".into()))],
969 );
970 let body2 = Term::Atom(
971 Unit::Constant("q".into()),
972 vec![Term::Unit(Unit::Variable("Q2".into()))],
973 );
974 let constrained = Term::Set(vec![Term::Unit(Unit::Variable("El".into()))]);
975 let unconstrained = Term::List(
976 vec![
977 Term::Unit(Unit::Variable("Q1".into())),
978 Term::Unit(Unit::Variable("Q2".into())),
979 ],
980 Box::new(Term::EmptyList),
981 );
982
983 assert_eq!(
984 clause,
985 TreeClause::MetaRule(vec![head, body1, body2, constrained, unconstrained])
986 );
987 assert_eq!(token_stream.parse_clause().unwrap(), None);
988 }
989
990 #[test]
991 fn parse_meta_rule_list_only() {
992 let mut token_stream =
994 TokenStream::new(tokenise("edge(El,Q1,Q2):-q(Q1),q(Q2),[El,Q1,Q2].".into()).unwrap());
995 let clause = token_stream.parse_clause().unwrap().unwrap();
996 let head = Term::Atom(
997 Unit::Constant("edge".into()),
998 vec![
999 Term::Unit(Unit::Variable("El".into())),
1000 Term::Unit(Unit::Variable("Q1".into())),
1001 Term::Unit(Unit::Variable("Q2".into())),
1002 ],
1003 );
1004 let body1 = Term::Atom(
1005 Unit::Constant("q".into()),
1006 vec![Term::Unit(Unit::Variable("Q1".into()))],
1007 );
1008 let body2 = Term::Atom(
1009 Unit::Constant("q".into()),
1010 vec![Term::Unit(Unit::Variable("Q2".into()))],
1011 );
1012 let unconstrained = Term::List(
1013 vec![
1014 Term::Unit(Unit::Variable("El".into())),
1015 Term::Unit(Unit::Variable("Q1".into())),
1016 Term::Unit(Unit::Variable("Q2".into())),
1017 ],
1018 Box::new(Term::EmptyList),
1019 );
1020
1021 assert_eq!(
1022 clause,
1023 TreeClause::MetaRule(vec![head, body1, body2, unconstrained])
1024 );
1025 assert_eq!(token_stream.parse_clause().unwrap(), None);
1026 }
1027
1028 #[test]
1029 fn parse_meta_fact() {
1030 let mut token_stream = TokenStream::new(tokenise("Map([],[],X),{Map}.".into()).unwrap());
1031 let clause = token_stream.parse_clause().unwrap().unwrap();
1032 let head = Term::Atom(
1033 Unit::Variable("Map".into()),
1034 vec![
1035 Term::EmptyList,
1036 Term::EmptyList,
1037 Term::Unit(Unit::Variable("X".into())),
1038 ],
1039 );
1040 let meta_data = Term::Set(vec![Term::Unit(Unit::Variable("Map".into()))]);
1041
1042 assert_eq!(clause, TreeClause::MetaFact(head, meta_data));
1043 assert_eq!(token_stream.parse_clause().unwrap(), None);
1044 }
1045
1046 #[test]
1047 fn parse_directive() {
1048 let mut token_stream =
1049 TokenStream::new(tokenise(":-test(a),['file/path'].".into()).unwrap());
1050 let clause = token_stream.parse_clause().unwrap().unwrap();
1051 let body = Term::Atom(
1052 Unit::Constant("test".into()),
1053 vec![Term::Unit(Unit::Constant("a".into()))],
1054 );
1055 let body2 = Term::List(
1056 vec![Term::Unit(Unit::Constant("file/path".into()))],
1057 Box::new(Term::EmptyList),
1058 );
1059
1060 assert_eq!(clause, TreeClause::Directive(vec![body, body2]));
1061 assert_eq!(token_stream.parse_clause().unwrap(), None);
1062 }
1063
1064 #[test]
1065 fn parse_all_clauses() {
1066 let text =
1067 "gt1(X):-X>1.\nman(plato).\nP(X,Y):-\n\tQ(X,Y),\n\t{P,Q}.\n:-test(a),['file/path']."
1068 .to_string();
1069 let mut token_stream = TokenStream::new(tokenise(text).unwrap());
1070 let clauses = token_stream.parse_all().unwrap();
1071
1072 let head = Term::Atom(
1073 Unit::Constant("gt1".into()),
1074 vec![Term::Unit(Unit::Variable("X".into()))],
1075 );
1076 let body = Term::Atom(
1077 Unit::Constant(">".into()),
1078 vec![
1079 Term::Unit(Unit::Variable("X".into())),
1080 Term::Unit(Unit::Int(1)),
1081 ],
1082 );
1083 assert_eq!(clauses[0], TreeClause::Rule(vec![head, body]));
1084
1085 let head = Term::Atom(
1086 Unit::Constant("man".into()),
1087 vec![Term::Unit(Unit::Constant("plato".into()))],
1088 );
1089 assert_eq!(clauses[1], TreeClause::Fact(head));
1090
1091 let head = Term::Atom(
1092 Unit::Variable("P".into()),
1093 vec![
1094 Term::Unit(Unit::Variable("X".into())),
1095 Term::Unit(Unit::Variable("Y".into())),
1096 ],
1097 );
1098 let body = Term::Atom(
1099 Unit::Variable("Q".into()),
1100 vec![
1101 Term::Unit(Unit::Variable("X".into())),
1102 Term::Unit(Unit::Variable("Y".into())),
1103 ],
1104 );
1105 let meta_data = Term::Set(vec![
1106 Term::Unit(Unit::Variable("P".into())),
1107 Term::Unit(Unit::Variable("Q".into())),
1108 ]);
1109 assert_eq!(
1110 clauses[2],
1111 TreeClause::MetaRule(vec![head, body, meta_data])
1112 );
1113
1114 let body = Term::Atom(
1115 Unit::Constant("test".into()),
1116 vec![Term::Unit(Unit::Constant("a".into()))],
1117 );
1118 let body2 = Term::List(
1119 vec![Term::Unit(Unit::Constant("file/path".into()))],
1120 Box::new(Term::EmptyList),
1121 );
1122 assert_eq!(clauses[3], TreeClause::Directive(vec![body, body2]));
1123 }
1124}