126 lines
2.8 KiB
Rust
126 lines
2.8 KiB
Rust
use std::path::Path;
|
|
|
|
use winnow::Parser;
|
|
use winnow::Result;
|
|
use winnow::ascii::alphanumeric0;
|
|
use winnow::ascii::multispace0;
|
|
use winnow::combinator::alt;
|
|
use winnow::combinator::delimited;
|
|
use winnow::combinator::opt;
|
|
use winnow::combinator::separated;
|
|
use winnow::combinator::seq;
|
|
use winnow::error::ContextError;
|
|
|
|
use crate::ast::Body;
|
|
use crate::ast::Clause;
|
|
use crate::ast::Module;
|
|
use crate::ast::Predicate;
|
|
use crate::ast::Variable;
|
|
|
|
pub fn predicate_parse(input: &mut &str) -> Result<Predicate>
|
|
{
|
|
let ident = alphanumeric0.parse_next(input)?;
|
|
|
|
// Check if output is a variable
|
|
if ident.chars().next().is_some_and(|char| char.is_uppercase())
|
|
{
|
|
Ok(Predicate::Variable(Variable(String::from(ident), None)))
|
|
}
|
|
else
|
|
{
|
|
let arguments = delimited(
|
|
("(", multispace0),
|
|
separated(1.., predicate_parse, (multispace0, ",", multispace0)),
|
|
(multispace0, ")"),
|
|
)
|
|
.parse_next(input)
|
|
.unwrap_or(Vec::new());
|
|
Ok(Predicate::Fixed(String::from(ident), arguments))
|
|
}
|
|
}
|
|
|
|
fn body_parse_or(input: &mut &str) -> Result<Body>
|
|
{
|
|
separated(
|
|
1..,
|
|
alt((
|
|
delimited("(", body_parse, ")"),
|
|
predicate_parse.map(Body::Term),
|
|
)),
|
|
(multispace0, ";", multispace0),
|
|
)
|
|
.map(Body::Or)
|
|
.parse_next(input)
|
|
}
|
|
|
|
pub fn body_parse(input: &mut &str) -> Result<Body>
|
|
{
|
|
// Parse and
|
|
separated(1.., body_parse_or, (multispace0, ",", multispace0))
|
|
.map(Body::And)
|
|
.parse_next(input)
|
|
}
|
|
|
|
pub fn clause_parse(input: &mut &str) -> Result<Clause>
|
|
{
|
|
seq! {
|
|
Clause
|
|
{
|
|
head: predicate_parse,
|
|
body: opt((multispace0, ":-", multispace0, body_parse).map(|(_, _, _, b)| b)),
|
|
_: multispace0,
|
|
_: "."
|
|
}
|
|
}
|
|
.parse_next(input)
|
|
}
|
|
|
|
pub fn module_parse(input: &mut &str) -> Result<Module>
|
|
{
|
|
let _: Result<&str, ContextError> = multispace0.parse_next(input);
|
|
separated(0.., clause_parse, multispace0)
|
|
.map(|clauses| Module { clauses })
|
|
.parse_next(input)
|
|
}
|
|
|
|
impl<T> From<T> for Module
|
|
where
|
|
T: AsRef<str>,
|
|
{
|
|
fn from(value: T) -> Self
|
|
{
|
|
let mut str: &str = value.as_ref();
|
|
module_parse.parse_next(&mut str).unwrap()
|
|
}
|
|
}
|
|
|
|
impl Module
|
|
{
|
|
pub fn parse_from_file<P: AsRef<Path>>(path: P) -> Self
|
|
{
|
|
std::fs::read_to_string(path).unwrap().into()
|
|
}
|
|
}
|
|
|
|
impl<T> From<T> for Predicate
|
|
where
|
|
T: AsRef<str>,
|
|
{
|
|
fn from(value: T) -> Self
|
|
{
|
|
let mut str: &str = value.as_ref();
|
|
predicate_parse.parse_next(&mut str).unwrap()
|
|
}
|
|
}
|
|
|
|
impl<T> From<T> for Body
|
|
where
|
|
T: AsRef<str>,
|
|
{
|
|
fn from(value: T) -> Self
|
|
{
|
|
let mut str: &str = value.as_ref();
|
|
body_parse.parse_next(&mut str).unwrap()
|
|
}
|
|
}
|