summaryrefslogtreecommitdiff
path: root/src/nibble
diff options
context:
space:
mode:
Diffstat (limited to 'src/nibble')
-rw-r--r--src/nibble/convert.rs165
-rw-r--r--src/nibble/cst.rs294
-rw-r--r--src/nibble/mod.rs539
3 files changed, 509 insertions, 489 deletions
diff --git a/src/nibble/convert.rs b/src/nibble/convert.rs
new file mode 100644
index 0000000..3e47208
--- /dev/null
+++ b/src/nibble/convert.rs
@@ -0,0 +1,165 @@
+use std::collections::HashMap;
+
+use syn::punctuated::Pair;
+
+use crate::chomp::ast;
+
+use super::cst::{Alt, Call, Cat, Fix, Ident, ParenExpression, Term};
+
+#[derive(Clone, Copy, Debug)]
+pub enum Binding {
+ Variable(usize),
+ Parameter(usize),
+ Global,
+}
+
+#[derive(Debug)]
+pub struct Context {
+ names: HashMap<String, Binding>,
+ vars: usize,
+}
+
+impl Context {
+ pub fn new<I: IntoIterator<Item = Ident>>(globals: &[Ident], params: I) -> Self {
+ let mut names = HashMap::new();
+ for global in globals {
+ names.insert(global.to_string(), Binding::Global);
+ }
+
+ for (index, param) in params.into_iter().enumerate() {
+ names.insert(param.to_string(), Binding::Parameter(index));
+ }
+
+ Self { names, vars: 0 }
+ }
+
+ pub fn lookup(&self, name: &Ident) -> Option<Binding> {
+ // 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,
+ }
+ }
+
+ pub fn with_variable<F: FnOnce(&mut Self) -> R, R>(&mut self, name: &Ident, f: F) -> R {
+ let old = self
+ .names
+ .insert(name.to_string(), Binding::Variable(self.vars));
+
+ // we make variable binding cheaper by inserting wrong and pulling right.
+ // we should increment all values in names instead, but that's slow
+ self.vars += 1;
+ let res = f(self);
+ self.vars -= 1;
+
+ if let Some(val) = old {
+ self.names.insert(name.to_string(), val);
+ } else {
+ self.names.remove(&name.to_string());
+ }
+
+ res
+ }
+}
+
+pub trait Convert {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression>;
+}
+
+impl Convert for Ident {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ let span = self.span();
+
+ match context.lookup(&self)? {
+ Binding::Variable(index) => Some(ast::Variable::new(self, index).into()),
+ Binding::Parameter(index) => Some(ast::Parameter::new(self, index).into()),
+ Binding::Global => Some(ast::Call::new(self, Vec::new(), Some(span)).into()),
+ }
+ }
+}
+
+impl Convert for Call {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ let span = self.span();
+ let args = self
+ .args
+ .into_iter()
+ .map(|arg| arg.convert(context))
+ .collect::<Option<_>>()?;
+ Some(ast::Call::new(self.name, args, span).into())
+ }
+}
+
+impl Convert for Fix {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ let span = self.span();
+ let expr = self.expr;
+ let inner = context.with_variable(&self.arg, |context| expr.convert(context))?;
+ Some(ast::Fix::new(self.arg, inner, span).into())
+ }
+}
+
+impl Convert for ParenExpression {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ self.expr.convert(context)
+ }
+}
+
+impl Convert for Term {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ match self {
+ Self::Epsilon(e) => Some(e.into()),
+ Self::Ident(i) => i.convert(context),
+ Self::Literal(l) => Some(l.into()),
+ Self::Call(c) => c.convert(context),
+ Self::Fix(f) => f.convert(context),
+ Self::Parens(p) => p.convert(context),
+ }
+ }
+}
+
+impl Convert for Cat {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ let mut iter = self.0.into_pairs();
+ let mut out = match iter.next().unwrap() {
+ Pair::Punctuated(t, p) => (t.convert(context)?, Some(p)),
+ Pair::End(t) => (t.convert(context)?, None),
+ };
+
+ for pair in iter {
+ let (fst, punct) = out;
+ out = match pair {
+ Pair::Punctuated(t, p) => (
+ ast::Cat::new(fst, punct, t.convert(context)?).into(),
+ Some(p),
+ ),
+ Pair::End(t) => (ast::Cat::new(fst, punct, t.convert(context)?).into(), None),
+ };
+ }
+
+ Some(out.0)
+ }
+}
+
+impl Convert for Alt {
+ fn convert(self, context: &mut Context) -> Option<ast::Expression> {
+ let mut iter = self.0.into_pairs();
+ let mut out = match iter.next().unwrap() {
+ Pair::Punctuated(t, p) => (t.convert(context)?, Some(p)),
+ Pair::End(t) => (t.convert(context)?, None),
+ };
+
+ for pair in iter {
+ let (fst, punct) = out;
+ out = match pair {
+ Pair::Punctuated(t, p) => (
+ ast::Alt::new(fst, punct, t.convert(context)?).into(),
+ Some(p),
+ ),
+ Pair::End(t) => (ast::Alt::new(fst, punct, t.convert(context)?).into(), None),
+ };
+ }
+
+ Some(out.0)
+ }
+}
diff --git a/src/nibble/cst.rs b/src/nibble/cst.rs
new file mode 100644
index 0000000..383eae9
--- /dev/null
+++ b/src/nibble/cst.rs
@@ -0,0 +1,294 @@
+use proc_macro2::Span;
+use syn::{
+ bracketed,
+ ext::IdentExt,
+ parenthesized,
+ parse::{Parse, ParseStream},
+ punctuated::Punctuated,
+ token::{Bracket, Comma, Let, Match, Paren},
+ LitStr, Token,
+};
+
+use crate::chomp::ast;
+
+use super::convert::{Context, Convert};
+
+pub type Epsilon = Token![_];
+
+pub type Ident = syn::Ident;
+
+pub type Literal = LitStr;
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ArgList<T> {
+ paren_token: Paren,
+ args: Punctuated<T, Comma>,
+}
+
+impl<T> ArgList<T> {
+ 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<T> IntoIterator for ArgList<T> {
+ type Item = T;
+
+ type IntoIter = <Punctuated<T, Comma> as IntoIterator>::IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.args.into_iter()
+ }
+}
+
+impl<T: Parse> Parse for ArgList<T> {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let args;
+ let paren_token = parenthesized!(args in input);
+ let args = args.call(Punctuated::parse_terminated)?;
+ Ok(Self { paren_token, args })
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Call {
+ pub name: Ident,
+ pub args: ArgList<Expression>,
+}
+
+impl Call {
+ pub fn span(&self) -> Option<Span> {
+ self.name.span().join(self.args.span())
+ }
+}
+
+impl Parse for Call {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let name = input.call(Ident::parse_any)?;
+ let args = input.parse()?;
+ Ok(Self { name, args })
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Fix {
+ bracket_token: Bracket,
+ pub arg: Ident,
+ paren_token: Paren,
+ pub expr: Expression,
+}
+
+impl Fix {
+ pub fn span(&self) -> Option<Span> {
+ self.bracket_token.span.join(self.paren_token.span)
+ }
+}
+
+impl Parse for Fix {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ 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,
+ })
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ParenExpression {
+ paren_token: Paren,
+ pub expr: Expression,
+}
+
+impl Parse for ParenExpression {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let expr;
+ let paren_token = parenthesized!(expr in input);
+ let expr = expr.parse()?;
+ Ok(Self { paren_token, expr })
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Term {
+ Epsilon(Epsilon),
+ Ident(Ident),
+ Literal(Literal),
+ Call(Call),
+ Fix(Fix),
+ Parens(ParenExpression),
+}
+
+impl Parse for Term {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ 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())
+ }
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Cat(pub Punctuated<Term, Token![.]>);
+
+impl Parse for Cat {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ input.call(Punctuated::parse_separated_nonempty).map(Self)
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct Alt(pub Punctuated<Cat, Token![|]>);
+
+impl Parse for Alt {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ input.call(Punctuated::parse_separated_nonempty).map(Self)
+ }
+}
+
+pub type Expression = Alt;
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct LetStatement {
+ let_token: Token![let],
+ name: Ident,
+ args: Option<ArgList<Ident>>,
+ eq_token: Token![=],
+ expr: Expression,
+ semi_token: Token![;],
+}
+
+impl LetStatement {
+ pub fn span(&self) -> Option<Span> {
+ self.let_token.span.join(self.semi_token.span)
+ }
+}
+
+impl Parse for LetStatement {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let let_token = input.parse()?;
+ let name = input.call(Ident::parse_any)?;
+ let args = if input.peek(Paren) {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+ let eq_token = input.parse()?;
+ let expr = input.parse()?;
+ let semi_token = input.parse()?;
+
+ Ok(Self {
+ let_token,
+ name,
+ args,
+ eq_token,
+ expr,
+ semi_token,
+ })
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct GoalStatement {
+ match_token: Token![match],
+ expr: Expression,
+ semi_token: Token![;],
+}
+
+impl Parse for GoalStatement {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let match_token = input.parse()?;
+ let expr = input.parse()?;
+ let semi_token = input.parse()?;
+
+ Ok(Self {
+ match_token,
+ expr,
+ semi_token,
+ })
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct File {
+ lets: Vec<LetStatement>,
+ goal: GoalStatement,
+}
+
+impl File {
+ pub fn convert(self) -> Option<(Vec<ast::Function>, ast::Expression)> {
+ let mut names = Vec::new();
+ let mut map = Vec::new();
+ for stmt in self.lets {
+ let count = stmt.args.as_ref().map(ArgList::len).unwrap_or_default();
+ let span = stmt.span();
+ let mut context = Context::new(
+ &names,
+ stmt.args.into_iter().flat_map(|args| args.into_iter()),
+ );
+ names.push(stmt.name.clone());
+ map.push(ast::Function::new(
+ stmt.name.clone(),
+ count,
+ stmt.expr.convert(&mut context)?,
+ span,
+ ));
+ }
+
+ let mut context = Context::new(&names, Vec::new());
+ let goal = self.goal.expr.convert(&mut context)?;
+ Some((map, goal))
+ }
+}
+
+impl Parse for File {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let mut lets = Vec::new();
+ let mut lookahead = input.lookahead1();
+
+ while lookahead.peek(Let) {
+ lets.push(input.parse()?);
+ lookahead = input.lookahead1();
+ }
+
+ let goal = if lookahead.peek(Match) {
+ input.parse()?
+ } else {
+ return Err(lookahead.error());
+ };
+
+ Ok(Self { lets, goal })
+ }
+}
diff --git a/src/nibble/mod.rs b/src/nibble/mod.rs
index 071b41a..14791fd 100644
--- a/src/nibble/mod.rs
+++ b/src/nibble/mod.rs
@@ -1,489 +1,50 @@
-use std::collections::HashMap;
-use std::rc::Rc;
-
-use crate::ast::{
- self,
- convert::{Context, Convert},
-};
-use proc_macro2::Span;
-use syn::{
- ext::IdentExt,
- parse::{Parse, ParseStream},
- punctuated::{Pair, Punctuated},
- token, Result, Token,
-};
-
-pub type Epsilon = Token![_];
-
-impl Convert for Epsilon {
- fn convert(&self, _: &mut Context) -> ast::Term {
- ast::Term::Epsilon(*self)
- }
-}
-
-type Ident = syn::Ident;
-
-impl Convert for Ident {
- fn convert(&self, context: &mut Context) -> ast::Term {
- use ast::Term;
- let name = self.to_string();
-
- if let Some(binding) = context.get_binding(&name) {
- Term::Binding(ast::Variable::new(self.clone(), binding))
- } else if let Some(variable) = context.get_variable(&name) {
- Term::Variable(ast::Variable::new(self.clone(), variable))
- } else {
- let span = self.span();
- Term::Call(ast::Call::new(self.clone(), Vec::new(), span))
- }
- }
-}
-
-type Literal = syn::LitStr;
-
-impl Convert for Literal {
- fn convert(&self, _: &mut Context) -> ast::Term {
- ast::Term::Literal(self.clone())
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct ArgList<T> {
- paren_token: token::Paren,
- args: Punctuated<T, token::Comma>,
-}
-
-impl<T> ArgList<T> {
- fn span(&self) -> Span {
- self.paren_token.span
- }
-
- fn len(&self) -> usize {
- self.args.len()
- }
-}
-
-impl<T> IntoIterator for ArgList<T> {
- type Item = T;
- type IntoIter = <Punctuated<T, Token![,]> as IntoIterator>::IntoIter;
-
- fn into_iter(self) -> Self::IntoIter {
- self.args.into_iter()
- }
-}
-
-impl<T: Parse> Parse for ArgList<T> {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let args;
- let paren_token = syn::parenthesized!(args in input);
- let args = args.call(Punctuated::parse_terminated)?;
- Ok(Self { paren_token, args })
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Call {
- name: Ident,
- args: ArgList<Expression>,
-}
-
-impl Call {
- fn span(&self) -> Span {
- self.name
- .span()
- .join(self.args.span())
- .unwrap_or_else(Span::call_site)
- }
-}
-
-impl Parse for Call {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let name = input.call(Ident::parse_any)?;
- let args = input.parse()?;
- Ok(Self { name, args })
- }
-}
-
-impl Convert for Call {
- fn convert(&self, context: &mut Context) -> ast::Term {
- use ast::Term;
- let args = self
- .args
- .clone()
- .into_iter()
- .map(|arg| arg.convert(context))
- .collect::<Vec<_>>();
- Term::Call(ast::Call::new(self.name.clone(), args, self.span()))
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Fix {
- bracket_token: token::Bracket,
- arg: Ident,
- paren_token: token::Paren,
- expr: Expression,
-}
-
-impl Fix {
- fn span(&self) -> Span {
- self.bracket_token
- .span
- .join(self.paren_token.span)
- .unwrap_or_else(Span::call_site)
- }
-}
-
-impl Parse for Fix {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let arg;
- let bracket_token = syn::bracketed!(arg in input);
- let arg = arg.call(Ident::parse_any)?;
- let expr;
- let paren_token = syn::parenthesized!(expr in input);
- let expr = expr.parse()?;
- Ok(Self {
- bracket_token,
- arg,
- paren_token,
- expr,
- })
- }
-}
-
-impl Convert for Fix {
- fn convert(&self, context: &mut Context) -> ast::Term {
- use ast::Term;
- let span = self.span();
- let expr = &self.expr;
- let arg_name = self.arg.to_string();
- Term::Fix(ast::Fix::new(
- self.arg.clone(),
- context.with_binding(arg_name, |ctx| expr.convert(ctx)),
- span,
- ))
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct ParenExpression {
- paren_tok: token::Paren,
- expr: Expression,
-}
-
-impl ParenExpression {
- pub fn span(&self) -> Span {
- self.paren_tok.span
- }
-}
-
-impl Parse for ParenExpression {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let expr;
- let paren_tok = syn::parenthesized!(expr in input);
- let expr = expr.parse()?;
- Ok(Self { paren_tok, expr })
- }
-}
-
-impl Convert for ParenExpression {
- fn convert(&self, context: &mut Context) -> ast::Term {
- self.expr.convert(context)
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum Term {
- Epsilon(Epsilon),
- Ident(Ident),
- Literal(Literal),
- Call(Call),
- Fix(Fix),
- Parens(ParenExpression),
-}
-
-impl Term {
- pub fn span(&self) -> Span {
- match self {
- Self::Epsilon(eps) => eps.span,
- Self::Ident(ident) => ident.span(),
- Self::Literal(lit) => lit.span(),
- Self::Call(call) => call.span(),
- Self::Fix(fix) => fix.span(),
- Self::Parens(paren) => paren.span(),
- }
- }
-}
-
-impl Parse for Term {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let lookahead = input.lookahead1();
- if lookahead.peek(Token![_]) {
- input.parse().map(Self::Epsilon)
- } else if lookahead.peek(syn::LitStr) {
- input.parse().map(Self::Literal)
- } else if lookahead.peek(token::Bracket) {
- input.parse().map(Self::Fix)
- } else if lookahead.peek(token::Paren) {
- let content;
- let paren_tok = syn::parenthesized!(content in input);
- content
- .parse()
- .map(|expr| Self::Parens(ParenExpression { paren_tok, expr }))
- } else if lookahead.peek(Ident::peek_any) {
- let name = input.call(Ident::parse_any)?;
- if input.peek(token::Paren) {
- input.parse().map(|args| Self::Call(Call { name, args }))
- } else {
- Ok(Self::Ident(name))
- }
- } else {
- Err(lookahead.error())
- }
- }
-}
-
-impl Convert for Term {
- fn convert(&self, context: &mut Context) -> ast::Term {
- match self {
- Self::Epsilon(e) => e.convert(context),
- Self::Ident(i) => i.convert(context),
- Self::Literal(l) => l.convert(context),
- Self::Call(c) => c.convert(context),
- Self::Fix(f) => f.convert(context),
- Self::Parens(e) => e.convert(context),
- }
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Cat {
- terms: Punctuated<Term, Token![.]>,
-}
-
-impl Cat {
- pub fn span(&self) -> Span {
- let mut pairs = self.terms.pairs();
- let mut span = pairs.next().and_then(|pair| match pair {
- Pair::Punctuated(term, punct) => term.span().join(punct.span),
- Pair::End(term) => Some(term.span()),
- });
-
- for pair in pairs {
- span = span.and_then(|span| match pair {
- Pair::Punctuated(term, punct) => {
- span.join(term.span()).and_then(|s| s.join(punct.span))
- }
- Pair::End(term) => span.join(term.span()),
- })
- }
-
- span.unwrap_or_else(Span::call_site)
- }
-}
-
-impl Parse for Cat {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- Ok(Self {
- terms: input.call(Punctuated::parse_separated_nonempty)?,
- })
- }
-}
-
-impl Convert for Cat {
- fn convert(&self, context: &mut Context) -> ast::Term {
- use ast::Term;
- let mut iter = self.terms.pairs();
- let init = match iter.next().unwrap() {
- Pair::Punctuated(t, p) => Ok((t.convert(context), p)),
- Pair::End(t) => Err(t.convert(context)),
- };
- iter.fold(init, |term, pair| {
- let (fst, punct) = term.unwrap();
- match pair {
- Pair::Punctuated(t, p) => {
- Ok((Term::Cat(ast::Cat::new(fst, *punct, t.convert(context))), p))
- }
- Pair::End(t) => Err(Term::Cat(ast::Cat::new(fst, *punct, t.convert(context)))),
- }
- })
- .unwrap_err()
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Alt {
- cats: Punctuated<Cat, Token![|]>,
-}
-
-impl Alt {
- pub fn span(&self) -> Span {
- let mut pairs = self.cats.pairs();
- let mut span = pairs.next().and_then(|pair| match pair {
- Pair::Punctuated(cat, punct) => cat.span().join(punct.span),
- Pair::End(cat) => Some(cat.span()),
- });
-
- for pair in pairs {
- span = span.and_then(|span| match pair {
- Pair::Punctuated(cat, punct) => {
- span.join(cat.span()).and_then(|s| s.join(punct.span))
- }
- Pair::End(cat) => span.join(cat.span()),
- })
- }
-
- span.unwrap_or_else(Span::call_site)
- }
-}
-
-impl Parse for Alt {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- Ok(Self {
- cats: input.call(Punctuated::parse_separated_nonempty)?,
- })
- }
-}
-
-impl Convert for Alt {
- fn convert(&self, context: &mut Context) -> ast::Term {
- use ast::Term;
- let mut iter = self.cats.pairs();
- let init = match iter.next().unwrap() {
- Pair::Punctuated(t, p) => Ok((t.convert(context), p)),
- Pair::End(t) => Err(t.convert(context)),
- };
- iter.fold(init, |cat, pair| {
- let (left, punct) = cat.unwrap();
- match pair {
- Pair::Punctuated(t, p) => Ok((
- Term::Alt(ast::Alt::new(left, *punct, t.convert(context))),
- p,
- )),
- Pair::End(t) => Err(Term::Alt(ast::Alt::new(left, *punct, t.convert(context)))),
- }
- })
- .unwrap_err()
- }
-}
-
-pub type Expression = Alt;
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct LetStatement {
- let_token: Token![let],
- name: Ident,
- args: Option<ArgList<Ident>>,
- eq_token: Token![=],
- expr: Expression,
- semi_token: Token![;],
-}
-
-impl Parse for LetStatement {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let let_token = input.parse()?;
- let name = input.call(Ident::parse_any)?;
- let args = if input.peek(token::Paren) {
- Some(input.parse()?)
- } else {
- None
- };
- let eq_token = input.parse()?;
- let expr = input.parse()?;
- let semi_token = input.parse()?;
-
- Ok(Self {
- let_token,
- name,
- args,
- eq_token,
- expr,
- semi_token,
- })
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Goal {
- match_token: Token![match],
- expr: Expression,
- semi_token: Token![;],
-}
-
-impl Parse for Goal {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let match_token = input.parse()?;
- let expr = input.parse()?;
- let semi_token = input.parse()?;
-
- Ok(Self { match_token, expr, semi_token })
- }
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct File {
- lets: Vec<LetStatement>,
- goal: Goal,
-}
-
-impl File {
- /// Returns function list and the goal. The function list consists of an
- /// [`Ident`], the converted [`ast::Term`] and the number of arguments.
- pub fn convert(self) -> (Vec<(Ident, ast::Term, usize)>, ast::Term) {
- let mut context = Context::new();
- let map = self
- .lets
- .into_iter()
- .map(|stmt| {
- let count = stmt.args.as_ref().map(ArgList::len).unwrap_or_default();
- context.set_variables(
- stmt.args
- .into_iter()
- .flat_map(|args| args.into_iter().map(|arg| arg.to_string())),
- );
- (stmt.name, stmt.expr.convert(&mut context), count)
- })
- .collect();
- let goal = self.goal.expr.convert(&mut context);
- (map, goal)
- }
-}
-
-impl Parse for File {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let mut lets = Vec::new();
- while input.peek(Token![let]) {
- lets.push(input.parse()?);
- }
-
- let goal = input.parse()?;
-
- Ok(Self { lets, goal })
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::{Epsilon, Ident, Literal};
- use syn::parse_str;
-
- #[test]
- fn parse_epsilon() {
- assert!(parse_str::<Epsilon>("_").is_ok());
- }
-
- #[test]
- fn parse_ident() {
- assert_eq!(parse_str::<Ident>("x").unwrap().to_string(), "x");
- assert_eq!(parse_str::<Ident>("x_yz").unwrap().to_string(), "x_yz");
- assert_eq!(parse_str::<Ident>("a123").unwrap().to_string(), "a123");
- assert_eq!(parse_str::<Ident>("𝒢𝒢").unwrap().to_string(), "𝒢𝒢");
- assert!(parse_str::<Ident>("1").is_err());
- assert!(parse_str::<Ident>("_").is_err());
- }
-
- #[test]
- fn parse_literal() {
- assert_eq!(parse_str::<Literal>(r#""hello""#).unwrap().value(), "hello")
- }
-}
+pub mod convert;
+pub mod cst;
+// impl File {
+// /// Returns function list and the goal. The function list consists of an
+// /// [`Ident`], the converted [`ast::Expression`] and the number of arguments.
+// pub fn convert(self) -> (Vec<(Ident, ast::Expression, usize)>, ast::Expression) {
+// let mut context = Context::new();
+// let map = self
+// .lets
+// .into_iter()
+// .map(|stmt| {
+// let count = stmt.args.as_ref().map(ArgList::len).unwrap_or_default();
+// context.set_variables(
+// stmt.args
+// .into_iter()
+// .flat_map(|args| args.into_iter().map(|arg| arg.to_string())),
+// );
+// (stmt.name, stmt.expr.convert(&mut context), count)
+// })
+// .collect();
+// let goal = self.goal.expr.convert(&mut context);
+// (map, goal)
+// }
+// }
+
+// #[cfg(test)]
+// mod tests {
+// use super::{Epsilon, Ident, Literal};
+// use syn::parse_str;
+
+// #[test]
+// fn parse_epsilon() {
+// assert!(parse_str::<Epsilon>("_").is_ok());
+// }
+
+// #[test]
+// fn parse_ident() {
+// assert_eq!(parse_str::<Ident>("x").unwrap().to_string(), "x");
+// assert_eq!(parse_str::<Ident>("x_yz").unwrap().to_string(), "x_yz");
+// assert_eq!(parse_str::<Ident>("a123").unwrap().to_string(), "a123");
+// assert_eq!(parse_str::<Ident>("𝒢𝒢").unwrap().to_string(), "𝒢𝒢");
+// assert!(parse_str::<Ident>("1").is_err());
+// assert!(parse_str::<Ident>("_").is_err());
+// }
+
+// #[test]
+// fn parse_literal() {
+// assert_eq!(parse_str::<Literal>(r#""hello""#).unwrap().value(), "hello")
+// }
+// }