From e1452227b8bd9ad3805480f8a5a66a75fb8370dd Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Fri, 8 Jan 2021 18:00:11 +0000 Subject: Do more restructuring. --- src/chomp/ast.rs | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 177 insertions(+), 17 deletions(-) (limited to 'src/chomp/ast.rs') diff --git a/src/chomp/ast.rs b/src/chomp/ast.rs index e8e3309..58d76c9 100644 --- a/src/chomp/ast.rs +++ b/src/chomp/ast.rs @@ -1,11 +1,80 @@ -use std::fmt::{self, Display}; +use std::{ + fmt::{self, Display}, + hash, +}; use proc_macro2::Span; use syn::{Ident, LitStr, Token}; -pub type Epsilon = Token![_]; +use super::Name; -pub type Literal = LitStr; +pub type Epsilon = Option; + +#[derive(Clone, Debug)] +pub enum Literal { + Spanned(LitStr), + Spanless(String), +} + +impl Literal { + pub fn value(&self) -> String { + match self { + Self::Spanned(l) => l.value(), + Self::Spanless(s) => s.clone(), + } + } + + pub fn span(&self) -> Option { + match self { + Self::Spanned(l) => Some(l.span()), + Self::Spanless(_) => None, + } + } + + pub fn as_litstr(self, span: Span) -> LitStr { + match self { + Self::Spanned(l) => l, + Self::Spanless(s) => LitStr::new(&s, span), + } + } +} + +impl PartialEq for Literal { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Spanned(me), Self::Spanned(them)) => me == them, + (Self::Spanned(me), Self::Spanless(them)) => &me.value() == them, + (Self::Spanless(me), Self::Spanned(them)) => me == &them.value(), + (Self::Spanless(me), Self::Spanless(them)) => me == them, + } + } +} + +impl Eq for Literal {} + +impl hash::Hash for Literal { + fn hash(&self, state: &mut H) { + self.value().hash(state) + } +} + +impl Display for Literal { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.value()) + } +} + +impl From for Literal { + fn from(l: LitStr) -> Self { + Self::Spanned(l) + } +} + +impl From for Literal { + fn from(s: String) -> Self { + Self::Spanless(s) + } +} #[derive(Clone, Debug)] pub struct Cat { @@ -50,6 +119,14 @@ impl Display for Cat { } } +impl PartialEq for Cat { + fn eq(&self, other: &Self) -> bool { + self.first() == other.first() && self.second() == other.second() + } +} + +impl Eq for Cat {} + #[derive(Clone, Debug)] pub struct Alt { pub left: Box, @@ -93,15 +170,23 @@ impl Display for Alt { } } +impl PartialEq for Alt { + fn eq(&self, other: &Self) -> bool { + self.left() == other.left() && self.right() == other.right() + } +} + +impl Eq for Alt {} + #[derive(Clone, Debug)] pub struct Fix { - pub arg: Ident, + pub arg: Name, pub inner: Box, pub span: Option, } impl Fix { - pub fn new(arg: Ident, inner: Expression, span: Option) -> Self { + pub fn new(arg: Name, inner: Expression, span: Option) -> Self { Self { arg, inner: Box::new(inner), @@ -109,7 +194,7 @@ impl Fix { } } - pub fn arg(&self) -> &Ident { + pub fn arg(&self) -> &Name { &self.arg } @@ -132,18 +217,26 @@ impl Display for Fix { } } -#[derive(Clone, Debug)] +impl PartialEq for Fix { + fn eq(&self, other: &Self) -> bool { + self.inner() == other.inner() + } +} + +impl Eq for Fix {} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Variable { - pub name: Ident, + pub name: Name, pub index: usize, } impl Variable { - pub fn new(name: Ident, index: usize) -> Self { + pub fn new(name: Name, index: usize) -> Self { Self { name, index } } - pub fn name(&self) -> &Ident { + pub fn name(&self) -> &Name { &self.name } @@ -162,18 +255,18 @@ impl Display for Variable { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Parameter { - pub name: Ident, + pub name: Name, pub index: usize, } impl Parameter { - pub fn new(name: Ident, index: usize) -> Self { + pub fn new(name: Name, index: usize) -> Self { Self { name, index } } - pub fn name(&self) -> &Ident { + pub fn name(&self) -> &Name { &self.name } @@ -188,7 +281,7 @@ impl Parameter { impl Display for Parameter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.name.fmt(f) + write!(f, "{}", self.name) } } @@ -242,6 +335,14 @@ impl Display for Call { } } +impl PartialEq for Call { + fn eq(&self, other: &Self) -> bool { + self.name() == other.name() && self.args() == other.args() + } +} + +impl Eq for Call {} + #[derive(Clone, Debug)] pub enum Expression { /// Matches the empty string. @@ -266,7 +367,7 @@ impl Display for Expression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Epsilon(_) => write!(f, "_"), - Self::Literal(l) => write!(f, "{:?}", l.value()), + Self::Literal(l) => l.fmt(f), Self::Cat(c) => c.fmt(f), Self::Alt(a) => a.fmt(f), Self::Fix(x) => x.fmt(f), @@ -277,6 +378,65 @@ impl Display for Expression { } } +impl PartialEq for Expression { + fn eq(&self, other: &Self) -> bool { + match self { + Self::Epsilon(_) => matches!(other, Self::Epsilon(_)), + Self::Literal(l) => { + if let Self::Literal(them) = other { + l == them + } else { + false + } + } + Self::Cat(c) => { + if let Self::Cat(them) = other { + c == them + } else { + false + } + } + Self::Alt(a) => { + if let Self::Alt(them) = other { + a == them + } else { + false + } + } + Self::Fix(f) => { + if let Self::Fix(them) = other { + f == them + } else { + false + } + } + Self::Variable(v) => { + if let Self::Variable(them) = other { + v == them + } else { + false + } + } + Self::Parameter(p) => { + if let Self::Parameter(them) = other { + p == them + } else { + false + } + } + Self::Call(c) => { + if let Self::Call(them) = other { + c == them + } else { + false + } + } + } + } +} + +impl Eq for Expression {} + impl From for Expression { fn from(eps: Epsilon) -> Self { Self::Epsilon(eps) @@ -334,7 +494,7 @@ pub struct Function { } impl Function { - pub fn new(name: Ident, params: usize, expr: Expression, span: Option) -> Self { + pub const fn new(name: Ident, params: usize, expr: Expression, span: Option) -> Self { Self { name, params, -- cgit v1.2.3