use std::iter::FusedIterator;
use std::ops::{Deref, Index};
use std::slice::ChunksExact;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SimpleUnary<'a> {
pub op: &'a str,
arg: Box<Simple<'a>>,
}
impl<'a> SimpleUnary<'a> {
pub fn new<S>(op: &'a str, arg: S) -> Self
where
S: Into<Simple<'a>>,
{
SimpleUnary {
op,
arg: Box::new(arg.into()),
}
}
#[must_use]
pub fn arg(&self) -> &Simple<'a> {
&self.arg
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SimpleFunc<'a> {
pub func: &'a str,
arg: Box<Simple<'a>>,
}
impl<'a> SimpleFunc<'a> {
pub fn new<S>(func: &'a str, arg: S) -> Self
where
S: Into<Simple<'a>>,
{
SimpleFunc {
func,
arg: Box::new(arg.into()),
}
}
#[must_use]
pub fn arg(&self) -> &Simple<'a> {
&self.arg
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SimpleBinary<'a> {
pub op: &'a str,
first: Box<Simple<'a>>,
second: Box<Simple<'a>>,
}
impl<'a> SimpleBinary<'a> {
pub fn new<F, S>(op: &'a str, first: F, second: S) -> Self
where
F: Into<Simple<'a>>,
S: Into<Simple<'a>>,
{
SimpleBinary {
op,
first: Box::new(first.into()),
second: Box::new(second.into()),
}
}
#[must_use]
pub fn first(&self) -> &Simple<'a> {
&self.first
}
#[must_use]
pub fn second(&self) -> &Simple<'a> {
&self.second
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Group<'a> {
pub left_bracket: &'a str,
pub expr: Expression<'a>,
pub right_bracket: &'a str,
}
impl<'a> Group<'a> {
pub fn new<E: Into<Expression<'a>>>(
left_bracket: &'a str,
expr: E,
right_bracket: &'a str,
) -> Self {
Group {
left_bracket,
expr: expr.into(),
right_bracket,
}
}
pub fn from_iter<T, I>(left_bracket: &'a str, inters: T, right_bracket: &'a str) -> Self
where
T: IntoIterator<Item = I>,
I: Into<Intermediate<'a>>,
{
Group {
left_bracket,
expr: inters.into_iter().collect(),
right_bracket,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Matrix<'a> {
pub left_bracket: &'a str,
cells: Box<[Expression<'a>]>,
num_cols: usize,
pub right_bracket: &'a str,
}
impl<'a> Matrix<'a> {
pub fn new<E>(left_bracket: &'a str, cells: E, num_cols: usize, right_bracket: &'a str) -> Self
where
E: Into<Box<[Expression<'a>]>>,
{
let cells = cells.into();
assert_eq!(cells.len() / num_cols * num_cols, cells.len());
Matrix {
left_bracket,
cells,
num_cols,
right_bracket,
}
}
#[must_use]
pub fn num_cols(&self) -> usize {
self.num_cols
}
#[must_use]
pub fn num_rows(&self) -> usize {
self.cells.len() / self.num_cols
}
#[must_use]
pub fn num_cells(&self) -> usize {
self.cells.len()
}
#[must_use]
pub fn rows(&self) -> MatrixRows<'a, '_> {
MatrixRows(self.cells.chunks_exact(self.num_cols))
}
#[must_use]
pub fn iter(&self) -> MatrixRows<'a, '_> {
self.into_iter()
}
}
impl<'a, 'b> IntoIterator for &'b Matrix<'a> {
type IntoIter = MatrixRows<'a, 'b>;
type Item = &'b [Expression<'a>];
fn into_iter(self) -> Self::IntoIter {
self.rows()
}
}
impl<'a> Index<usize> for Matrix<'a> {
type Output = [Expression<'a>];
fn index(&self, row: usize) -> &Self::Output {
self.rows().nth(row).expect("index out of bounds")
}
}
impl<'a> Index<[usize; 2]> for Matrix<'a> {
type Output = Expression<'a>;
fn index(&self, idx: [usize; 2]) -> &Self::Output {
let [x, y] = idx;
assert!(x < self.num_cols, "index out of bounds");
&self.cells[x + self.num_cols * y]
}
}
#[derive(Debug, Clone)]
pub struct MatrixRows<'a, 'b>(ChunksExact<'b, Expression<'a>>);
impl<'a, 'b> Iterator for MatrixRows<'a, 'b> {
type Item = &'b [Expression<'a>];
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn count(self) -> usize {
self.len()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.0.nth(n)
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
}
impl FusedIterator for MatrixRows<'_, '_> {}
impl DoubleEndedIterator for MatrixRows<'_, '_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.0.nth_back(n)
}
}
impl ExactSizeIterator for MatrixRows<'_, '_> {}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub enum Simple<'a> {
#[default]
Missing,
Number(&'a str),
Text(&'a str),
Ident(&'a str),
Symbol(&'a str),
Unary(SimpleUnary<'a>),
Func(SimpleFunc<'a>),
Binary(SimpleBinary<'a>),
Group(Group<'a>),
Matrix(Matrix<'a>),
}
impl Simple<'_> {
#[must_use]
pub fn as_option(&self) -> Option<&Self> {
match self {
Simple::Missing => None,
simple => Some(simple),
}
}
}
macro_rules! simple_from {
($from:ty => $to:ident) => {
impl<'a> From<$from> for Simple<'a> {
fn from(inp: $from) -> Self {
Simple::$to(inp)
}
}
};
}
simple_from!(SimpleUnary<'a> => Unary);
simple_from!(SimpleFunc<'a> => Func);
simple_from!(SimpleBinary<'a> => Binary);
simple_from!(Group<'a> => Group);
simple_from!(Matrix<'a> => Matrix);
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub enum Script<'a> {
#[default]
None,
Sub(Simple<'a>),
Super(Simple<'a>),
Subsuper(Simple<'a>, Simple<'a>),
}
impl<'a> Script<'a> {
#[must_use]
pub fn sub(&self) -> Option<&Simple<'a>> {
match self {
Script::Sub(sub) | Script::Subsuper(sub, _) => Some(sub),
_ => None,
}
}
#[must_use]
pub fn sup(&self) -> Option<&Simple<'a>> {
match self {
Script::Super(sup) | Script::Subsuper(_, sup) => Some(sup),
_ => None,
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct SimpleScript<'a> {
pub simple: Simple<'a>,
pub script: Script<'a>,
}
impl<'a> SimpleScript<'a> {
pub fn new<S>(simple: S, script: Script<'a>) -> Self
where
S: Into<Simple<'a>>,
{
SimpleScript {
simple: simple.into(),
script,
}
}
pub fn without_scripts<S>(simple: S) -> Self
where
S: Into<Simple<'a>>,
{
Self::new(simple, Script::None)
}
pub fn with_sub<S, Sub>(simple: S, sub: Sub) -> Self
where
S: Into<Simple<'a>>,
Sub: Into<Simple<'a>>,
{
Self::new(simple, Script::Sub(sub.into()))
}
pub fn with_super<S, Sup>(simple: S, sup: Sup) -> Self
where
S: Into<Simple<'a>>,
Sup: Into<Simple<'a>>,
{
Self::new(simple, Script::Super(sup.into()))
}
pub fn with_subsuper<S, Sub, Sup>(simple: S, sub: Sub, sup: Sup) -> Self
where
S: Into<Simple<'a>>,
Sub: Into<Simple<'a>>,
Sup: Into<Simple<'a>>,
{
Self::new(simple, Script::Subsuper(sub.into(), sup.into()))
}
}
impl<'a, S> From<S> for SimpleScript<'a>
where
S: Into<Simple<'a>>,
{
fn from(inp: S) -> Self {
SimpleScript::without_scripts(inp.into())
}
}
impl<'a> Deref for SimpleScript<'a> {
type Target = Script<'a>;
fn deref(&self) -> &Self::Target {
&self.script
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Func<'a> {
pub func: &'a str,
pub script: Script<'a>,
arg: Box<ScriptFunc<'a>>,
}
impl<'a> Func<'a> {
pub fn new<Arg>(func: &'a str, script: Script<'a>, arg: Arg) -> Self
where
Arg: Into<ScriptFunc<'a>>,
{
Func {
func,
script,
arg: Box::new(arg.into()),
}
}
pub fn without_scripts<Arg>(func: &'a str, arg: Arg) -> Self
where
Arg: Into<ScriptFunc<'a>>,
{
Self::new(func, Script::None, arg)
}
pub fn with_sub<Sub, Arg>(func: &'a str, sub: Sub, arg: Arg) -> Self
where
Sub: Into<Simple<'a>>,
Arg: Into<ScriptFunc<'a>>,
{
Self::new(func, Script::Sub(sub.into()), arg)
}
pub fn with_super<Sup, Arg>(func: &'a str, sup: Sup, arg: Arg) -> Self
where
Sup: Into<Simple<'a>>,
Arg: Into<ScriptFunc<'a>>,
{
Self::new(func, Script::Super(sup.into()), arg)
}
pub fn with_subsuper<Sub, Sup, Arg>(func: &'a str, sub: Sub, sup: Sup, arg: Arg) -> Self
where
Sub: Into<Simple<'a>>,
Sup: Into<Simple<'a>>,
Arg: Into<ScriptFunc<'a>>,
{
Self::new(func, Script::Subsuper(sub.into(), sup.into()), arg)
}
#[must_use]
pub fn arg(&self) -> &ScriptFunc<'a> {
&self.arg
}
}
impl<'a> Deref for Func<'a> {
type Target = Script<'a>;
fn deref(&self) -> &Self::Target {
&self.script
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ScriptFunc<'a> {
Simple(SimpleScript<'a>),
Func(Func<'a>),
}
impl Default for ScriptFunc<'_> {
fn default() -> Self {
ScriptFunc::Simple(SimpleScript::default())
}
}
impl<'a> From<Func<'a>> for ScriptFunc<'a> {
fn from(func: Func<'a>) -> Self {
ScriptFunc::Func(func)
}
}
impl<'a, S> From<S> for ScriptFunc<'a>
where
S: Into<SimpleScript<'a>>,
{
fn from(inp: S) -> Self {
ScriptFunc::Simple(inp.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Frac<'a> {
pub numer: ScriptFunc<'a>,
pub denom: ScriptFunc<'a>,
}
impl<'a> Frac<'a> {
pub fn new<N, D>(numer: N, denom: D) -> Self
where
N: Into<ScriptFunc<'a>>,
D: Into<ScriptFunc<'a>>,
{
Frac {
numer: numer.into(),
denom: denom.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Intermediate<'a> {
ScriptFunc(ScriptFunc<'a>),
Frac(Frac<'a>),
}
impl Default for Intermediate<'_> {
fn default() -> Self {
Intermediate::ScriptFunc(ScriptFunc::default())
}
}
impl<'a> From<Frac<'a>> for Intermediate<'a> {
fn from(frac: Frac<'a>) -> Self {
Intermediate::Frac(frac)
}
}
impl<'a, S> From<S> for Intermediate<'a>
where
S: Into<ScriptFunc<'a>>,
{
fn from(inp: S) -> Self {
Intermediate::ScriptFunc(inp.into())
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Expression<'a>(Box<[Intermediate<'a>]>);
impl<'a> Deref for Expression<'a> {
type Target = [Intermediate<'a>];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a, I> FromIterator<I> for Expression<'a>
where
I: Into<Intermediate<'a>>,
{
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = I>,
{
Expression(iter.into_iter().map(std::convert::Into::into).collect())
}
}
impl<'a, B> From<B> for Expression<'a>
where
B: Into<Box<[Intermediate<'a>]>>,
{
fn from(inp: B) -> Self {
Expression(inp.into())
}
}