summaryrefslogtreecommitdiff
path: root/src/nibble
diff options
context:
space:
mode:
authorGreg Brown <gmb60@cam.ac.uk>2021-01-21 09:42:02 +0000
committerGreg Brown <gmb60@cam.ac.uk>2021-01-21 17:45:02 +0000
commit1a93b1f82bc8c21d24e67031c5eca96830e928c7 (patch)
tree4c3fbfac9f0fbbc31defee03cd460e0400278d30 /src/nibble
parentfaa3f30deb32d0a1fd7cb196559762635b22ecfd (diff)
Fix many warnings.
Diffstat (limited to 'src/nibble')
-rw-r--r--src/nibble/convert.rs115
-rw-r--r--src/nibble/cst.rs103
2 files changed, 157 insertions, 61 deletions
diff --git a/src/nibble/convert.rs b/src/nibble/convert.rs
index 3310b2a..bfa0be2 100644
--- a/src/nibble/convert.rs
+++ b/src/nibble/convert.rs
@@ -1,7 +1,7 @@
-use std::{collections::HashMap, fmt};
+use std::{collections::HashMap, fmt, mem};
use proc_macro2::Span;
-use syn::punctuated::Pair;
+use syn::{punctuated::Pair, Token};
use crate::chomp::{
ast::{self, NamedExpression},
@@ -41,7 +41,9 @@ impl Context {
// we make variable binding cheaper by inserting wrong and pulling right.
match self.names.get(&name.to_string()).copied() {
Some(Binding::Variable(index)) => Some(Binding::Variable(self.vars - index - 1)),
- x => x,
+ Some(Binding::Parameter(index)) => Some(Binding::Parameter(index)),
+ Some(Binding::Global) => Some(Binding::Global),
+ None => None,
}
}
@@ -68,7 +70,9 @@ impl Context {
#[derive(Clone, Debug)]
pub enum ConvertError {
- UndeclaredName(Name),
+ UndeclaredName(Box<Name>),
+ EmptyCat(Option<Span>),
+ EmptyAlt(Option<Span>),
}
impl From<ConvertError> for syn::Error {
@@ -76,6 +80,7 @@ impl From<ConvertError> for syn::Error {
let msg = e.to_string();
let span = match e {
ConvertError::UndeclaredName(name) => name.span(),
+ ConvertError::EmptyCat(span) | ConvertError::EmptyAlt(span) => span,
};
Self::new(span.unwrap_or_else(Span::call_site), msg)
@@ -88,6 +93,12 @@ impl fmt::Display for ConvertError {
Self::UndeclaredName(name) => {
write!(f, "undeclared name: `{}`", name)
}
+ Self::EmptyCat(_) => {
+ write!(f, "concatenation has no elements")
+ }
+ Self::EmptyAlt(_) => {
+ write!(f, "alternation has no elements")
+ }
}
}
}
@@ -105,7 +116,7 @@ impl Convert for Ident {
let binding = context
.lookup(&name)
- .ok_or_else(|| ConvertError::UndeclaredName(name.clone()))?;
+ .ok_or_else(|| ConvertError::UndeclaredName(Box::new(name.clone())))?;
Ok(match binding {
Binding::Variable(index) => NamedExpression {
@@ -198,42 +209,37 @@ impl Convert for Term {
impl Convert for Cat {
fn convert(self, context: &mut Context) -> Result<NamedExpression, ConvertError> {
+ fn convert_pair(
+ pair: Pair<Term, Token![.]>,
+ context: &mut Context,
+ ) -> Result<(NamedExpression, Option<Span>), ConvertError> {
+ match pair {
+ Pair::Punctuated(t, p) => t.convert(context).map(|expr| (expr, Some(p.span))),
+ Pair::End(t) => t.convert(context).map(|expr| (expr, None)),
+ }
+ }
+
+ let span = self.span();
let mut iter = self.0.into_pairs();
- let (first, punct) = match iter.next().unwrap() {
- Pair::Punctuated(t, p) => (t.convert(context)?, Some(p.span)),
- Pair::End(t) => (t.convert(context)?, None),
- };
+ let (first, mut punct) = iter
+ .next()
+ .ok_or(ConvertError::EmptyCat(span))
+ .and_then(|pair| convert_pair(pair, context))?;
- let mut rest = Vec::new();
- let (span, _) = iter.try_fold(
- (
- first.span.and_then(|s| punct.and_then(|p| s.join(p))),
- punct,
- ),
- |(span, punct), pair| {
- let (snd, p) = match pair {
- Pair::Punctuated(t, p) => (t.convert(context)?, Some(p.span)),
- Pair::End(t) => (t.convert(context)?, None),
- };
-
- let span = span
- .and_then(|s| snd.span.and_then(|t| s.join(t)))
- .and_then(|s| p.and_then(|p| s.join(p)));
- rest.push((punct, snd));
- Ok((span, p))
- },
- )?;
+ let mut rest = iter.map(|pair| {
+ convert_pair(pair, context).map(|(snd, p)| (mem::replace(&mut punct, p), snd))
+ });
- let mut iter = rest.into_iter();
- if let Some((punct, second)) = iter.next() {
+ if let Some(res) = rest.next() {
+ let (punct, second) = res?;
Ok(NamedExpression {
name: None,
expr: ast::Cat {
first: Box::new(first),
punct,
second: Box::new(second),
- rest: iter.collect(),
+ rest: rest.collect::<Result<_, _>>()?,
}
.into(),
span,
@@ -260,42 +266,37 @@ impl Convert for Labelled {
impl Convert for Alt {
fn convert(self, context: &mut Context) -> Result<NamedExpression, ConvertError> {
+fn convert_pair(
+ pair: Pair<Labelled, Token![|]>,
+ context: &mut Context,
+ ) -> Result<(NamedExpression, Option<Span>), ConvertError> {
+ match pair {
+ Pair::Punctuated(t, p) => t.convert(context).map(|expr| (expr, Some(p.span))),
+ Pair::End(t) => t.convert(context).map(|expr| (expr, None)),
+ }
+ }
+
+ let span = self.span();
let mut iter = self.0.into_pairs();
- let (first, punct) = match iter.next().unwrap() {
- Pair::Punctuated(t, p) => (t.convert(context)?, Some(p.span)),
- Pair::End(t) => (t.convert(context)?, None),
- };
+ let (first, mut punct) = iter
+ .next()
+ .ok_or(ConvertError::EmptyAlt(span))
+ .and_then(|pair| convert_pair(pair, context))?;
- let mut rest = Vec::new();
- let (span, _) = iter.try_fold(
- (
- first.span.and_then(|s| punct.and_then(|p| s.join(p))),
- punct,
- ),
- |(span, punct), pair| {
- let (snd, p) = match pair {
- Pair::Punctuated(t, p) => (t.convert(context)?, Some(p.span)),
- Pair::End(t) => (t.convert(context)?, None),
- };
-
- let span = span
- .and_then(|s| snd.span.and_then(|t| s.join(t)))
- .and_then(|s| p.and_then(|p| s.join(p)));
- rest.push((punct, snd));
- Ok((span, p))
- },
- )?;
+ let mut rest = iter.map(|pair| {
+ convert_pair(pair, context).map(|(snd, p)| (mem::replace(&mut punct, p), snd))
+ });
- let mut iter = rest.into_iter();
- if let Some((punct, second)) = iter.next() {
+ if let Some(res) = rest.next() {
+ let (punct, second) = res?;
Ok(NamedExpression {
name: None,
expr: ast::Alt {
first: Box::new(first),
punct,
second: Box::new(second),
- rest: iter.collect(),
+ rest: rest.collect::<Result<_, _>>()?,
}
.into(),
span,
diff --git a/src/nibble/cst.rs b/src/nibble/cst.rs
index fc698e8..d8b71b7 100644
--- a/src/nibble/cst.rs
+++ b/src/nibble/cst.rs
@@ -1,3 +1,5 @@
+use std::fmt;
+
use proc_macro2::Span;
use syn::{
bracketed,
@@ -58,7 +60,14 @@ impl<T: Parse> Parse for ArgList<T> {
}
}
-#[derive(Clone)]
+impl<T: fmt::Debug> fmt::Debug for ArgList<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "ArgList")?;
+ f.debug_list().entries(self.args.iter()).finish()
+ }
+}
+
+#[derive(Clone, Debug)]
pub struct Call {
pub name: Ident,
pub args: ArgList<Expression>,
@@ -109,6 +118,15 @@ impl Parse for Fix {
}
}
+impl fmt::Debug for Fix {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Fix")
+ .field("arg", &self.arg)
+ .field("expr", &self.expr)
+ .finish()
+ }
+}
+
#[derive(Clone)]
pub struct ParenExpression {
paren_token: Paren,
@@ -124,6 +142,14 @@ impl Parse for ParenExpression {
}
}
+impl fmt::Debug for ParenExpression {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("ParenExpression")
+ .field("expr", &self.expr)
+ .finish()
+ }
+}
+
#[derive(Clone)]
pub enum Term {
Epsilon(Epsilon),
@@ -173,6 +199,19 @@ impl Parse for Term {
}
}
+impl fmt::Debug for Term {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Term::Epsilon(_) => write!(f, "Term::Epsilon"),
+ Term::Ident(i) => write!(f, "Term::Ident({:?})", i),
+ Term::Literal(l) => write!(f, "Term::Literal({:?})", l.value()),
+ Term::Call(c) => write!(f, "Term::Call({:?})", c),
+ Term::Fix(x) => write!(f, "Term::Fix({:?})", x),
+ Term::Parens(p) => write!(f, "Term::Parens({:?})", p),
+ }
+ }
+}
+
#[derive(Clone)]
pub struct Cat(pub Punctuated<Term, Token![.]>);
@@ -200,6 +239,13 @@ impl Cat {
}
}
+impl fmt::Debug for Cat {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Cat")?;
+ f.debug_list().entries(self.0.iter()).finish()
+ }
+}
+
#[derive(Clone)]
pub struct Label {
colon_tok: Token![:],
@@ -220,7 +266,13 @@ impl Parse for Label {
}
}
-#[derive(Clone)]
+impl fmt::Debug for Label {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Label").field("label", &self.label).finish()
+ }
+}
+
+#[derive(Clone, Debug)]
pub struct Labelled {
pub cat: Cat,
pub label: Option<Label>,
@@ -251,12 +303,37 @@ impl Parse for Labelled {
#[derive(Clone)]
pub struct Alt(pub Punctuated<Labelled, Token![|]>);
+impl Alt {
+ pub fn span(&self) -> Option<Span> {
+ let mut iter = self.0.pairs();
+ let span = match iter.next()? {
+ Pair::Punctuated(t, p) => t.span().and_then(|s| s.join(p.span)),
+ Pair::End(t) => t.span(),
+ }?;
+
+ iter.try_fold(span, |span, pair| match pair {
+ Pair::Punctuated(t, p) => t
+ .span()
+ .and_then(|s| span.join(s))
+ .and_then(|s| s.join(p.span)),
+ Pair::End(t) => t.span().and_then(|s| span.join(s)),
+ })
+ }
+}
+
impl Parse for Alt {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
input.call(Punctuated::parse_separated_nonempty).map(Self)
}
}
+impl fmt::Debug for Alt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Alt")?;
+ f.debug_list().entries(self.0.iter()).finish()
+ }
+}
+
pub type Expression = Alt;
#[derive(Clone)]
@@ -299,6 +376,16 @@ impl Parse for LetStatement {
}
}
+impl fmt::Debug for LetStatement {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("LetStatement")
+ .field("name", &self.name)
+ .field("args", &self.args)
+ .field("expr", &self.expr)
+ .finish()
+ }
+}
+
#[derive(Clone)]
pub struct GoalStatement {
match_token: Token![match],
@@ -320,7 +407,15 @@ impl Parse for GoalStatement {
}
}
-#[derive(Clone)]
+impl fmt::Debug for GoalStatement {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("GoalStatement")
+ .field("expr", &self.expr)
+ .finish()
+ }
+}
+
+#[derive(Clone, Debug)]
pub struct File {
lets: Vec<LetStatement>,
goal: GoalStatement,
@@ -336,7 +431,7 @@ impl File {
let params = stmt
.args
.into_iter()
- .flat_map(|args| args.into_iter())
+ .flat_map(ArgList::into_iter)
.map(Name::from);
let mut context = Context::new(&names, params.clone());
let mut expr = stmt.expr.convert(&mut context)?;