From d93ba45b0a952dea06f5cc5326eefb0818525912 Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Fri, 30 Apr 2021 14:36:54 +0100 Subject: Move items in `nibble::cst` to `nibble` --- src/nibble/mod.rs | 474 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 473 insertions(+), 1 deletion(-) (limited to 'src/nibble/mod.rs') diff --git a/src/nibble/mod.rs b/src/nibble/mod.rs index 41e895c..3f5c892 100644 --- a/src/nibble/mod.rs +++ b/src/nibble/mod.rs @@ -1,2 +1,474 @@ pub mod convert; -pub mod cst; + +use std::fmt; + +use proc_macro2::Span; +use syn::{ + bracketed, + ext::IdentExt, + parenthesized, + parse::{Parse, ParseStream}, + punctuated::{Pair, Punctuated}, + token::{Bracket, Comma, Let, Match, Paren}, + LitStr, Token, +}; + +use crate::chomp::{ast, Name}; + +use convert::{Context, Convert, ConvertError}; + +pub type Epsilon = Token![_]; + +pub type Ident = syn::Ident; + +pub type Literal = LitStr; + +#[derive(Clone)] +pub struct ArgList { + paren_token: Paren, + args: Punctuated, +} + +impl ArgList { + pub fn span(&self) -> Span { + self.paren_token.span + } + + pub fn len(&self) -> usize { + self.args.len() + } + + pub fn is_empty(&self) -> bool { + self.args.is_empty() + } +} + +impl IntoIterator for ArgList { + type Item = T; + + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.args.into_iter() + } +} + +impl Parse for ArgList { + fn parse(input: ParseStream<'_>) -> syn::Result { + let args; + let paren_token = parenthesized!(args in input); + let args = args.call(Punctuated::parse_terminated)?; + Ok(Self { paren_token, args }) + } +} + +impl fmt::Debug for ArgList { + 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, +} + +impl Call { + pub fn span(&self) -> Option { + self.name.span().join(self.args.span()) + } +} + +impl Parse for Call { + fn parse(input: ParseStream<'_>) -> syn::Result { + let name = input.call(Ident::parse_any)?; + let args = input.parse()?; + Ok(Self { name, args }) + } +} + +#[derive(Clone)] +pub struct Fix { + bracket_token: Bracket, + pub arg: Ident, + paren_token: Paren, + pub expr: Expression, +} + +impl Fix { + pub fn span(&self) -> Option { + self.bracket_token.span.join(self.paren_token.span) + } +} + +impl Parse for Fix { + fn parse(input: ParseStream<'_>) -> syn::Result { + let arg; + let bracket_token = bracketed!(arg in input); + let arg = arg.call(Ident::parse_any)?; + let expr; + let paren_token = parenthesized!(expr in input); + let expr = expr.parse()?; + Ok(Self { + bracket_token, + arg, + paren_token, + expr, + }) + } +} + +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, + pub expr: Expression, +} + +impl Parse for ParenExpression { + fn parse(input: ParseStream<'_>) -> syn::Result { + let expr; + let paren_token = parenthesized!(expr in input); + let expr = expr.parse()?; + Ok(Self { paren_token, expr }) + } +} + +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), + Ident(Ident), + Literal(Literal), + Call(Call), + Fix(Fix), + Parens(ParenExpression), +} + +impl Term { + pub fn span(&self) -> Option { + match self { + Self::Epsilon(e) => Some(e.span), + Self::Ident(i) => Some(i.span()), + Self::Literal(l) => Some(l.span()), + Self::Call(c) => c.span(), + Self::Fix(f) => f.span(), + Self::Parens(p) => Some(p.paren_token.span), + } + } +} + +impl Parse for Term { + fn parse(input: ParseStream<'_>) -> syn::Result { + let lookahead = input.lookahead1(); + + if lookahead.peek(Token![_]) { + input.parse().map(Self::Epsilon) + } else if lookahead.peek(LitStr) { + input.parse().map(Self::Literal) + } else if lookahead.peek(Bracket) { + input.parse().map(Self::Fix) + } else if lookahead.peek(Paren) { + input.parse().map(Self::Parens) + } else if lookahead.peek(Ident::peek_any) { + let name = input.call(Ident::parse_any)?; + + if input.peek(Paren) { + input.parse().map(|args| Self::Call(Call { name, args })) + } else { + Ok(Self::Ident(name)) + } + } else { + Err(lookahead.error()) + } + } +} + +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); + +impl Parse for Cat { + fn parse(input: ParseStream<'_>) -> syn::Result { + input.call(Punctuated::parse_separated_nonempty).map(Self) + } +} + +impl Cat { + pub fn span(&self) -> Option { + 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 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![:], + pub label: Ident, +} + +impl Label { + pub fn span(&self) -> Option { + self.colon_tok.span.join(self.label.span()) + } +} + +impl Parse for Label { + fn parse(input: ParseStream<'_>) -> syn::Result { + let colon_tok = input.parse()?; + let label = input.call(Ident::parse_any)?; + Ok(Self { colon_tok, label }) + } +} + +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