ast: fn main
, structification
parser: unified post/infix, context-full grammar repl: modes
This commit is contained in:
parent
434fa225e7
commit
8640ec4261
76
src/ast.rs
76
src/ast.rs
@ -58,7 +58,7 @@ pub struct MakeArm<A: Annotation = Span>(pub String, pub Option<Anno<Expr<A>, A>
|
||||
/// (Pat |)* Pat? => Expr
|
||||
/// ```
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct MatchArm<A: Annotation = Span>(pub Vec<Pat>, pub Anno<Expr<A>, A>);
|
||||
pub struct MatchArm<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
||||
|
||||
/// In-universe types
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -77,6 +77,22 @@ pub enum Ty {
|
||||
Fn(Vec<Ty>),
|
||||
}
|
||||
|
||||
/// A `const` binding (which defines its name before executing)
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Const<A: Annotation = Span>(pub Pat, pub Anno<Expr<A>, A>);
|
||||
|
||||
/// A function definition `fn Ident? (Pat,*) Expr`
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Fn<A: Annotation = Span>(pub Option<String>, pub Pat, pub Anno<Expr<A>, A>);
|
||||
|
||||
/// A `let` binding: `let Pat (= Expr)?`
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Let<A: Annotation = Span>(pub Pat, pub Option<Anno<Expr<A>, A>>);
|
||||
|
||||
/// `match Expr { MatchArm,* }``
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Match<A: Annotation = Span>(pub Anno<Expr<A>, A>, pub Vec<MatchArm<A>>);
|
||||
|
||||
/// Expressions: The beating heart of Dough
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Expr<A: Annotation = Span> {
|
||||
@ -87,15 +103,15 @@ pub enum Expr<A: Annotation = Span> {
|
||||
/// A literal bool, string, char, or int
|
||||
Lit(Literal),
|
||||
/// let Pat<NoTopAlt> = expr
|
||||
Let(Pat, Option<Box<Anno<Self, A>>>),
|
||||
Let(Box<Let<A>>),
|
||||
/// `const Pat<NoTopAlt> (= Expr)?` (Basically let rec)
|
||||
Const(Pat, Box<Anno<Self, A>>),
|
||||
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn (Pat,*) Expr`
|
||||
Fn(Pat, Box<Anno<Self, A>>),
|
||||
Const(Box<Const<A>>),
|
||||
/// `| Pat<Tuple> | Expr` | `|| Expr` | `fn Ident? (Pat,*) Expr`
|
||||
Fn(Box<Fn<A>>),
|
||||
/// Expr { (Ident (: Expr)?),* }
|
||||
Make(Box<Anno<Self, A>>, Vec<MakeArm<A>>),
|
||||
/// match Expr { MatchArm,* }
|
||||
Match(Box<Anno<Self, A>>, Vec<MatchArm<A>>),
|
||||
Match(Box<Match<A>>),
|
||||
/// Op Expr | Expr Op | Expr (Op Expr)+ | Op Expr Expr else Expr
|
||||
Op(Op, Vec<Anno<Self, A>>),
|
||||
}
|
||||
@ -205,22 +221,52 @@ impl<T: Display + Annotation, A: Annotation> Display for Anno<T, A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Display for Const<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self(pat, expr) = self;
|
||||
write!(f, "const {pat} = {expr}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Display for Fn<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self(Some(name), pat, expr) => write!(f, "fn {name} {pat} {expr}"),
|
||||
Self(None, pat, expr) => write!(f, "|{pat}| {expr}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Display for Let<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self(pat, Some(expr)) => write!(f, "let {pat} = {expr}"),
|
||||
Self(pat, None) => write!(f, "let ({pat})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Display for Match<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self(expr, match_arms) = self;
|
||||
f.delimit_indented(fmt!("match {expr} {{"), "}")
|
||||
.list_wrap("\n", match_arms, ",\n", ",\n")
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Display for Expr<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Id(id) => id.fmt(f),
|
||||
Self::MetId(id) => write!(f, "`{id}"),
|
||||
Self::Lit(literal) => literal.fmt(f),
|
||||
Self::Let(pat, Some(expr)) => write!(f, "let {pat} = {expr}"),
|
||||
Self::Let(pat, None) => write!(f, "let ({pat})"),
|
||||
Self::Const(pat, expr) => write!(f, "const {pat} = {expr}"),
|
||||
Self::Let(v) => v.fmt(f),
|
||||
Self::Const(v) => v.fmt(f),
|
||||
Self::Make(expr, make_arms) => {
|
||||
f.delimit(fmt!("({expr} {{"), "})").list(make_arms, ", ")
|
||||
}
|
||||
Self::Match(expr, match_arms) => f
|
||||
.delimit_indented(fmt!("match {expr} {{"), "}")
|
||||
.list_wrap("\n", match_arms, ",\n", ",\n"),
|
||||
Self::Fn(pat, expr) => write!(f, "fn {pat} {expr}"),
|
||||
Self::Match(v) => v.fmt(f),
|
||||
Self::Fn(v) => v.fmt(f),
|
||||
|
||||
Self::Op(op @ (Op::If | Op::While), exprs) => match exprs.as_slice() {
|
||||
[cond, pass, fail] => write!(f, "{op}{cond} {pass} else {fail}"),
|
||||
@ -315,8 +361,8 @@ impl<A: Annotation> Display for MakeArm<A> {
|
||||
|
||||
impl<A: Annotation> Display for MatchArm<A> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self(pats, expr) = self;
|
||||
f.delimit("", fmt!(" => {expr}")).list(pats, " | ")
|
||||
let Self(pat, expr) = self;
|
||||
write!(f, "{pat} => {expr}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,60 @@ impl<M: Match<A> + Annotation, A: Annotation> Match<A> for Anno<M, A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Match<A> for Const<A> {
|
||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||
let (Self(pat_pat, pat_expr), Self(expr_pat, expr_expr)) = (pat, expr);
|
||||
Match::recurse(sub, pat_pat, expr_pat) && Match::recurse(sub, pat_expr, expr_expr)
|
||||
}
|
||||
|
||||
fn apply(&mut self, sub: &Subst<A>) {
|
||||
let Self(pat, expr) = self;
|
||||
pat.apply(sub);
|
||||
expr.apply(sub);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Match<A> for Fn<A> {
|
||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||
let (Self(pat_id, pat_arg, pat_body), Self(expr_id, expr_arg, expr_body)) = (pat, expr);
|
||||
pat_id == expr_id
|
||||
&& Match::recurse(sub, pat_arg, expr_arg)
|
||||
&& Match::recurse(sub, pat_body, expr_body)
|
||||
}
|
||||
|
||||
fn apply(&mut self, sub: &Subst<A>) {
|
||||
let Self(_, pat, body) = self;
|
||||
pat.apply(sub);
|
||||
body.apply(sub);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Match<A> for Let<A> {
|
||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||
let (Self(pat_pat, pat_expr), Self(expr_pat, expr_expr)) = (pat, expr);
|
||||
Match::recurse(sub, pat_pat, expr_pat) && Match::recurse(sub, pat_expr, expr_expr)
|
||||
}
|
||||
|
||||
fn apply(&mut self, sub: &Subst<A>) {
|
||||
let Self(pat, expr) = self;
|
||||
pat.apply(sub);
|
||||
expr.apply(sub);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Match<A> for crate::ast::Match<A> {
|
||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||
let (Self(pat_expr, pat_arms), Self(expr_expr, expr_arms)) = (pat, expr);
|
||||
Match::recurse(sub, pat_expr, expr_expr) && Match::recurse(sub, pat_arms, expr_arms)
|
||||
}
|
||||
|
||||
fn apply(&mut self, sub: &Subst<A>) {
|
||||
let Self(pat, expr) = self;
|
||||
pat.apply(sub);
|
||||
expr.apply(sub);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Annotation> Match<A> for Expr<A> {
|
||||
fn recurse(sub: &mut Subst<A>, pat: &Self, expr: &Self) -> bool {
|
||||
match (pat, expr) {
|
||||
@ -87,25 +141,17 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
||||
(Expr::Id(_), _) => false,
|
||||
(Expr::Lit(pat), Expr::Lit(expr)) => pat == expr,
|
||||
(Expr::Lit(_), _) => false,
|
||||
(Expr::Let(pat_pat, pat_expr), Expr::Let(expr_pat, expr_expr)) => {
|
||||
Match::recurse(sub, pat_pat, expr_pat) && Match::recurse(sub, pat_expr, expr_expr)
|
||||
}
|
||||
(Expr::Let(pat), Expr::Let(expr)) => Match::recurse(sub, pat, expr),
|
||||
(Expr::Let(..), _) => false,
|
||||
(Expr::Const(pat_pat, pat_expr), Expr::Const(expr_pat, expr_expr)) => {
|
||||
Match::recurse(sub, pat_pat, expr_pat) && Match::recurse(sub, pat_expr, expr_expr)
|
||||
}
|
||||
(Expr::Const(pat), Expr::Const(expr)) => Match::recurse(sub, pat, expr),
|
||||
(Expr::Const(..), _) => false,
|
||||
(Expr::Make(pat, pat_arms), Expr::Make(expr, expr_arms)) => {
|
||||
Match::recurse(sub, pat, expr) && Match::recurse(sub, pat_arms, expr_arms)
|
||||
}
|
||||
(Expr::Make(..), _) => false,
|
||||
(Expr::Match(pat, pat_arms), Expr::Match(expr, expr_arms)) => {
|
||||
Match::recurse(sub, pat, expr) && Match::recurse(sub, pat_arms, expr_arms)
|
||||
}
|
||||
(Expr::Match(pat), Expr::Match(expr)) => Match::recurse(sub, pat, expr),
|
||||
(Expr::Match(..), _) => false,
|
||||
(Expr::Fn(pat_pats, pat_expr), Expr::Fn(expr_pats, expr_expr)) => {
|
||||
Match::recurse(sub, pat_pats, expr_pats) && Match::recurse(sub, pat_expr, expr_expr)
|
||||
}
|
||||
(Expr::Fn(pat), Expr::Fn(expr)) => Match::recurse(sub, pat, expr),
|
||||
(Expr::Fn(..), _) => false,
|
||||
(Expr::Op(pat_op, pat_exprs), Expr::Op(expr_op, expr_exprs)) => {
|
||||
Match::recurse(sub, pat_op, expr_op) && Match::recurse(sub, pat_exprs, expr_exprs)
|
||||
@ -122,24 +168,20 @@ impl<A: Annotation> Match<A> for Expr<A> {
|
||||
}
|
||||
}
|
||||
Expr::Id(_) | Expr::Lit(_) => {}
|
||||
Expr::Let(pat, expr) => {
|
||||
pat.apply(sub);
|
||||
Expr::Let(expr) => {
|
||||
expr.apply(sub);
|
||||
}
|
||||
Expr::Const(pat, expr) => {
|
||||
pat.apply(sub);
|
||||
Expr::Const(expr) => {
|
||||
expr.apply(sub);
|
||||
}
|
||||
Expr::Make(expr, make_arms) => {
|
||||
expr.apply(sub);
|
||||
make_arms.apply(sub);
|
||||
}
|
||||
Expr::Match(expr, match_arms) => {
|
||||
Expr::Match(expr) => {
|
||||
expr.apply(sub);
|
||||
match_arms.apply(sub);
|
||||
}
|
||||
Expr::Fn(pats, expr) => {
|
||||
pats.apply(sub);
|
||||
Expr::Fn(expr) => {
|
||||
expr.apply(sub);
|
||||
}
|
||||
Expr::Op(op, exprs) => {
|
||||
|
93
src/main.rs
93
src/main.rs
@ -1,4 +1,8 @@
|
||||
//! Tests the lexer
|
||||
use doughlang::{
|
||||
ast::{Anno, Pat},
|
||||
parser::PPrec,
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
use doughlang::{
|
||||
ast::{
|
||||
@ -25,7 +29,19 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
print!("\x1b[H\x1b[2J");
|
||||
Ok(Response::Deny)
|
||||
}
|
||||
"lex" => {
|
||||
lex()?;
|
||||
Ok(Response::Deny)
|
||||
}
|
||||
"expr" => {
|
||||
exprs()?;
|
||||
Ok(Response::Deny)
|
||||
}
|
||||
"pat" => {
|
||||
pats()?;
|
||||
Ok(Response::Deny)
|
||||
}
|
||||
"macro" => {
|
||||
if let Err(e) = subst() {
|
||||
println!("\x1b[31m{e}\x1b[0m");
|
||||
}
|
||||
@ -38,28 +54,79 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
})?;
|
||||
} else {
|
||||
let doc = std::io::read_to_string(stdin())?;
|
||||
lex(&doc);
|
||||
// lex(&doc);
|
||||
parse(&doc);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn lex(document: &str) {
|
||||
let mut lexer = Lexer::new(document);
|
||||
loop {
|
||||
match lexer.scan() {
|
||||
Ok(Token { lexeme, kind, span: Span { head, tail } }) => {
|
||||
println!(
|
||||
fn lex() -> Result<(), Box<dyn Error>> {
|
||||
read_and("\x1b[93m", " >", "?>", |line| {
|
||||
let mut lexer = Lexer::new(line);
|
||||
if line.trim().is_empty() {
|
||||
return Ok(Response::Break);
|
||||
}
|
||||
loop {
|
||||
match lexer.scan() {
|
||||
Err(LexError { res: "EOF", .. }) => {
|
||||
break Ok(Response::Accept);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("\x1b[31m{e}\x1b[0m");
|
||||
break Ok(Response::Deny);
|
||||
}
|
||||
Ok(Token { lexeme, kind, span: Span { head, tail } }) => println!(
|
||||
"{kind:?}\x1b[11G {head:<4} {tail:<4} {}",
|
||||
lexeme.escape_debug()
|
||||
)
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
break;
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn exprs() -> Result<(), Box<dyn Error>> {
|
||||
read_and("\x1b[93m", " >", "?>", |line| {
|
||||
let mut parser = Parser::new(Lexer::new(line));
|
||||
if line.trim().is_empty() {
|
||||
return Ok(Response::Break);
|
||||
}
|
||||
loop {
|
||||
match parser.parse::<Anno<Expr>>(0) {
|
||||
Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => {
|
||||
break Ok(Response::Accept);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("\x1b[31m{e}\x1b[0m");
|
||||
break Ok(Response::Deny);
|
||||
}
|
||||
Ok(v) => println!("{v}\n{v:#?}"),
|
||||
}
|
||||
}
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pats() -> Result<(), Box<dyn Error>> {
|
||||
read_and("\x1b[94m", " >", "?>", |line| {
|
||||
let mut parser = Parser::new(Lexer::new(line));
|
||||
if line.trim().is_empty() {
|
||||
return Ok(Response::Break);
|
||||
}
|
||||
loop {
|
||||
match parser.parse::<Pat>(PPrec::Max) {
|
||||
Err(ParseError::FromLexer(LexError { res: "EOF", .. })) => {
|
||||
break Ok(Response::Accept);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("\x1b[31m{e}\x1b[0m");
|
||||
break Ok(Response::Deny);
|
||||
}
|
||||
Ok(v) => println!("{v}\n{v:#?}"),
|
||||
}
|
||||
}
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn subst() -> Result<(), Box<dyn Error>> {
|
||||
|
242
src/parser.rs
242
src/parser.rs
@ -121,6 +121,7 @@ impl<'t> Parser<'t> {
|
||||
sep: TKind,
|
||||
end: TKind,
|
||||
) -> PResult<Vec<P>> {
|
||||
// TODO: This loses lexer errors
|
||||
while self.peek_if(end).is_none() {
|
||||
elems.push(self.parse(level)?);
|
||||
if self.next_if(sep).is_err() {
|
||||
@ -167,6 +168,11 @@ impl<'t> Parser<'t> {
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub fn consume_if(&mut self, next: TKind) -> PResult<&mut Self> {
|
||||
self.next_if(next)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Consumes the currently peeked token without returning it.
|
||||
pub fn consume(&mut self) -> &mut Self {
|
||||
self.next_tok = None;
|
||||
@ -217,6 +223,18 @@ pub enum PPrec {
|
||||
Max,
|
||||
}
|
||||
|
||||
impl PPrec {
|
||||
fn next(self) -> Self {
|
||||
match self {
|
||||
Self::Min => Self::Min,
|
||||
Self::Typed => Self::Min,
|
||||
Self::Tuple => Self::Typed,
|
||||
Self::Alt => Self::Tuple,
|
||||
Self::Max => Self::Alt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for Pat {
|
||||
type Prec = PPrec;
|
||||
fn parse(p: &mut Parser<'t>, level: PPrec) -> PResult<Self> {
|
||||
@ -240,13 +258,13 @@ impl<'t> Parse<'t> for Pat {
|
||||
TKind::LParen => {
|
||||
Pat::Tuple(
|
||||
p.consume()
|
||||
.list(vec![], PPrec::Tuple, TKind::Comma, TKind::RParen)?,
|
||||
.list(vec![], PPrec::Max, TKind::Comma, TKind::RParen)?,
|
||||
)
|
||||
}
|
||||
TKind::LBrack => {
|
||||
Pat::Slice(
|
||||
p.consume()
|
||||
.list(vec![], PPrec::Tuple, TKind::Comma, TKind::RBrack)?,
|
||||
.list(vec![], PPrec::Max, TKind::Comma, TKind::RBrack)?,
|
||||
)
|
||||
}
|
||||
_ => Err(ParseError::NotPattern(tok.kind, tok.span))?,
|
||||
@ -257,14 +275,16 @@ impl<'t> Parse<'t> for Pat {
|
||||
let kind = tok.kind;
|
||||
|
||||
head = match kind {
|
||||
TKind::Colon if level > PPrec::Typed => {
|
||||
TKind::Colon if level >= PPrec::Typed => {
|
||||
Pat::Typed(head.into(), p.consume().parse(())?)
|
||||
}
|
||||
TKind::Comma if level > PPrec::Tuple => {
|
||||
Pat::Tuple(p.consume().list_bare(vec![head], PPrec::Tuple, kind)?)
|
||||
}
|
||||
TKind::Bar if level > PPrec::Alt => {
|
||||
Pat::Alt(p.consume().list_bare(vec![head], PPrec::Alt, kind)?)
|
||||
TKind::Comma if level >= PPrec::Tuple => Pat::Tuple(p.consume().list_bare(
|
||||
vec![head],
|
||||
PPrec::Tuple.next(),
|
||||
kind,
|
||||
)?),
|
||||
TKind::Bar if level >= PPrec::Alt => {
|
||||
Pat::Alt(p.consume().list_bare(vec![head], PPrec::Alt.next(), kind)?)
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
@ -305,32 +325,9 @@ impl<'t> Parse<'t> for Ty {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for MatchArm {
|
||||
type Prec = usize;
|
||||
fn parse(p: &mut Parser<'t>, level: usize) -> PResult<Self> {
|
||||
p.next_if(TKind::Bar).ok();
|
||||
Ok(MatchArm(
|
||||
p.list(vec![], PPrec::Max, TKind::Bar, TKind::FatArrow)?,
|
||||
p.parse(level)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for MakeArm {
|
||||
type Prec = ();
|
||||
fn parse(p: &mut Parser<'t>, _level: ()) -> PResult<Self> {
|
||||
Ok(MakeArm(p.next_if(TKind::Identifier)?.lexeme, {
|
||||
p.next_if(TKind::Colon)
|
||||
.ok()
|
||||
.map(|_| p.parse(Prec::Min.value()))
|
||||
.transpose()?
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Organizes the precedence hierarchy for syntactic elements
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum Prec {
|
||||
pub enum Prec {
|
||||
Min,
|
||||
/// The Semicolon Operator gets its own precedence level
|
||||
Do,
|
||||
@ -462,7 +459,7 @@ fn from_infix(token: &Token) -> PResult<(Ps, Prec)> {
|
||||
TKind::Question => (Ps::Op(Op::Try), Prec::Unary),
|
||||
TKind::LParen => (Ps::Op(Op::Call), Prec::Extend),
|
||||
TKind::LBrack => (Ps::Op(Op::Index), Prec::Extend),
|
||||
// TKind::LCurly => (Ps::Make, Prec::Make),
|
||||
TKind::LCurly => (Ps::Make, Prec::Make),
|
||||
TKind::RParen | TKind::RBrack | TKind::RCurly => (Ps::End, Prec::Max),
|
||||
TKind::Eq => (Ps::Op(Op::Set), Prec::Assign),
|
||||
TKind::XorXor => (Ps::Op(Op::LogXor), Prec::Logical),
|
||||
@ -488,13 +485,79 @@ fn from_infix(token: &Token) -> PResult<(Ps, Prec)> {
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::match_single_binding, unused)]
|
||||
fn from_postfix(token: &Token) -> PResult<(Ps, Prec)> {
|
||||
Ok(match token.kind {
|
||||
TKind::LCurly => (Ps::Make, Prec::Make),
|
||||
kind => Err(ParseError::NotPostfix(kind, token.span))?,
|
||||
// _ => (Ps::End, Prec::Max),
|
||||
})
|
||||
impl<'t> Parse<'t> for Const {
|
||||
type Prec = ();
|
||||
|
||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||
Ok(Self(
|
||||
p.consume().parse(PPrec::Alt)?,
|
||||
p.consume_if(TKind::Eq)?.parse(Prec::Tuple.value())?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for Fn {
|
||||
type Prec = ();
|
||||
|
||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||
Ok(Self(
|
||||
p.consume()
|
||||
.next_if(TKind::Identifier)
|
||||
.map(|id| id.lexeme)
|
||||
.ok(),
|
||||
Pat::Tuple(p.consume_if(TKind::LParen)?.list(
|
||||
vec![],
|
||||
PPrec::Tuple,
|
||||
TKind::Comma,
|
||||
TKind::RParen,
|
||||
)?),
|
||||
p.parse(Prec::Body.next())?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for Let {
|
||||
type Prec = ();
|
||||
|
||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||
Ok(Self(
|
||||
p.consume().parse(PPrec::Alt)?,
|
||||
p.opt_if(Prec::Tuple.value(), TKind::Eq)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for Match {
|
||||
type Prec = ();
|
||||
|
||||
fn parse(p: &mut Parser<'t>, _level: Self::Prec) -> PResult<Self> {
|
||||
Ok(Self(p.consume().parse(Prec::Logical.value())?, {
|
||||
p.next_if(TKind::LCurly)?;
|
||||
p.list(vec![], Prec::Body.next(), TKind::Comma, TKind::RCurly)?
|
||||
}))
|
||||
}
|
||||
}
|
||||
impl<'t> Parse<'t> for MatchArm {
|
||||
type Prec = usize;
|
||||
fn parse(p: &mut Parser<'t>, level: usize) -> PResult<Self> {
|
||||
p.next_if(TKind::Bar).ok();
|
||||
Ok(MatchArm(
|
||||
p.parse(PPrec::Max)?,
|
||||
p.consume_if(TKind::FatArrow)?.parse(level)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for MakeArm {
|
||||
type Prec = ();
|
||||
fn parse(p: &mut Parser<'t>, _level: ()) -> PResult<Self> {
|
||||
Ok(MakeArm(p.next_if(TKind::Identifier)?.lexeme, {
|
||||
p.next_if(TKind::Colon)
|
||||
.ok()
|
||||
.map(|_| p.parse(Prec::Body.value()))
|
||||
.transpose()?
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> Parse<'t> for Expr {
|
||||
@ -520,14 +583,8 @@ impl<'t> Parse<'t> for Expr {
|
||||
Ps::Id => Expr::Id(p.take_lexeme().expect("should have ident")),
|
||||
Ps::Mid => Expr::MetId(p.consume().next()?.lexeme),
|
||||
Ps::Lit => Expr::Lit(p.parse(())?),
|
||||
Ps::Let => Expr::Let(
|
||||
p.consume().parse(PPrec::Alt)?,
|
||||
p.opt_if(prec.value(), TKind::Eq)?,
|
||||
),
|
||||
Ps::Const => Expr::Const(p.consume().parse(PPrec::Tuple)?, {
|
||||
p.next_if(TKind::Eq)?;
|
||||
p.parse(prec.next())?
|
||||
}),
|
||||
Ps::Let => Expr::Let(p.parse(())?),
|
||||
Ps::Const => Expr::Const(p.parse(())?),
|
||||
Ps::Op(Op::Macro) => Expr::Op(
|
||||
Op::Macro,
|
||||
vec![p.consume().parse(prec.next())?, {
|
||||
@ -535,10 +592,7 @@ impl<'t> Parse<'t> for Expr {
|
||||
p.parse(prec.next())?
|
||||
}],
|
||||
),
|
||||
Ps::Match => Expr::Match(p.consume().parse(Prec::Logical.value())?, {
|
||||
p.next_if(TKind::LCurly)?;
|
||||
p.list(vec![], prec.next(), TKind::Comma, TKind::RCurly)?
|
||||
}),
|
||||
Ps::Match => Expr::Match(p.parse(())?),
|
||||
Ps::Op(Op::Block) => Expr::Op(
|
||||
Op::Block,
|
||||
p.consume().opt(MIN, TKind::RCurly)?.into_iter().collect(),
|
||||
@ -564,27 +618,17 @@ impl<'t> Parse<'t> for Expr {
|
||||
];
|
||||
Expr::Op(op, exprs)
|
||||
}
|
||||
Ps::Fn => {
|
||||
// TODO: move this to 'item' parsing
|
||||
p.consume().next_if(TKind::LParen)?;
|
||||
Expr::Fn(
|
||||
Pat::Tuple(p.consume().list(
|
||||
vec![],
|
||||
PPrec::Tuple,
|
||||
TKind::Comma,
|
||||
TKind::RParen,
|
||||
)?),
|
||||
p.parse(prec.next())?,
|
||||
)
|
||||
}
|
||||
Ps::Lambda => Expr::Fn(
|
||||
Pat::Tuple(
|
||||
p.consume()
|
||||
.list(vec![], PPrec::Tuple, TKind::Comma, TKind::Bar)?,
|
||||
),
|
||||
Ps::Fn => Expr::Fn(p.parse(())?),
|
||||
Ps::Lambda => Expr::Fn(Box::new(Fn(
|
||||
None,
|
||||
p.consume()
|
||||
.opt(PPrec::Tuple, TKind::Bar)?
|
||||
.unwrap_or(Pat::Tuple(vec![])),
|
||||
p.parse(Prec::Body.next())?,
|
||||
),
|
||||
Ps::Lambda0 => Expr::Fn(Pat::Tuple(vec![]), p.consume().parse(Prec::Body.next())?),
|
||||
))),
|
||||
Ps::Lambda0 => Expr::Fn(Box::new(Fn(None, Pat::Tuple(vec![]), {
|
||||
p.consume().parse(Prec::Body.next())?
|
||||
}))),
|
||||
Ps::DoubleRef => Expr::Op(
|
||||
Op::Refer,
|
||||
vec![Expr::Op(Op::Refer, vec![p.consume().parse(prec.next())?]).anno(span)],
|
||||
@ -594,25 +638,7 @@ impl<'t> Parse<'t> for Expr {
|
||||
_ => unimplemented!("prefix {op:?}"),
|
||||
};
|
||||
|
||||
// Postfix
|
||||
while let Ok(tok) = p.peek()
|
||||
&& let Ok((op, prec)) = from_postfix(tok)
|
||||
&& level <= prec.prev()
|
||||
&& op != Ps::End
|
||||
{
|
||||
// let kind = tok.kind;
|
||||
let span = span.merge(p.span());
|
||||
// p.consume();
|
||||
head = match (op, &head) {
|
||||
(Ps::Make, Expr::Op(Op::Path, _) | Expr::Id(_) | Expr::MetId(_)) => Expr::Make(
|
||||
head.anno(span).into(),
|
||||
p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
|
||||
),
|
||||
_ => break,
|
||||
};
|
||||
}
|
||||
|
||||
// Infix
|
||||
// Infix and Postfix
|
||||
while let Ok(tok) = p.peek()
|
||||
&& let Ok((op, prec)) = from_infix(tok)
|
||||
&& level <= prec.prev()
|
||||
@ -621,26 +647,37 @@ impl<'t> Parse<'t> for Expr {
|
||||
let kind = tok.kind;
|
||||
let span = span.merge(p.span());
|
||||
|
||||
p.consume();
|
||||
|
||||
head = match op {
|
||||
Ps::Make => Expr::Make(
|
||||
head.anno(span).into(),
|
||||
p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
|
||||
),
|
||||
// Make (structor expressions) are context-sensitive
|
||||
Ps::Make => match &head {
|
||||
Expr::Op(Op::Path, _) | Expr::Id(_) | Expr::MetId(_) => Expr::Make(
|
||||
head.anno(span).into(),
|
||||
p.consume().list(vec![], (), TKind::Comma, TKind::RCurly)?,
|
||||
),
|
||||
_ => break,
|
||||
},
|
||||
Ps::Op(Op::Index) => Expr::Op(
|
||||
Op::Index,
|
||||
p.list(vec![head.anno(span)], 0, TKind::Comma, TKind::RBrack)?,
|
||||
p.consume()
|
||||
.list(vec![head.anno(span)], 0, TKind::Comma, TKind::RBrack)?,
|
||||
),
|
||||
Ps::Op(Op::Call) => Expr::Op(
|
||||
Op::Call,
|
||||
p.list(vec![head.anno(span)], 0, TKind::Comma, TKind::RParen)?,
|
||||
p.consume()
|
||||
.list(vec![head.anno(span)], 0, TKind::Comma, TKind::RParen)?,
|
||||
),
|
||||
Ps::Op(op @ (Op::Do | Op::Tuple | Op::Dot | Op::Path | Op::LogAnd | Op::LogOr)) => {
|
||||
Expr::Op(op, p.list_bare(vec![head.anno(span)], prec.next(), kind)?)
|
||||
Expr::Op(
|
||||
op,
|
||||
p.consume()
|
||||
.list_bare(vec![head.anno(span)], prec.next(), kind)?,
|
||||
)
|
||||
}
|
||||
Ps::Op(op @ Op::Try) => Expr::Op(op, vec![head.anno(span)]),
|
||||
Ps::Op(op) => Expr::Op(op, vec![head.anno(span), p.parse(prec.next())?]),
|
||||
Ps::Op(op @ Op::Try) => {
|
||||
p.consume();
|
||||
Expr::Op(op, vec![head.anno(span)])
|
||||
}
|
||||
Ps::Op(op) => Expr::Op(op, vec![head.anno(span), p.consume().parse(prec.next())?]),
|
||||
_ => unimplemented!("infix {op:?}"),
|
||||
}
|
||||
}
|
||||
@ -655,7 +692,6 @@ impl<'t, P: Parse<'t> + Annotation> Parse<'t> for Anno<P> {
|
||||
where Self: Sized {
|
||||
let start = p.span();
|
||||
let anno = Anno(p.parse(level)?, start.merge(p.span()));
|
||||
println!("{}:\t{anno}", anno.1);
|
||||
Ok(anno)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user