From aac3549a72663c523a456b2f5d7c3b77f509cdd6 Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Thu, 14 Jan 2021 11:42:55 +0000 Subject: Add labelled expressions. Restructure project (again). Convert `Cat` and `Alt` from binary to n+2-ary. --- src/nibble/cst.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 16 deletions(-) (limited to 'src/nibble/cst.rs') diff --git a/src/nibble/cst.rs b/src/nibble/cst.rs index 2b52678..f6fa51b 100644 --- a/src/nibble/cst.rs +++ b/src/nibble/cst.rs @@ -4,14 +4,14 @@ use syn::{ ext::IdentExt, parenthesized, parse::{Parse, ParseStream}, - punctuated::Punctuated, + punctuated::{Pair, Punctuated}, token::{Bracket, Comma, Let, Match, Paren}, LitStr, Token, }; -use crate::chomp::ast; +use crate::chomp::{Name, ast}; -use super::convert::{Context, Convert}; +use super::convert::{Context, Convert, ConvertError}; pub type Epsilon = Token![_]; @@ -134,6 +134,19 @@ pub enum Term { 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(); @@ -169,8 +182,74 @@ impl Parse for Cat { } } +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)), + }) + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +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 }) + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Labelled { + pub cat: Cat, + pub label: Option