pub mod convert; 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::{Name, ast::{self, TopLevel}}; 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)] pub struct Fix { bang_token: Token![!], pub expr: Box, } impl Fix { pub fn span(&self) -> Option { self.bang_token.span.join(self.expr.span()?) } } impl Parse for Fix { fn parse(input: ParseStream<'_>) -> syn::Result { let bang_token = input.parse()?; let expr = input.parse()?; Ok(Self { bang_token, expr }) } } impl fmt::Debug for Fix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Fix").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), 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::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(Token![!]) { input.parse().map(Self::Fix) } else if lookahead.peek(Paren) { input.parse().map(Self::Parens) } else if lookahead.peek(Ident::peek_any) { input.call(Ident::parse_any).map(Self::Ident) } 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::Fix(x) => write!(f, "Term::Fix({:?})", x), Term::Parens(p) => write!(f, "Term::Parens({:?})", p), } } } #[derive(Clone, Debug)] pub struct Call(pub Vec); impl Call { pub fn span(&self) -> Option { let mut iter = self.0.iter(); let first = iter.next()?.span()?; iter.try_fold(first, |span, t| t.span().and_then(|s| span.join(s))) } } impl Parse for Call { fn parse(input: ParseStream<'_>) -> syn::Result { let mut out = Vec::new(); out.push(input.parse()?); loop { let lookahead = input.lookahead1(); if lookahead.peek(Token![_]) || lookahead.peek(LitStr) || lookahead.peek(Token![!]) || lookahead.peek(Paren) || lookahead.peek(Ident::peek_any) { out.push(input.parse()?); } else { break; } } Ok(Self(out)) } } #[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