Compare commits
3 Commits
2c6d14234c
...
operators
| Author | SHA1 | Date | |
|---|---|---|---|
| 27af8c9263 | |||
| c82384764c | |||
| 21414f75db |
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[submodule "winnow"]
|
||||
path = winnow
|
||||
url = git@github.com:supersurviveur/winnow.git
|
||||
branch = operator-in-expression
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -323,8 +323,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
@ -7,6 +7,6 @@ edition = "2024"
|
||||
bimap = "0.6.3"
|
||||
env_logger = "0.11.8"
|
||||
log = "0.4.29"
|
||||
winnow = { version = "0.7.14", path = "./winnow" }
|
||||
lru = "0.16.3"
|
||||
owo-colors = "4.2.3"
|
||||
winnow = "0.7.14"
|
||||
|
||||
57
src/ast.rs
57
src/ast.rs
@ -30,7 +30,43 @@ pub enum Body
|
||||
pub enum Predicate
|
||||
{
|
||||
Variable(Variable), // Upercase variable like X
|
||||
Fixed(String, Vec<Predicate>),
|
||||
Fixed(Functor, Vec<Predicate>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Functor
|
||||
{
|
||||
Operator(Operator),
|
||||
Functor(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Operator
|
||||
{
|
||||
pub op: String,
|
||||
pub precedence: usize,
|
||||
pub op_type: OperatorType,
|
||||
}
|
||||
|
||||
impl Operator
|
||||
{
|
||||
pub fn new(op: String, precedence: usize, op_type: OperatorType) -> Self
|
||||
{
|
||||
Self {
|
||||
op,
|
||||
precedence,
|
||||
op_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum OperatorType
|
||||
{
|
||||
Prefix,
|
||||
Postfix,
|
||||
LeftInfix,
|
||||
RightInfix,
|
||||
}
|
||||
|
||||
impl Display for Body
|
||||
@ -126,3 +162,22 @@ impl Display for Module
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Functor
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
||||
{
|
||||
match self
|
||||
{
|
||||
Functor::Operator(op) => write!(f, "{}", op),
|
||||
Functor::Functor(name) => write!(f, "{}", name),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Display for Operator
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
||||
{
|
||||
write!(f, "{}", self.op)
|
||||
}
|
||||
}
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@ -17,9 +17,24 @@ fn main()
|
||||
|
||||
mult(zero, X, zero).
|
||||
mult(s(Y), X, Z) :- mult(Y, X, W), add(W, X, Z).
|
||||
|
||||
op(10, yfx, +).
|
||||
op(8, yfx, ^).
|
||||
op(6, xfy, ::).
|
||||
op(2, fx, [).
|
||||
op(2, xf, ]).
|
||||
op(3, yfx, |).
|
||||
|
||||
A + B :- test.
|
||||
|
||||
A ^ B + C :- test.
|
||||
A::B::C :- A.
|
||||
[Hd|Tl] :- Hd::Tl.
|
||||
"
|
||||
.into();
|
||||
|
||||
// println!("{}", module);
|
||||
// let prop: Body = "mult(X, s(s(s(zero))), s(s(s(s(s(s(s(s(s(zero))))))))))".into();
|
||||
//let prop: Body = "integer(s(X))".into();
|
||||
let prop: Body = "mult(X, s(s(zero)), s(s(s(s(zero)))))".into();
|
||||
//let prop: Body = "mult(X, Y, Z)".into();
|
||||
|
||||
275
src/parsing.rs
275
src/parsing.rs
@ -1,25 +1,205 @@
|
||||
use std::path::Path;
|
||||
use std::{collections::HashMap, 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 winnow::{
|
||||
ascii::{self, alphanumeric1, multispace0},
|
||||
combinator::{
|
||||
alt, delimited, expression, opt, preceded, repeat, separated, seq, terminated, Infix,
|
||||
Postfix, Prefix,
|
||||
},
|
||||
error::ContextError,
|
||||
Parser, Result, Stateful,
|
||||
};
|
||||
|
||||
use crate::ast::Body;
|
||||
use crate::ast::Clause;
|
||||
use crate::ast::Functor;
|
||||
use crate::ast::Module;
|
||||
use crate::ast::Operator;
|
||||
use crate::ast::Predicate;
|
||||
use crate::ast::{Body, OperatorType};
|
||||
use crate::ast::Variable;
|
||||
|
||||
pub fn predicate_parse(input: &mut &str) -> Result<Predicate>
|
||||
impl Operator
|
||||
{
|
||||
let ident = alphanumeric0.parse_next(input)?;
|
||||
pub fn get_precedence(&self) -> usize
|
||||
{
|
||||
self.precedence
|
||||
}
|
||||
pub fn make_infix_operator<'a>(self) -> Infix<Stream<'a>, Predicate, Operator, ContextError>
|
||||
{
|
||||
fn make_predicate(
|
||||
_: &mut Stream,
|
||||
a: Predicate,
|
||||
op: Operator,
|
||||
b: Predicate,
|
||||
) -> Result<Predicate>
|
||||
{
|
||||
Ok(Predicate::Fixed(Functor::Operator(op), vec![a, b]))
|
||||
}
|
||||
let precedence = self.get_precedence() as i64;
|
||||
match self.op_type
|
||||
{
|
||||
OperatorType::LeftInfix => Infix::Left(precedence, self, make_predicate),
|
||||
OperatorType::RightInfix => Infix::Right(precedence, self, make_predicate),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Operator
|
||||
{
|
||||
fn infix(value: String, state: &State) -> Result<Self>
|
||||
{
|
||||
state
|
||||
.custom_operators
|
||||
.get(&(value.clone(), OperatorType::RightInfix))
|
||||
.or_else(|| {
|
||||
state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::LeftInfix))
|
||||
})
|
||||
.ok_or(ContextError::new())
|
||||
.cloned()
|
||||
}
|
||||
fn prefix(value: String, state: &State) -> Result<Self>
|
||||
{
|
||||
state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Prefix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned()
|
||||
}
|
||||
fn postfix(value: String, state: &State) -> Result<Self>
|
||||
{
|
||||
state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Postfix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
|
||||
const OPERATORS: [&str; 9] = [":", "-", "+", "|", "/", "*", "[", "]", "^"];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct State
|
||||
{
|
||||
custom_operators: HashMap<(String, OperatorType), Operator>,
|
||||
}
|
||||
|
||||
impl Default for State
|
||||
{
|
||||
fn default() -> Self
|
||||
{
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl State
|
||||
{
|
||||
pub fn new() -> Self
|
||||
{
|
||||
Self {
|
||||
custom_operators: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Stream<'is> = Stateful<&'is str, State>;
|
||||
|
||||
pub fn operator_parse(input: &mut Stream) -> Result<String>
|
||||
{
|
||||
delimited(multispace0, repeat(1.., alt(OPERATORS)), multispace0)
|
||||
.map(|op: String| Ok(op))
|
||||
.parse_next(input)?
|
||||
}
|
||||
|
||||
pub fn operator_parse_infix(input: &mut Stream) -> Result<Operator>
|
||||
{
|
||||
operator_parse(input).map(|op| Operator::infix(op, &input.state))?
|
||||
}
|
||||
pub fn operator_parse_postfix(input: &mut Stream) -> Result<Operator>
|
||||
{
|
||||
operator_parse(input).map(|op| Operator::postfix(op, &input.state))?
|
||||
}
|
||||
pub fn operator_parse_prefix(input: &mut Stream) -> Result<Operator>
|
||||
{
|
||||
operator_parse(input).map(|op| Operator::prefix(op, &input.state))?
|
||||
}
|
||||
|
||||
pub fn operator_definition_parse(input: &mut Stream) -> Result<()>
|
||||
{
|
||||
let (precedence, op_type, op) = preceded(
|
||||
"op",
|
||||
delimited(
|
||||
("(", multispace0),
|
||||
seq! {
|
||||
ascii::dec_uint,
|
||||
_: (multispace0, ",", multispace0),
|
||||
alt(("xfx", "xfy", "yfx", "xf", "yf", "fy", "fx")),
|
||||
_: (multispace0, ",", multispace0),
|
||||
operator_parse,
|
||||
},
|
||||
(multispace0, ")", multispace0, "."),
|
||||
),
|
||||
)
|
||||
.parse_next(input)?;
|
||||
let op_type = match op_type
|
||||
{
|
||||
"xf" | "yf" => OperatorType::Postfix,
|
||||
"fx" | "fy" => OperatorType::Prefix,
|
||||
"xfx" => unimplemented!(),
|
||||
"yfx" => OperatorType::LeftInfix,
|
||||
"xfy" => OperatorType::RightInfix,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
input.state.custom_operators.insert(
|
||||
(op.clone(), op_type.clone()),
|
||||
Operator::new(op, precedence, op_type),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn predicate_parse_infix_expression<'a>(
|
||||
input: &mut Stream<'a>,
|
||||
) -> Result<Infix<Stream<'a>, Predicate, Operator, ContextError>>
|
||||
{
|
||||
let op = operator_parse_infix.parse_next(input)?;
|
||||
Ok(op.make_infix_operator())
|
||||
}
|
||||
|
||||
pub fn predicate_parse_prefix_expression<'a>(
|
||||
input: &mut Stream<'a>,
|
||||
) -> Result<Prefix<Stream<'a>, Predicate, Operator, ContextError>>
|
||||
{
|
||||
let op = operator_parse_prefix.parse_next(input)?;
|
||||
let precedence = op.get_precedence() as i64;
|
||||
Ok(Prefix(precedence, op, |_, op, a| {
|
||||
Ok(Predicate::Fixed(Functor::Operator(op), vec![a]))
|
||||
}))
|
||||
}
|
||||
pub fn predicate_parse_postfix_expression<'a>(
|
||||
input: &mut Stream<'a>,
|
||||
) -> Result<Postfix<Stream<'a>, Predicate, Operator, ContextError>>
|
||||
{
|
||||
let op = operator_parse_postfix.parse_next(input)?;
|
||||
let precedence = op.get_precedence() as i64;
|
||||
Ok(Postfix(precedence, op, |_, a, op| {
|
||||
Ok(Predicate::Fixed(Functor::Operator(op), vec![a]))
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn predicate_parse_expression(input: &mut Stream) -> Result<Predicate>
|
||||
{
|
||||
expression(predicate_parse_recursive)
|
||||
.infix(predicate_parse_infix_expression)
|
||||
.postfix(predicate_parse_postfix_expression)
|
||||
.prefix(predicate_parse_prefix_expression)
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
pub fn predicate_parse_variable_or_functor(input: &mut Stream) -> Result<Predicate>
|
||||
{
|
||||
let ident = alphanumeric1.parse_next(input)?;
|
||||
|
||||
// Check if output is a variable
|
||||
if ident.chars().next().is_some_and(|char| char.is_uppercase())
|
||||
@ -35,11 +215,28 @@ pub fn predicate_parse(input: &mut &str) -> Result<Predicate>
|
||||
)
|
||||
.parse_next(input)
|
||||
.unwrap_or(Vec::new());
|
||||
Ok(Predicate::Fixed(String::from(ident), arguments))
|
||||
Ok(Predicate::Fixed(
|
||||
Functor::Functor(String::from(ident)),
|
||||
arguments,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn body_parse_or(input: &mut &str) -> Result<Body>
|
||||
pub fn predicate_parse_recursive(input: &mut Stream) -> Result<Predicate>
|
||||
{
|
||||
alt((
|
||||
delimited("(", predicate_parse, ")"),
|
||||
predicate_parse_variable_or_functor,
|
||||
))
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
pub fn predicate_parse(input: &mut Stream) -> Result<Predicate>
|
||||
{
|
||||
alt((predicate_parse_expression, predicate_parse_recursive)).parse_next(input)
|
||||
}
|
||||
|
||||
fn body_parse_or(input: &mut Stream) -> Result<Body>
|
||||
{
|
||||
separated(
|
||||
1..,
|
||||
@ -53,7 +250,7 @@ fn body_parse_or(input: &mut &str) -> Result<Body>
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
pub fn body_parse(input: &mut &str) -> Result<Body>
|
||||
pub fn body_parse(input: &mut Stream) -> Result<Body>
|
||||
{
|
||||
// Parse and
|
||||
separated(1.., body_parse_or, (multispace0, ",", multispace0))
|
||||
@ -61,7 +258,7 @@ pub fn body_parse(input: &mut &str) -> Result<Body>
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
pub fn clause_parse(input: &mut &str) -> Result<Clause>
|
||||
pub fn clause_parse(input: &mut Stream) -> Result<Clause>
|
||||
{
|
||||
seq! {
|
||||
Clause
|
||||
@ -75,12 +272,19 @@ pub fn clause_parse(input: &mut &str) -> Result<Clause>
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
pub fn module_parse(input: &mut &str) -> Result<Module>
|
||||
pub fn module_parse(input: &mut Stream) -> Result<Module>
|
||||
{
|
||||
let _: Result<&str, ContextError> = multispace0.parse_next(input);
|
||||
separated(0.., clause_parse, multispace0)
|
||||
.map(|clauses| Module { clauses })
|
||||
.parse_next(input)
|
||||
separated(
|
||||
0..,
|
||||
preceded::<_, (), _, _, _, _>(
|
||||
repeat(0.., terminated(operator_definition_parse, multispace0)),
|
||||
clause_parse,
|
||||
),
|
||||
multispace0,
|
||||
)
|
||||
.map(|clauses| Module { clauses })
|
||||
.parse_next(input)
|
||||
}
|
||||
|
||||
impl<T> From<T> for Module
|
||||
@ -89,8 +293,13 @@ where
|
||||
{
|
||||
fn from(value: T) -> Self
|
||||
{
|
||||
let mut str: &str = value.as_ref();
|
||||
module_parse.parse_next(&mut str).unwrap()
|
||||
let str: &str = value.as_ref();
|
||||
module_parse
|
||||
.parse_next(&mut Stream {
|
||||
input: str,
|
||||
state: State::new(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,8 +317,13 @@ where
|
||||
{
|
||||
fn from(value: T) -> Self
|
||||
{
|
||||
let mut str: &str = value.as_ref();
|
||||
predicate_parse.parse_next(&mut str).unwrap()
|
||||
let str: &str = value.as_ref();
|
||||
predicate_parse
|
||||
.parse_next(&mut Stream {
|
||||
input: str,
|
||||
state: State::new(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +333,12 @@ where
|
||||
{
|
||||
fn from(value: T) -> Self
|
||||
{
|
||||
let mut str: &str = value.as_ref();
|
||||
body_parse.parse_next(&mut str).unwrap()
|
||||
let str: &str = value.as_ref();
|
||||
body_parse
|
||||
.parse_next(&mut Stream {
|
||||
input: str,
|
||||
state: State::new(),
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use log::info;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::Style;
|
||||
use owo_colors::colors::css::DarkGray;
|
||||
use owo_colors::colors::css::Gray;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::Style;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
1
winnow
Submodule
1
winnow
Submodule
Submodule winnow added at cc0438a28f
Reference in New Issue
Block a user