gdl-parser 0.0.8

A parser for GDL (game description language)
Documentation
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' .)*