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)) if matches!(tail.as_ref(), Term::EmptyList) => {
277 if vars
278 .iter()
279 .any(|v| !matches!(v, Term::Unit(Unit::Variable(_))))
280 {
281 return Err(format!("Unconstrained variable list should only contain variables, got {:?}", vars));
282 }
283 if len >= 2 {
285 if let Term::Set(eq_vars) = &literals[len - 2] {
286 if eq_vars
287 .iter()
288 .any(|eq_var| !matches!(eq_var, Term::Unit(Unit::Variable(_))))
289 {
290 return Err(format!("Incorrectly formatted existentially quantified variables {:?}", eq_vars));
291 }
292 }
293 }
294 true
296 }
297 _ => false,
298 };
299 if meta_rule {
300 Ok(Some(TreeClause::MetaRule(literals)))
301 } else {
302 Ok(Some(TreeClause::Rule(literals)))
303 }
304 }
305 Some(",") => {
306 let meta_data = self.parse_expression()?;
308 if let Term::Set(eq_vars) = &meta_data {
309 if eq_vars
310 .iter()
311 .any(|eq_var| !matches!(eq_var, Term::Unit(Unit::Variable(_))))
312 {
313 return Err(format!("Incorrectly formatted existentially quantified variables {:?}", eq_vars));
314 }
315 self.expect(".")?;
316 Ok(Some(TreeClause::MetaFact(literals.pop().unwrap(), meta_data)))
317 } else {
318 Err(format!("Expected set of existentially quantified variables after comma in meta-fact, got {:?}", meta_data))
319 }
320 }
321 Some(".") => Ok(Some(TreeClause::Fact(literals[0].clone()))),
322 Some(token) => Err(format!("Expected \".\", \",\", or \":-\", recieved {token}")),
323 None => Err("Unexpected end of file".into()),
324 }
325 }
326 }
327 }
328
329 pub fn parse_all(&mut self) -> Result<Vec<TreeClause>, String> {
330 let mut clauses = Vec::<TreeClause>::new();
331 loop {
332 match self.parse_clause() {
333 Ok(Some(clause)) => clauses.push(clause),
334 Ok(None) => return Ok(clauses),
335 Err(msg) => return Err(format!("Line {}: {msg}", self.line)),
336 }
337 }
338 }
339}
340
341#[cfg(test)]
342mod tests {
343 use super::{
344 super::tokeniser::tokenise,
345 {Term, TokenStream, TreeClause, Unit},
346 };
347 #[test]
348 fn parse_number_term() {
349 let text = tokenise("10".into()).unwrap();
351 let term = TokenStream::new(text.clone()).parse_term().unwrap();
352 assert_eq!(term, Term::Unit(Unit::Int(10)));
353 let term = TokenStream::new(text).parse_expression().unwrap();
354 assert_eq!(term, Term::Unit(Unit::Int(10)));
355
356 let text = tokenise("-10".into()).unwrap();
358 let term = TokenStream::new(text.clone()).parse_term().unwrap();
359 assert_eq!(term, Term::Unit(Unit::Int(-10)));
360 let term = TokenStream::new(text).parse_expression().unwrap();
361 assert_eq!(term, Term::Unit(Unit::Int(-10)));
362
363 let text = tokenise("1.01".into()).unwrap();
365 let term = TokenStream::new(text.clone()).parse_term().unwrap();
366 assert_eq!(term, Term::Unit(Unit::Float(1.01)));
367 let term = TokenStream::new(text).parse_expression().unwrap();
368 assert_eq!(term, Term::Unit(Unit::Float(1.01)));
369
370 let text = tokenise("-1.01".into()).unwrap();
372 let term = TokenStream::new(text.clone()).parse_term().unwrap();
373 assert_eq!(term, Term::Unit(Unit::Float(-1.01)));
374 let term = TokenStream::new(text).parse_expression().unwrap();
375 assert_eq!(term, Term::Unit(Unit::Float(-1.01)));
376 }
377
378 #[test]
379 fn parse_constant_term() {
380 let text = tokenise("constant".into()).unwrap();
381 let term = TokenStream::new(text.clone()).parse_term().unwrap();
382 assert_eq!(term, Term::Unit(Unit::Constant("constant".into())));
383 let term = TokenStream::new(text).parse_expression().unwrap();
384 assert_eq!(term, Term::Unit(Unit::Constant("constant".into())));
385
386 let text = tokenise("constant_1".into()).unwrap();
387 let term = TokenStream::new(text.clone()).parse_term().unwrap();
388 assert_eq!(term, Term::Unit(Unit::Constant("constant_1".into())));
389 let term = TokenStream::new(text).parse_expression().unwrap();
390 assert_eq!(term, Term::Unit(Unit::Constant("constant_1".into())));
391
392 let text = tokenise("'file/path'".into()).unwrap();
393 let term = TokenStream::new(text.clone()).parse_term().unwrap();
394 assert_eq!(term, Term::Unit(Unit::Constant("file/path".into())));
395 let term = TokenStream::new(text).parse_expression().unwrap();
396 assert_eq!(term, Term::Unit(Unit::Constant("file/path".into())));
397
398 let text = tokenise("'c*o/n\"s-t'".into()).unwrap();
399 let term = TokenStream::new(text.clone()).parse_term().unwrap();
400 assert_eq!(term, Term::Unit(Unit::Constant("c*o/n\"s-t".into())));
401 let term = TokenStream::new(text).parse_expression().unwrap();
402 assert_eq!(term, Term::Unit(Unit::Constant("c*o/n\"s-t".into())));
403 }
404
405 #[test]
406 fn parse_variable_term() {
407 let text = tokenise("Var".into()).unwrap();
408 let term = TokenStream::new(text.clone()).parse_term().unwrap();
409 assert_eq!(term, Term::Unit(Unit::Variable("Var".into())));
410 let term = TokenStream::new(text).parse_expression().unwrap();
411 assert_eq!(term, Term::Unit(Unit::Variable("Var".into())));
412
413 let text = tokenise("VAR_Under".into()).unwrap();
414 let term = TokenStream::new(text.clone()).parse_term().unwrap();
415 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under".into())));
416 let term = TokenStream::new(text).parse_expression().unwrap();
417 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under".into())));
418
419 let text = tokenise("VAR10".into()).unwrap();
420 let term = TokenStream::new(text.clone()).parse_term().unwrap();
421 assert_eq!(term, Term::Unit(Unit::Variable("VAR10".into())));
422 let term = TokenStream::new(text).parse_expression().unwrap();
423 assert_eq!(term, Term::Unit(Unit::Variable("VAR10".into())));
424
425 let text = tokenise("VAR_Under2".into()).unwrap();
426 let term = TokenStream::new(text.clone()).parse_term().unwrap();
427 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under2".into())));
428 let term = TokenStream::new(text).parse_expression().unwrap();
429 assert_eq!(term, Term::Unit(Unit::Variable("VAR_Under2".into())));
430 }
431
432 #[test]
433 fn parse_string_term() {
434 let text = tokenise("\"A String\"".into()).unwrap();
435 let term = TokenStream::new(text.clone()).parse_term().unwrap();
436 assert_eq!(term, Term::Unit(Unit::String("\"A String\"".into())));
437 let term = TokenStream::new(text).parse_expression().unwrap();
438 assert_eq!(term, Term::Unit(Unit::String("\"A String\"".into())));
439
440 let text = tokenise("\"A \\\"String\"".into()).unwrap();
441 let term = TokenStream::new(text.clone()).parse_term().unwrap();
442 assert_eq!(term, Term::Unit(Unit::String("\"A \"String\"".into())));
443 let term = TokenStream::new(text).parse_expression().unwrap();
444 assert_eq!(term, Term::Unit(Unit::String("\"A \"String\"".into())));
445
446 let text = tokenise("\"A *+-=: String\"".into()).unwrap();
447 let term = TokenStream::new(text.clone()).parse_term().unwrap();
448 assert_eq!(term, Term::Unit(Unit::String("\"A *+-=: String\"".into())));
449 let term = TokenStream::new(text).parse_expression().unwrap();
450 assert_eq!(term, Term::Unit(Unit::String("\"A *+-=: String\"".into())));
451 }
452
453 #[test]
454 fn parse_atom_term() {
455 let p = Unit::Constant("p".into());
456 let q = Unit::Variable("Q".into());
457 let x = Unit::Variable("X".into());
458 let y = Unit::Variable("Y".into());
459 let a = Unit::Constant("a".into());
460 let b = Unit::Constant("b".into());
461
462 let text = tokenise("p(X,a)".into()).unwrap();
463 let term = TokenStream::new(text.clone()).parse_term().unwrap();
464 assert_eq!(
465 term,
466 Term::Atom(
467 p.clone(),
468 vec![Term::Unit(x.clone()), Term::Unit(a.clone())]
469 )
470 );
471 let term = TokenStream::new(text).parse_expression().unwrap();
472 assert_eq!(
473 term,
474 Term::Atom(
475 p.clone(),
476 vec![Term::Unit(x.clone()), Term::Unit(a.clone())]
477 )
478 );
479
480 let text = tokenise("Q(b,Y)".into()).unwrap();
481 let term = TokenStream::new(text.clone()).parse_term().unwrap();
482 assert_eq!(
483 term,
484 Term::Atom(
485 q.clone(),
486 vec![Term::Unit(b.clone()), Term::Unit(y.clone())]
487 )
488 );
489 let term = TokenStream::new(text).parse_expression().unwrap();
490 assert_eq!(
491 term,
492 Term::Atom(
493 q.clone(),
494 vec![Term::Unit(b.clone()), Term::Unit(y.clone())]
495 )
496 );
497 }
498
499 #[test]
500 fn parse_list_term() {
501 let a = Term::Unit(Unit::Constant("a".into()));
502 let b = Term::Unit(Unit::Constant("b".into()));
503 let c = Term::Unit(Unit::Constant("c".into()));
504 let t = Term::Unit(Unit::Variable("T".into()));
505 let p = Unit::Constant("p".into());
506
507 let text = tokenise("[a,b,c]".into()).unwrap();
508 let term = TokenStream::new(text.clone()).parse_term().unwrap();
509 assert_eq!(
510 term,
511 Term::List(
512 vec![a.clone(), b.clone(), c.clone()],
513 Box::new(Term::EmptyList)
514 )
515 );
516 let term = TokenStream::new(text).parse_expression().unwrap();
517 assert_eq!(
518 term,
519 Term::List(
520 vec![a.clone(), b.clone(), c.clone()],
521 Box::new(Term::EmptyList)
522 )
523 );
524
525 let text = tokenise("[a,b,c|[]]".into()).unwrap();
526 let term = TokenStream::new(text.clone()).parse_term().unwrap();
527 assert_eq!(
528 term,
529 Term::List(
530 vec![a.clone(), b.clone(), c.clone()],
531 Box::new(Term::EmptyList)
532 )
533 );
534 let term = TokenStream::new(text).parse_expression().unwrap();
535 assert_eq!(
536 term,
537 Term::List(
538 vec![a.clone(), b.clone(), c.clone()],
539 Box::new(Term::EmptyList)
540 )
541 );
542
543 let text = tokenise("[a|T]".into()).unwrap();
544 let term = TokenStream::new(text.clone()).parse_term().unwrap();
545 assert_eq!(term, Term::List(vec![a.clone()], Box::new(t.clone())));
546 let term = TokenStream::new(text).parse_expression().unwrap();
547 assert_eq!(term, Term::List(vec![a.clone()], Box::new(t.clone())));
548
549 let text = tokenise("[a,[b,c]]".into()).unwrap();
550 let sub_list = Term::List(vec![b.clone(), c.clone()], Box::new(Term::EmptyList));
551 let term = TokenStream::new(text.clone()).parse_term().unwrap();
552 assert_eq!(
553 term,
554 Term::List(vec![a.clone(), sub_list.clone()], Box::new(Term::EmptyList))
555 );
556 let term = TokenStream::new(text).parse_expression().unwrap();
557 assert_eq!(
558 term,
559 Term::List(vec![a.clone(), sub_list.clone()], Box::new(Term::EmptyList))
560 );
561
562 let text = tokenise("p([a,[b,c|T]])".into()).unwrap();
563 let sub_list = Term::List(vec![b.clone(), c.clone()], Box::new(t.clone()));
564 let list = Term::List(vec![a.clone(), sub_list.clone()], Box::new(Term::EmptyList));
565 let term = TokenStream::new(text.clone()).parse_term().unwrap();
566 assert_eq!(term, Term::Atom(p.clone(), vec![list.clone()]));
567 let term = TokenStream::new(text).parse_expression().unwrap();
568 assert_eq!(term, Term::Atom(p.clone(), vec![list]));
569
570 let text = tokenise("[]".into()).unwrap();
571 let term = TokenStream::new(text.clone()).parse_term().unwrap();
572 assert_eq!(term, Term::EmptyList);
573 let term = TokenStream::new(text).parse_expression().unwrap();
574 assert_eq!(term, Term::EmptyList);
575 }
576
577 #[test]
578 fn parse_set_term() {
579 let a = Term::Unit(Unit::Constant("a".into()));
580 let b = Term::Unit(Unit::Constant("b".into()));
581 let c = Term::Unit(Unit::Constant("c".into()));
582 let p = Unit::Constant("p".into());
583
584 let abc = Term::Set(vec![a.clone(), b.clone(), c.clone()]);
585
586 let text = tokenise("{a,b,c}".into()).unwrap();
587 let term = TokenStream::new(text.clone()).parse_term().unwrap();
588 assert_eq!(term, abc.clone());
589 let term = TokenStream::new(text).parse_expression().unwrap();
590 assert_eq!(term, abc.clone());
591
592 let text = tokenise("p({a,b,c})".into()).unwrap();
593 let term = TokenStream::new(text.clone()).parse_term().unwrap();
594 assert_eq!(term, Term::Atom(p.clone(), vec![abc.clone()]));
595 let term = TokenStream::new(text).parse_expression().unwrap();
596 assert_eq!(term, Term::Atom(p.clone(), vec![abc.clone()]));
597
598 let text = tokenise("{a,{b,c}}".into()).unwrap();
599 let term = TokenStream::new(text.clone()).parse_term().unwrap();
600 assert_eq!(
601 term,
602 Term::Set(vec![a.clone(), Term::Set(vec![b.clone(), c.clone()])])
603 );
604 let term = TokenStream::new(text).parse_expression().unwrap();
605 assert_eq!(
606 term,
607 Term::Set(vec![a.clone(), Term::Set(vec![b.clone(), c.clone()])])
608 );
609
610 let text = tokenise("{a,{}}".into()).unwrap();
611 let term = TokenStream::new(text.clone()).parse_term().unwrap();
612 assert_eq!(term, Term::Set(vec![a.clone(), Term::Set(vec![])]));
613 let term = TokenStream::new(text).parse_expression().unwrap();
614 assert_eq!(term, Term::Set(vec![a.clone(), Term::Set(vec![])]));
615 }
616
617 #[test]
618 fn parse_tuple() {
619 let a = Term::Unit(Unit::Constant("a".into()));
620 let b = Term::Unit(Unit::Constant("b".into()));
621 let c = Term::Unit(Unit::Constant("c".into()));
622 let p = Unit::Constant("p".into());
623
624 let abc = Term::Tuple(vec![a.clone(), b.clone(), c.clone()]);
625 let bc = Term::Tuple(vec![b.clone(), c.clone()]);
626
627 let text = tokenise("(a,b,c)".into()).unwrap();
628 let term = TokenStream::new(text).parse_expression().unwrap();
629 assert_eq!(term, abc.clone());
630
631 let text = tokenise("(a,(b,c))".into()).unwrap();
632 let term = TokenStream::new(text).parse_expression().unwrap();
633 assert_eq!(term, Term::Tuple(vec![a.clone(), bc.clone()]));
634
635 let text = tokenise("(a,())".into()).unwrap();
637 let term = TokenStream::new(text).parse_expression().unwrap();
638 assert_eq!(term, Term::Tuple(vec![a.clone(), Term::Tuple(vec![])]));
639
640 let text = tokenise("p((a,b,c))".into()).unwrap();
641 let term = TokenStream::new(text).parse_expression().unwrap();
642 assert_eq!(term, Term::Atom(p, vec![abc.clone()]));
643 }
644
645 #[test]
647 fn unclosed_atom() {
648 let mut tokens = TokenStream::new(tokenise("p(X,Y".into()).unwrap());
649 match tokens.parse_expression() {
650 Ok(_) => panic!("Should have thrown error"),
651 Err(message) => assert_eq!(message, "Unexpected End of File"),
652 }
653
654 let mut tokens = TokenStream::new(tokenise("p(X,Y.".into()).unwrap());
655 match tokens.parse_expression() {
656 Ok(_) => panic!("Should have thrown error"),
657 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
658 }
659
660 let mut tokens = TokenStream::new(tokenise("p(X,(Y)".into()).unwrap());
661 match tokens.parse_expression() {
662 Ok(_) => panic!("Should have thrown error"),
663 Err(message) => assert_eq!(message, "Unexpected End of File"),
664 }
665
666 let mut tokens = TokenStream::new(tokenise("p(X,(Y).".into()).unwrap());
667 match tokens.parse_expression() {
668 Ok(_) => panic!("Should have thrown error"),
669 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
670 }
671 }
672
673 #[test]
674 fn unclosed_list() {
675 let mut tokens = TokenStream::new(tokenise("[X,Y".into()).unwrap());
676 match tokens.parse_expression() {
677 Ok(_) => panic!("Should have thrown error"),
678 Err(message) => assert_eq!(message, "Unexpected End of File"),
679 }
680
681 let mut tokens = TokenStream::new(tokenise("[X,Y.".into()).unwrap());
682 match tokens.parse_expression() {
683 Ok(_) => panic!("Should have thrown error"),
684 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
685 }
686
687 let mut tokens = TokenStream::new(tokenise("[X,[Y]".into()).unwrap());
688 match tokens.parse_expression() {
689 Ok(_) => panic!("Should have thrown error"),
690 Err(message) => assert_eq!(message, "Unexpected End of File"),
691 }
692
693 let mut tokens = TokenStream::new(tokenise("[X,[Y].".into()).unwrap());
694 match tokens.parse_expression() {
695 Ok(_) => panic!("Should have thrown error"),
696 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
697 }
698 }
699
700 #[test]
701 fn unclosed_set() {
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 End of File"),
706 }
707
708 let mut tokens = TokenStream::new(tokenise("{X,Y.".into()).unwrap());
709 match tokens.parse_expression() {
710 Ok(_) => panic!("Should have thrown error"),
711 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
712 }
713
714 let mut tokens = TokenStream::new(tokenise("{X,{Y}".into()).unwrap());
715 match tokens.parse_expression() {
716 Ok(_) => panic!("Should have thrown error"),
717 Err(message) => assert_eq!(message, "Unexpected End of File"),
718 }
719
720 let mut tokens = TokenStream::new(tokenise("{X,{Y}.".into()).unwrap());
721 match tokens.parse_expression() {
722 Ok(_) => panic!("Should have thrown error"),
723 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
724 }
725 }
726
727 #[test]
728 fn unclosed_tuple() {
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 End of File"),
733 }
734
735 let mut tokens = TokenStream::new(tokenise("(X,Y.".into()).unwrap());
736 match tokens.parse_expression() {
737 Ok(_) => panic!("Should have thrown error"),
738 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
739 }
740
741 let mut tokens = TokenStream::new(tokenise("(X,(Y)".into()).unwrap());
742 match tokens.parse_expression() {
743 Ok(_) => panic!("Should have thrown error"),
744 Err(message) => assert_eq!(message, "Unexpected End of File"),
745 }
746
747 let mut tokens = TokenStream::new(tokenise("(X,(Y).".into()).unwrap());
748 match tokens.parse_expression() {
749 Ok(_) => panic!("Should have thrown error"),
750 Err(message) => assert_eq!(message, "Unexpected token in arguments: ."),
751 }
752 }
753
754 #[test]
755 fn infix_order() {
756 let x = Term::Unit(Unit::Variable("X".into()));
757 let _y = Term::Unit(Unit::Variable("Y".into()));
758 let one = Term::Unit(Unit::Int(1));
759 let two = Term::Unit(Unit::Int(2));
760 let three = Term::Unit(Unit::Int(3));
761 let one_and_half = Term::Unit(Unit::Float(1.5));
762 let plus = Unit::Constant("+".into());
763 let _minus = Unit::Constant("-".into());
764 let divide = Unit::Constant("/".into());
765 let _times = Unit::Constant("*".into());
766 let power = Unit::Constant("**".into());
767 let eqauls = Unit::Constant("=:=".into());
768
769 let text = tokenise("X =:= 1 + 2 / 1.5**3".into()).unwrap();
770 let term = TokenStream::new(text).parse_expression().unwrap();
771 assert_eq!(
772 term,
773 Term::Atom(
774 eqauls,
775 vec![
776 x.clone(),
777 Term::Atom(
778 plus.clone(),
779 vec![
780 one.clone(),
781 Term::Atom(
782 divide.clone(),
783 vec![
784 two.clone(),
785 Term::Atom(
786 power.clone(),
787 vec![one_and_half.clone(), three.clone()]
788 )
789 ]
790 )
791 ]
792 )
793 ]
794 )
795 );
796 }
797
798 #[test]
799 fn grouped_expression() {
800 let x = Term::Unit(Unit::Variable("X".into()));
801 let _y = Term::Unit(Unit::Variable("Y".into()));
802 let one = Term::Unit(Unit::Int(1));
803 let two = Term::Unit(Unit::Int(2));
804 let three = Term::Unit(Unit::Int(3));
805 let one_and_half = Term::Unit(Unit::Float(1.5));
806 let plus = Unit::Constant("+".into());
807 let _minus = Unit::Constant("-".into());
808 let divide = Unit::Constant("/".into());
809 let _times = Unit::Constant("*".into());
810 let power = Unit::Constant("**".into());
811 let equals = Unit::Constant("=:=".into());
812
813 let text = tokenise("X =:= 1 + (2 / 1.5)**3".into()).unwrap();
814 let term = TokenStream::new(text).parse_expression().unwrap();
815
816 assert_eq!(
817 term,
818 Term::Atom(
819 equals,
820 vec![
821 x,
822 Term::Atom(
823 plus,
824 vec![
825 one,
826 Term::Atom(
827 power,
828 vec![Term::Atom(divide, vec![two, one_and_half]), three]
829 )
830 ]
831 )
832 ]
833 )
834 );
835 }
836
837 #[test]
838 fn tuple_or_grouped_expression() {
839 let x = Term::Unit(Unit::Variable("X".into()));
840 let y = Term::Unit(Unit::Variable("Y".into()));
841 let a = Term::Unit(Unit::Constant("a".into()));
842 let one = Term::Unit(Unit::Int(1));
843 let two = Term::Unit(Unit::Int(2));
844 let three = Term::Unit(Unit::Int(3));
845 let one_and_half = Term::Unit(Unit::Float(1.5));
846 let plus = Unit::Constant("+".into());
847 let _minus = Unit::Constant("-".into());
848 let divide = Unit::Constant("/".into());
849 let _times = Unit::Constant("*".into());
850 let power = Unit::Constant("**".into());
851 let equals = Unit::Constant("=:=".into());
852
853 let text = tokenise("(a,X =:= 1 + (2 / 1.5)**(3,Y))".into()).unwrap();
854 let term = TokenStream::new(text).parse_expression().unwrap();
855
856 assert_eq!(
857 term,
858 Term::Tuple(vec![
859 a,
860 Term::Atom(
861 equals,
862 vec![
863 x,
864 Term::Atom(
865 plus,
866 vec![
867 one,
868 Term::Atom(
869 power,
870 vec![
871 Term::Atom(divide, vec![two, one_and_half]),
872 Term::Tuple(vec![three, y])
873 ]
874 )
875 ]
876 )
877 ]
878 )
879 ])
880 );
881 }
882
883 #[test]
884 fn parse_rule() {
885 let mut token_stream = TokenStream::new(tokenise("gt1(X):-X>1.".into()).unwrap());
886 let clause = token_stream.parse_clause().unwrap().unwrap();
887 let head = Term::Atom(
888 Unit::Constant("gt1".into()),
889 vec![Term::Unit(Unit::Variable("X".into()))],
890 );
891 let body = Term::Atom(
892 Unit::Constant(">".into()),
893 vec![
894 Term::Unit(Unit::Variable("X".into())),
895 Term::Unit(Unit::Int(1)),
896 ],
897 );
898
899 assert_eq!(clause, TreeClause::Rule(vec![head, body]));
900 }
902
903 #[test]
904 fn parse_fact() {
905 let mut token_stream = TokenStream::new(tokenise("man(plato).".into()).unwrap());
906 let clause = token_stream.parse_clause().unwrap().unwrap();
907 let head = Term::Atom(
908 Unit::Constant("man".into()),
909 vec![Term::Unit(Unit::Constant("plato".into()))],
910 );
911
912 assert_eq!(clause, TreeClause::Fact(head));
913 assert_eq!(token_stream.parse_clause().unwrap(), None);
914 }
915
916 #[test]
917 fn parse_meta_rule() {
918 let mut token_stream = TokenStream::new(tokenise("P(X,Y):-Q(X,Y),{P,Q}.".into()).unwrap());
919 let clause = token_stream.parse_clause().unwrap().unwrap();
920 let head = Term::Atom(
921 Unit::Variable("P".into()),
922 vec![
923 Term::Unit(Unit::Variable("X".into())),
924 Term::Unit(Unit::Variable("Y".into())),
925 ],
926 );
927 let body = Term::Atom(
928 Unit::Variable("Q".into()),
929 vec![
930 Term::Unit(Unit::Variable("X".into())),
931 Term::Unit(Unit::Variable("Y".into())),
932 ],
933 );
934 let meta_data = Term::Set(vec![
935 Term::Unit(Unit::Variable("P".into())),
936 Term::Unit(Unit::Variable("Q".into())),
937 ]);
938
939 assert_eq!(clause, TreeClause::MetaRule(vec![head, body, meta_data]));
940 assert_eq!(token_stream.parse_clause().unwrap(), None);
941 }
942
943 #[test]
944 fn parse_meta_rule_with_unconstrained_list() {
945 let mut token_stream = TokenStream::new(tokenise("edge(El,Q1,Q2):-q(Q1),q(Q2),{El},[Q1,Q2].".into()).unwrap());
947 let clause = token_stream.parse_clause().unwrap().unwrap();
948 let head = Term::Atom(
949 Unit::Constant("edge".into()),
950 vec![
951 Term::Unit(Unit::Variable("El".into())),
952 Term::Unit(Unit::Variable("Q1".into())),
953 Term::Unit(Unit::Variable("Q2".into())),
954 ],
955 );
956 let body1 = Term::Atom(
957 Unit::Constant("q".into()),
958 vec![Term::Unit(Unit::Variable("Q1".into()))],
959 );
960 let body2 = Term::Atom(
961 Unit::Constant("q".into()),
962 vec![Term::Unit(Unit::Variable("Q2".into()))],
963 );
964 let constrained = Term::Set(vec![
965 Term::Unit(Unit::Variable("El".into())),
966 ]);
967 let unconstrained = Term::List(
968 vec![
969 Term::Unit(Unit::Variable("Q1".into())),
970 Term::Unit(Unit::Variable("Q2".into())),
971 ],
972 Box::new(Term::EmptyList),
973 );
974
975 assert_eq!(clause, TreeClause::MetaRule(vec![head, body1, body2, constrained, unconstrained]));
976 assert_eq!(token_stream.parse_clause().unwrap(), None);
977 }
978
979 #[test]
980 fn parse_meta_rule_list_only() {
981 let mut token_stream = TokenStream::new(tokenise("edge(El,Q1,Q2):-q(Q1),q(Q2),[El,Q1,Q2].".into()).unwrap());
983 let clause = token_stream.parse_clause().unwrap().unwrap();
984 let head = Term::Atom(
985 Unit::Constant("edge".into()),
986 vec![
987 Term::Unit(Unit::Variable("El".into())),
988 Term::Unit(Unit::Variable("Q1".into())),
989 Term::Unit(Unit::Variable("Q2".into())),
990 ],
991 );
992 let body1 = Term::Atom(
993 Unit::Constant("q".into()),
994 vec![Term::Unit(Unit::Variable("Q1".into()))],
995 );
996 let body2 = Term::Atom(
997 Unit::Constant("q".into()),
998 vec![Term::Unit(Unit::Variable("Q2".into()))],
999 );
1000 let unconstrained = Term::List(
1001 vec![
1002 Term::Unit(Unit::Variable("El".into())),
1003 Term::Unit(Unit::Variable("Q1".into())),
1004 Term::Unit(Unit::Variable("Q2".into())),
1005 ],
1006 Box::new(Term::EmptyList),
1007 );
1008
1009 assert_eq!(clause, TreeClause::MetaRule(vec![head, body1, body2, unconstrained]));
1010 assert_eq!(token_stream.parse_clause().unwrap(), None);
1011 }
1012
1013 #[test]
1014 fn parse_meta_fact() {
1015 let mut token_stream = TokenStream::new(tokenise("Map([],[],X),{Map}.".into()).unwrap());
1016 let clause = token_stream.parse_clause().unwrap().unwrap();
1017 let head = Term::Atom(
1018 Unit::Variable("Map".into()),
1019 vec![
1020 Term::EmptyList,
1021 Term::EmptyList,
1022 Term::Unit(Unit::Variable("X".into())),
1023 ],
1024 );
1025 let meta_data = Term::Set(vec![
1026 Term::Unit(Unit::Variable("Map".into())),
1027 ]);
1028
1029 assert_eq!(clause, TreeClause::MetaFact(head, meta_data));
1030 assert_eq!(token_stream.parse_clause().unwrap(), None);
1031 }
1032
1033 #[test]
1034 fn parse_directive() {
1035 let mut token_stream =
1036 TokenStream::new(tokenise(":-test(a),['file/path'].".into()).unwrap());
1037 let clause = token_stream.parse_clause().unwrap().unwrap();
1038 let body = Term::Atom(
1039 Unit::Constant("test".into()),
1040 vec![Term::Unit(Unit::Constant("a".into()))],
1041 );
1042 let body2 = Term::List(
1043 vec![Term::Unit(Unit::Constant("file/path".into()))],
1044 Box::new(Term::EmptyList),
1045 );
1046
1047 assert_eq!(clause, TreeClause::Directive(vec![body, body2]));
1048 assert_eq!(token_stream.parse_clause().unwrap(), None);
1049 }
1050
1051 #[test]
1052 fn parse_all_clauses() {
1053 let text =
1054 "gt1(X):-X>1.\nman(plato).\nP(X,Y):-\n\tQ(X,Y),\n\t{P,Q}.\n:-test(a),['file/path']."
1055 .to_string();
1056 let mut token_stream = TokenStream::new(tokenise(text).unwrap());
1057 let clauses = token_stream.parse_all().unwrap();
1058
1059 let head = Term::Atom(
1060 Unit::Constant("gt1".into()),
1061 vec![Term::Unit(Unit::Variable("X".into()))],
1062 );
1063 let body = Term::Atom(
1064 Unit::Constant(">".into()),
1065 vec![
1066 Term::Unit(Unit::Variable("X".into())),
1067 Term::Unit(Unit::Int(1)),
1068 ],
1069 );
1070 assert_eq!(clauses[0], TreeClause::Rule(vec![head, body]));
1071
1072 let head = Term::Atom(
1073 Unit::Constant("man".into()),
1074 vec![Term::Unit(Unit::Constant("plato".into()))],
1075 );
1076 assert_eq!(clauses[1], TreeClause::Fact(head));
1077
1078 let head = Term::Atom(
1079 Unit::Variable("P".into()),
1080 vec![
1081 Term::Unit(Unit::Variable("X".into())),
1082 Term::Unit(Unit::Variable("Y".into())),
1083 ],
1084 );
1085 let body = Term::Atom(
1086 Unit::Variable("Q".into()),
1087 vec![
1088 Term::Unit(Unit::Variable("X".into())),
1089 Term::Unit(Unit::Variable("Y".into())),
1090 ],
1091 );
1092 let meta_data = Term::Set(vec![
1093 Term::Unit(Unit::Variable("P".into())),
1094 Term::Unit(Unit::Variable("Q".into())),
1095 ]);
1096 assert_eq!(
1097 clauses[2],
1098 TreeClause::MetaRule(vec![head, body, meta_data])
1099 );
1100
1101 let body = Term::Atom(
1102 Unit::Constant("test".into()),
1103 vec![Term::Unit(Unit::Constant("a".into()))],
1104 );
1105 let body2 = Term::List(
1106 vec![Term::Unit(Unit::Constant("file/path".into()))],
1107 Box::new(Term::EmptyList),
1108 );
1109 assert_eq!(clauses[3], TreeClause::Directive(vec![body, body2]));
1110 }
1111}