use crate::{Token, TokenId};
use std::fmt;
pub type Prec = u16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Fixity {
Nilfix,
Prefix,
Suffix,
Infix,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Assoc {
Left,
Right,
}
#[derive(Debug, Clone)]
pub(crate) struct Op<T: Token> {
pub(crate) token: T,
pub(crate) fixity: Fixity,
pub(crate) assoc: Assoc,
pub(crate) prec: Prec,
pub(crate) arity: usize,
pub(crate) left_prec: Option<Prec>,
pub(crate) right_prec: Option<Prec>,
}
impl<T: Token> Op<T> {
pub(crate) fn new(
token: T,
fixity: Fixity,
assoc: Assoc,
prec: Prec,
num_tokens: usize,
) -> Op<T> {
assert_ne!(token, T::LEX_ERROR);
assert_ne!(token, T::BLANK);
assert_ne!(token, T::JUXTAPOSE);
Op::new_unchecked(token, fixity, assoc, prec, num_tokens)
}
pub(crate) fn new_atom(token: T, _token_id: TokenId) -> Op<T> {
Op::new_unchecked(token, Fixity::Nilfix, Assoc::Left, 0, 1)
}
pub(crate) fn new_error() -> Op<T> {
Op::new_unchecked(T::LEX_ERROR, Fixity::Nilfix, Assoc::Left, 0, 1)
}
pub(crate) fn new_blank() -> Op<T> {
Op::new_unchecked(T::BLANK, Fixity::Nilfix, Assoc::Left, 0, 1)
}
pub(crate) fn new_juxtapose(assoc: Assoc, prec: Prec) -> Op<T> {
Op::new_unchecked(T::JUXTAPOSE, Fixity::Infix, assoc, prec, 1)
}
fn new_unchecked(
token: T,
fixity: Fixity,
assoc: Assoc,
prec: Prec,
num_tokens: usize,
) -> Op<T> {
use Assoc::{Left, Right};
use Fixity::{Infix, Nilfix, Prefix, Suffix};
let (left_prec, right_prec) = match (fixity, assoc) {
(Nilfix, _) => (None, None),
(Prefix, Left) => (None, Some(prec)),
(Prefix, Right) => (None, Some(prec + 1)),
(Suffix, Left) => (Some(prec + 1), None),
(Suffix, Right) => (Some(prec), None),
(Infix, Left) => (Some(prec + 1), Some(prec)),
(Infix, Right) => (Some(prec), Some(prec + 1)),
};
let arity = match fixity {
Nilfix => num_tokens - 1,
Prefix | Suffix => num_tokens,
Infix => num_tokens + 1,
};
Op {
token,
fixity,
assoc,
prec,
arity,
left_prec,
right_prec,
}
}
}
impl<T: Token> fmt::Display for Op<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.token)
}
}