summaryrefslogtreecommitdiff
path: root/src/nibble/cst.rs
diff options
context:
space:
mode:
authorGreg Brown <gmb60@cam.ac.uk>2021-04-18 11:50:06 +0100
committerGreg Brown <gmb60@cam.ac.uk>2021-04-22 09:45:51 +0100
commit081560e2080426bc61e75624f3af96c97aa6c011 (patch)
tree21f2f97d31a8b15519908337179d006d392dd4aa /src/nibble/cst.rs
parent449695dcf87d26b0d06a51ca27bbc8214338f954 (diff)
Update AST and parser for lambda expressions.
Diffstat (limited to 'src/nibble/cst.rs')
-rw-r--r--src/nibble/cst.rs322
1 files changed, 193 insertions, 129 deletions
diff --git a/src/nibble/cst.rs b/src/nibble/cst.rs
index d8b71b7..6137640 100644
--- a/src/nibble/cst.rs
+++ b/src/nibble/cst.rs
@@ -2,16 +2,18 @@ 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},
+ token::{Comma, Let, Match, Paren},
LitStr, Token,
};
-use crate::chomp::{ast, Name};
+use crate::chomp::{
+ ast::{self, TopLevel},
+ Name,
+};
use super::convert::{Context, Convert, ConvertError};
@@ -67,63 +69,29 @@ impl<T: fmt::Debug> fmt::Debug for ArgList<T> {
}
}
-#[derive(Clone, Debug)]
-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)]
pub struct Fix {
- bracket_token: Bracket,
- pub arg: Ident,
- paren_token: Paren,
- pub expr: Expression,
+ bang_token: Token![!],
+ pub expr: Box<Term>,
}
impl Fix {
pub fn span(&self) -> Option<Span> {
- self.bracket_token.span.join(self.paren_token.span)
+ self.bang_token.span.join(self.expr.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,
- })
+ 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("arg", &self.arg)
- .field("expr", &self.expr)
- .finish()
+ f.debug_struct("Fix").field("expr", &self.expr).finish()
}
}
@@ -155,7 +123,6 @@ pub enum Term {
Epsilon(Epsilon),
Ident(Ident),
Literal(Literal),
- Call(Call),
Fix(Fix),
Parens(ParenExpression),
}
@@ -166,7 +133,6 @@ impl Term {
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),
}
@@ -181,18 +147,12 @@ impl Parse for Term {
input.parse().map(Self::Epsilon)
} else if lookahead.peek(LitStr) {
input.parse().map(Self::Literal)
- } else if lookahead.peek(Bracket) {
+ } 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) {
- 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))
- }
+ input.call(Ident::parse_any).map(Self::Ident)
} else {
Err(lookahead.error())
}
@@ -205,15 +165,47 @@ impl fmt::Debug for Term {
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, Debug)]
+pub struct Call(pub Vec<Term>);
+
+impl Call {
+ pub fn span(&self) -> Option<Span> {
+ 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<Self> {
+ 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<Term, Token![.]>);
+pub struct Cat(pub Punctuated<Call, Token![.]>);
impl Parse for Cat {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
@@ -334,58 +326,60 @@ impl fmt::Debug for Alt {
}
}
-pub type Expression = Alt;
-
#[derive(Clone)]
-pub struct LetStatement {
- let_token: Token![let],
- name: Ident,
- args: Option<ArgList<Ident>>,
- eq_token: Token![=],
- expr: Expression,
- semi_token: Token![;],
+pub struct Lambda {
+ slash_tok_left: Token![/],
+ pub args: ArgList<Ident>,
+ slash_tok_right: Token![/],
+ pub expr: Alt,
}
-impl LetStatement {
+impl Lambda {
pub fn span(&self) -> Option<Span> {
- self.let_token.span.join(self.semi_token.span)
+ self.slash_tok_left.span.join(self.expr.span()?)
}
}
-impl Parse for LetStatement {
+impl Parse for Lambda {
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 slash_tok_left = input.parse()?;
+ let args = input.parse()?;
+ let slash_tok_right = input.parse()?;
let expr = input.parse()?;
- let semi_token = input.parse()?;
-
Ok(Self {
- let_token,
- name,
+ slash_tok_left,
args,
- eq_token,
+ slash_tok_right,
expr,
- semi_token,
})
}
}
-impl fmt::Debug for LetStatement {
+impl fmt::Debug for Lambda {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("LetStatement")
- .field("name", &self.name)
+ f.debug_struct("Lambda")
.field("args", &self.args)
.field("expr", &self.expr)
.finish()
}
}
+#[derive(Clone, Debug)]
+pub enum Expression {
+ Alt(Alt),
+ Lambda(Lambda),
+}
+
+impl Parse for Expression {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ if input.peek(Token![/]) {
+ input.parse().map(Self::Lambda)
+ } else {
+ input.parse().map(Self::Alt)
+ }
+ }
+}
+
#[derive(Clone)]
pub struct GoalStatement {
match_token: Token![match],
@@ -415,58 +409,128 @@ impl fmt::Debug for GoalStatement {
}
}
-#[derive(Clone, Debug)]
-pub struct File {
- lets: Vec<LetStatement>,
- goal: GoalStatement,
-}
-
-impl File {
- pub fn convert(self) -> Result<(Vec<ast::Function>, ast::NamedExpression), ConvertError> {
- let mut names = Vec::new();
- let mut map = Vec::new();
- for stmt in self.lets {
- let span = stmt.span();
- let name: Name = stmt.name.into();
- let params = stmt
- .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)?;
- names.push(name.clone());
- expr.name = Some(name.clone());
- map.push(ast::Function {
- name,
- params: params.map(Some).collect(),
- expr,
- span,
- });
- }
+#[derive(Clone)]
+pub struct LetStatement {
+ let_token: Token![let],
+ name: Ident,
+ args: Option<ArgList<Ident>>,
+ eq_token: Token![=],
+ expr: Expression,
+ semi_token: Token![;],
+ next: Box<Statement>,
+}
- let mut context = Context::new(&names, Vec::new());
- let goal = self.goal.expr.convert(&mut context)?;
- Ok((map, goal))
+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()?;
+ let next = Box::new(input.parse()?);
+
+ Ok(Self {
+ let_token,
+ name,
+ args,
+ eq_token,
+ expr,
+ semi_token,
+ next,
+ })
}
}
-impl Parse for File {
- fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
- let mut lets = Vec::new();
- let mut lookahead = input.lookahead1();
+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)
+ .field("next", &self.next)
+ .finish()
+ }
+}
- while lookahead.peek(Let) {
- lets.push(input.parse()?);
- lookahead = input.lookahead1();
+#[derive(Clone, Debug)]
+pub enum Statement {
+ Goal(GoalStatement),
+ Let(LetStatement),
+}
+
+impl Statement {
+ pub fn convert(self) -> Result<TopLevel, ConvertError> {
+ let mut stmt = self;
+ let mut context = Context::new();
+ let mut name_val = Vec::new();
+ while let Self::Let(let_stmt) = stmt {
+ let mut val = match let_stmt.args {
+ Some(args) => {
+ todo!()
+ }
+ None => let_stmt.expr.convert(&mut context),
+ }?;
+ let name: Name = let_stmt.name.into();
+ val.name = val.name.or_else(|| Some(name.clone()));
+ context.push_variable(name.clone());
+ name_val.push((name, val));
+ stmt = *let_stmt.next;
}
- let goal = if lookahead.peek(Match) {
- input.parse()?
- } else {
- return Err(lookahead.error());
+ let goal = match stmt {
+ Statement::Goal(goal) => TopLevel::Goal(goal.expr.convert(&mut context)?),
+ Statement::Let(_) => unreachable!(),
};
- Ok(Self { lets, goal })
+ Ok(name_val.into_iter().rfold(goal, |inner, (name, val)| {
+ TopLevel::Let(ast::Let {
+ name,
+ val,
+ inner: Box::new(inner),
+ })
+ }))
+ // let mut map = Vec::new();
+ // for stmt in self.lets {
+ // let span = stmt.span();
+ // let name: Name = stmt.name.into();
+ // let params = stmt
+ // .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)?;
+ // names.push(name.clone());
+ // expr.name = Some(name.clone());
+ // map.push(ast::Function {
+ // name,
+ // params: params.map(Some).collect(),
+ // expr,
+ // span,
+ // });
+ // }
+
+ // let mut context = Context::new(&names, Vec::new());
+ // let goal = self.goal.expr.convert(&mut context)?;
+ // Ok((map, goal))
+ }
+}
+
+impl Parse for Statement {
+ fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+ let mut lookahead = input.lookahead1();
+
+ if lookahead.peek(Let) {
+ input.parse().map(Self::Let)
+ } else if lookahead.peek(Match) {
+ input.parse().map(Self::Goal)
+ } else {
+ Err(lookahead.error())
+ }
}
}