Use custom operators
This commit is contained in:
32
src/ast.rs
32
src/ast.rs
@ -38,12 +38,23 @@ pub enum Functor
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Operator
|
||||
pub struct Operator
|
||||
{
|
||||
Plus,
|
||||
Minus,
|
||||
Cons,
|
||||
Custom(String, usize, OperatorType),
|
||||
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)]
|
||||
@ -51,7 +62,8 @@ pub enum OperatorType
|
||||
{
|
||||
Prefix,
|
||||
Postfix,
|
||||
Infix,
|
||||
LeftInfix,
|
||||
RightInfix,
|
||||
}
|
||||
|
||||
impl Display for Body
|
||||
@ -150,12 +162,6 @@ impl Display for Operator
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
||||
{
|
||||
match self
|
||||
{
|
||||
Operator::Plus => write!(f, "+"),
|
||||
Operator::Minus => write!(f, "-"),
|
||||
Operator::Cons => write!(f, "::"),
|
||||
Operator::Custom(string, _, _) => write!(f, "{}", string),
|
||||
}
|
||||
write!(f, "{}", self.op)
|
||||
}
|
||||
}
|
||||
|
||||
11
src/main.rs
11
src/main.rs
@ -18,12 +18,17 @@ 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.
|
||||
|
||||
op(8, xfx, ^).
|
||||
|
||||
A ^ B + C :- test.
|
||||
(A::B)::C :- A.
|
||||
A::B::C :- A.
|
||||
[Hd|Tl] :- Hd::Tl.
|
||||
"
|
||||
.into();
|
||||
|
||||
@ -21,11 +21,25 @@ impl Operator
|
||||
{
|
||||
pub fn get_precedence(&self) -> usize
|
||||
{
|
||||
match self
|
||||
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>
|
||||
{
|
||||
Operator::Plus | Operator::Minus => 10,
|
||||
Operator::Cons => 12,
|
||||
Operator::Custom(_, precedence, _) => *precedence,
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,38 +48,32 @@ impl Operator
|
||||
{
|
||||
fn infix(value: String, state: &State) -> Result<Self>
|
||||
{
|
||||
match value.as_str()
|
||||
{
|
||||
"+" => Ok(Operator::Plus),
|
||||
"::" => Ok(Operator::Cons),
|
||||
_ => state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Infix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned(),
|
||||
}
|
||||
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>
|
||||
{
|
||||
match value.as_str()
|
||||
{
|
||||
_ => state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Prefix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned(),
|
||||
}
|
||||
state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Prefix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned()
|
||||
}
|
||||
fn postfix(value: String, state: &State) -> Result<Self>
|
||||
{
|
||||
match value.as_str()
|
||||
{
|
||||
_ => state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Postfix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned(),
|
||||
}
|
||||
state
|
||||
.custom_operators
|
||||
.get(&(value, OperatorType::Postfix))
|
||||
.ok_or(ContextError::new())
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,12 +146,14 @@ pub fn operator_definition_parse(input: &mut Stream) -> Result<()>
|
||||
{
|
||||
"xf" | "yf" => OperatorType::Postfix,
|
||||
"fx" | "fy" => OperatorType::Prefix,
|
||||
"xfx" | "xfy" | "yfx" => OperatorType::Infix,
|
||||
"xfx" => unimplemented!(),
|
||||
"yfx" => OperatorType::LeftInfix,
|
||||
"xfy" => OperatorType::RightInfix,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
input.state.custom_operators.insert(
|
||||
(op.clone(), op_type.clone()),
|
||||
Operator::Custom(op, precedence, op_type),
|
||||
Operator::new(op, precedence, op_type),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@ -153,13 +163,7 @@ pub fn predicate_parse_infix_expression<'a>(
|
||||
) -> Result<Infix<Stream<'a>, Predicate, Operator, ContextError>>
|
||||
{
|
||||
let op = operator_parse_infix.parse_next(input)?;
|
||||
let precedence = op.get_precedence() as i64;
|
||||
Ok(Infix::Left(precedence, op, |_, a, op, b| {
|
||||
Ok(Predicate::Fixed(
|
||||
Functor::Operator(op),
|
||||
vec![a, b],
|
||||
))
|
||||
}))
|
||||
Ok(op.make_infix_operator())
|
||||
}
|
||||
|
||||
pub fn predicate_parse_prefix_expression<'a>(
|
||||
@ -169,10 +173,7 @@ pub fn predicate_parse_prefix_expression<'a>(
|
||||
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],
|
||||
))
|
||||
Ok(Predicate::Fixed(Functor::Operator(op), vec![a]))
|
||||
}))
|
||||
}
|
||||
pub fn predicate_parse_postfix_expression<'a>(
|
||||
@ -182,10 +183,7 @@ pub fn predicate_parse_postfix_expression<'a>(
|
||||
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],
|
||||
))
|
||||
Ok(Predicate::Fixed(Functor::Operator(op), vec![a]))
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user