use super::{Description, Clause, Rule, Sentence, Term, Literal, Constant, Variable, Function,
Relation, Proposition, Not, Or, Distinct};
use super::Clause::{RuleClause, SentenceClause};
use super::Sentence::{PropSentence, RelSentence};
use super::Literal::{NotLit, OrLit, DistinctLit, RelLit, PropLit};
use super::Term::{FuncTerm, VarTerm, ConstTerm};
#[pub]
description -> Description
= __ clauses:clause* { Description::new(clauses) }
clause -> Clause
= r:rule { RuleClause(r) } / s:sentence { SentenceClause(s) }
rule -> Rule
= lparen rule_tok head:sentence body:literal* rparen { Rule::new(head, body) }
sentence -> Sentence
= l:prop_lit {
match l {
PropLit(p) => PropSentence(p),
_ => panic!("Expected a PropLit, got {:?}", l)
}
}
/ ( lparen l:rel_lit rparen {
match l {
RelLit(p) => RelSentence(p),
_ => panic!("Expected a RelLit, got {:?}", l)
}
})
literal -> Literal
= ( lparen l:( or_lit / not_lit / distinct_lit / rel_lit ) rparen { l } ) / prop_lit
not_lit -> Literal
= not_tok l:literal { NotLit(Not::new(Box::new(l))) }
or_lit -> Literal
= or_tok lits:literal* { OrLit(Or::new(lits)) }
distinct_lit -> Literal
= distinct_tok t1:term t2:term { DistinctLit(Distinct::new(t1, t2)) }
prop_lit -> Literal
= name:constant { PropLit(Proposition::new(name)) }
rel_lit -> Literal
= name:constant args:term* { RelLit(Relation::new(name, args)) }
term -> Term
= ( lparen t:func_term rparen { t } ) / var_term / const_term
func_term -> Term
= name:constant args:term* { FuncTerm(Function::new(name, args)) }
var_term -> Term
= '?' name:constant { VarTerm(Variable::new(name)) }
const_term -> Term
= name:constant { ConstTerm(name) }
constant -> Constant
= name:ident { Constant::new(name.to_string()) }
// While `ident`s should normally start with a letter, we'll be treating numeric constants as
// idents, so we don't enforce that here
ident -> String
= s:(ident_char+ { match_str.to_string() }) __ { s }
ident_char -> char
= letter / digit / underscore
underscore -> char
= '_' { match_str.chars().next().unwrap() }
letter -> char
= [a-zA-Z] { match_str.chars().next().unwrap() }
digit -> char
= [0-9] { match_str.chars().next().unwrap() }
lparen = '(' __
rparen = ')' __
rule_tok = '<=' __
not_tok = 'not' kw__
or_tok = 'or' kw__
distinct_tok = 'distinct' kw__
kw__ = (!ident_char) __
__ = (whitespace / comment)*
whitespace = [ \t\n\r]
comment = ';' (!'\n' .)*