Compare commits

..

2 Commits

Author SHA1 Message Date
Scott Richmond
e4f70dde42 Use chumsky::recursive::Recursive in place of fn recursive 2024-10-31 16:28:15 -04:00
Scott Richmond
1b9f1d56bc Fix Stream::from_iter call 2024-10-31 15:38:55 -04:00

View File

@ -9,9 +9,9 @@
// * ignored words // * ignored words
// todo: // todo:
// * [ ] rewrite fn parser to use chumsky::Recursive::declare/define // * [x] rewrite fn parser to use chumsky::Recursive::declare/define
// - [ ] do this to extract/simplify/DRY things like tuple patterns, fn clauses, etc. // - [x] do this to extract/simplify/DRY things like tuple patterns, fn clauses, etc.
// * [ ] Work around chumsky::Stream::from_iter().spanned disappearing in most recent version // * [x] Work around chumsky::Stream::from_iter().spanned disappearing in most recent version
// * [x] investigate using labels (which is behind a compiler flag, somehow) // * [x] investigate using labels (which is behind a compiler flag, somehow)
// * [ ] wire up Ariadne parsing errors // * [ ] wire up Ariadne parsing errors
// * [ ] validation // * [ ] validation
@ -28,6 +28,7 @@
use chumsky::{ use chumsky::{
input::{Stream, ValueInput}, input::{Stream, ValueInput},
prelude::*, prelude::*,
recursive::Recursive,
}; };
use imbl::{HashMap, Vector}; use imbl::{HashMap, Vector};
use std::fmt; use std::fmt;
@ -344,21 +345,33 @@ fn parser<'src, I>(
where where
I: ValueInput<'src, Token = Token<'src>, Span = Span>, I: ValueInput<'src, Token = Token<'src>, Span = Span>,
{ {
recursive(|expr| { let mut expr = Recursive::declare();
let mut pattern = Recursive::declare();
let mut simple = Recursive::declare();
let mut nonbinding = Recursive::declare();
let separators = recursive(|separators| { let separators = recursive(|separators| {
just(Token::Punctuation(",")) just(Token::Punctuation(","))
.or(just(Token::Punctuation("\n"))) .or(just(Token::Punctuation("\n")))
.then(separators.clone().repeated()) .then(separators.clone().repeated())
}); });
let pattern = recursive(|pattern| { let terminators = recursive(|terminators| {
let placeholder = select! {Token::Punctuation("_") => Pattern::Placeholder} just(Token::Punctuation(";"))
.map_with(|p, e| (p, e.span())); .or(just(Token::Punctuation("\n")))
.then(terminators.clone().repeated())
});
let word = let placeholder_pattern =
select! {Token::Punctuation("_") => Pattern::Placeholder}.map_with(|p, e| (p, e.span()));
let word_pattern =
select! { Token::Word(w) => Pattern::Word(w) }.map_with(|w, e| (w, e.span())); select! { Token::Word(w) => Pattern::Word(w) }.map_with(|w, e| (w, e.span()));
let atom = select! { let atom_pattern = select! {
Token::Nil => Pattern::Atom(Value::Nil), Token::Nil => Pattern::Atom(Value::Nil),
Token::Boolean(b) => Pattern::Atom(Value::Boolean(b)), Token::Boolean(b) => Pattern::Atom(Value::Boolean(b)),
Token::Number(n) => Pattern::Atom(Value::Number(n)), Token::Number(n) => Pattern::Atom(Value::Number(n)),
@ -366,16 +379,17 @@ where
} }
.map_with(|a, e| (a, e.span())); .map_with(|a, e| (a, e.span()));
let tuple = pattern let tuple_pattern = pattern
.clone() .clone()
.separated_by(separators.clone()) .separated_by(separators.clone())
.allow_leading() .allow_leading()
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")"))) .delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
.map_with(|tuple, e| (Pattern::Tuple(tuple), e.span())); .map_with(|tuple, e| (Pattern::Tuple(tuple), e.span()))
.labelled("tuple pattern");
let list = pattern let list_pattern = pattern
.clone() .clone()
.separated_by(separators.clone()) .separated_by(separators.clone())
.allow_leading() .allow_leading()
@ -384,19 +398,19 @@ where
.delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]"))) .delimited_by(just(Token::Punctuation("[")), just(Token::Punctuation("]")))
.map_with(|list, e| (Pattern::List(list), e.span())); .map_with(|list, e| (Pattern::List(list), e.span()));
let pair = select! {Token::Keyword(k) => Value::Keyword(k)} let pair_pattern = select! {Token::Keyword(k) => Value::Keyword(k)}
.then(pattern.clone()) .then(pattern.clone())
.map_with(|(kw, patt), e| (Pattern::Pair(kw, Box::new(patt)), e.span())); .map_with(|(kw, patt), e| (Pattern::Pair(kw, Box::new(patt)), e.span()));
let shorthand = select! {Token::Word(w) => w}.map_with(|w, e| { let shorthand_pattern = select! {Token::Word(w) => w}.map_with(|w, e| {
( (
Pattern::Pair(Value::Keyword(w), Box::new((Pattern::Word(w), e.span()))), Pattern::Pair(Value::Keyword(w), Box::new((Pattern::Word(w), e.span()))),
e.span(), e.span(),
) )
}); });
let dict = pair let dict_pattern = pair_pattern
.or(shorthand) .or(shorthand_pattern)
.separated_by(separators.clone()) .separated_by(separators.clone())
.allow_leading() .allow_leading()
.allow_trailing() .allow_trailing()
@ -407,13 +421,15 @@ where
) )
.map_with(|dict, e| (Pattern::Dict(dict), e.span())); .map_with(|dict, e| (Pattern::Dict(dict), e.span()));
atom.or(word) pattern.define(
.or(placeholder) atom_pattern
.or(tuple) .or(word_pattern)
.or(list) .or(placeholder_pattern)
.or(dict) .or(tuple_pattern.clone())
.labelled("pattern") .or(list_pattern)
}); .or(dict_pattern)
.labelled("pattern"),
);
let placeholder = let placeholder =
select! {Token::Punctuation("_") => Ast::Placeholder}.map_with(|p, e| (p, e.span())); select! {Token::Punctuation("_") => Ast::Placeholder}.map_with(|p, e| (p, e.span()));
@ -422,7 +438,6 @@ where
.map_with(|w, e| (w, e.span())) .map_with(|w, e| (w, e.span()))
.labelled("word"); .labelled("word");
let simple = recursive(|simple| {
let value = select! { let value = select! {
Token::Nil => Ast::Value(Value::Nil), Token::Nil => Ast::Value(Value::Nil),
Token::Boolean(b) => Ast::Value(Value::Boolean(b)), Token::Boolean(b) => Ast::Value(Value::Boolean(b)),
@ -434,8 +449,6 @@ where
let keyword = select! {Token::Keyword(k) => Ast::Value(Value::Keyword(k)),} let keyword = select! {Token::Keyword(k) => Ast::Value(Value::Keyword(k)),}
.map_with(|k, e| (k, e.span())); .map_with(|k, e| (k, e.span()));
// let word = select! {Token::Word(w) => Ast::Word(w)}.map_with(|w, e| (w, e.span()));
let tuple = simple let tuple = simple
.clone() .clone()
.separated_by(separators.clone()) .separated_by(separators.clone())
@ -445,9 +458,6 @@ where
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")"))) .delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
.map_with(|tuple, e| (Ast::Tuple(tuple), e.span())); .map_with(|tuple, e| (Ast::Tuple(tuple), e.span()));
// let placeholder = select! {Token::Punctuation("_") => Ast::Placeholder}
// .map_with(|p, e| (p, e.span()));
let args = simple let args = simple
.clone() .clone()
.or(placeholder) .or(placeholder)
@ -504,6 +514,7 @@ where
) )
.map_with(|dict, e| (Ast::Dict(dict), e.span())); .map_with(|dict, e| (Ast::Dict(dict), e.span()));
simple.define(
synthetic synthetic
.or(word) .or(word)
.or(keyword) .or(keyword)
@ -511,17 +522,9 @@ where
.or(tuple) .or(tuple)
.or(list) .or(list)
.or(dict) .or(dict)
.labelled("simple expression") .labelled("simple expression"),
}); );
let terminators = recursive(|terminators| {
just(Token::Punctuation("\n"))
.or(just(Token::Punctuation(";")))
.then(terminators.clone().repeated())
.labelled("terminator")
});
let nonbinding = recursive(|nonbinding| {
let block = expr let block = expr
.clone() .clone()
.separated_by(terminators.clone()) .separated_by(terminators.clone())
@ -561,9 +564,7 @@ where
.clone() .clone()
.then_ignore(just(Token::Punctuation("->"))) .then_ignore(just(Token::Punctuation("->")))
.then(expr.clone()) .then(expr.clone())
.map_with(|(cond, body), e| { .map_with(|(cond, body), e| (Ast::WhenClause(Box::new(cond), Box::new(body)), e.span()));
(Ast::WhenClause(Box::new(cond), Box::new(body)), e.span())
});
let when = just(Token::Reserved("when")) let when = just(Token::Reserved("when"))
.ignore_then( .ignore_then(
@ -580,9 +581,7 @@ where
.clone() .clone()
.then_ignore(just(Token::Punctuation("->"))) .then_ignore(just(Token::Punctuation("->")))
.then(expr.clone()) .then(expr.clone())
.map_with(|(patt, body), e| { .map_with(|(patt, body), e| (Ast::MatchClause(Box::new(patt), Box::new(body)), e.span()));
(Ast::MatchClause(Box::new(patt), Box::new(body)), e.span())
});
let match_ = just(Token::Reserved("match")) let match_ = just(Token::Reserved("match"))
.ignore_then(simple.clone()) .ignore_then(simple.clone())
@ -615,8 +614,7 @@ where
nonbinding nonbinding
.clone() .clone()
.separated_by( .separated_by(
just(Token::Punctuation(">")) just(Token::Punctuation(">")).then(just(Token::Punctuation("\n")).repeated()),
.then(just(Token::Punctuation("\n")).repeated()),
) )
.collect(), .collect(),
) )
@ -625,34 +623,20 @@ where
let repeat = just(Token::Reserved("repeat")) let repeat = just(Token::Reserved("repeat"))
.ignore_then(simple.clone()) .ignore_then(simple.clone())
.then(block.clone()) .then(block.clone())
.map_with(|(count, body), e| { .map_with(|(count, body), e| (Ast::Repeat(Box::new(count), Box::new(body)), e.span()));
(Ast::Repeat(Box::new(count), Box::new(body)), e.span())
});
let tuple_pattern = pattern
.clone()
.separated_by(separators.clone())
.allow_leading()
.allow_trailing()
.collect()
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
.map_with(|tuple, e| (Pattern::Tuple(tuple), e.span()))
.labelled("tuple pattern");
let fn_clause = tuple_pattern let fn_clause = tuple_pattern
.clone()
.then_ignore(just(Token::Punctuation("->"))) .then_ignore(just(Token::Punctuation("->")))
.then(nonbinding.clone()) .then(nonbinding.clone())
.map_with(|(pattern, body), e| { .map_with(|(pattern, body), e| (Ast::FnClause(Box::new(pattern), Box::new(body)), e.span()))
(Ast::FnClause(Box::new(pattern), Box::new(body)), e.span())
})
.labelled("function clause"); .labelled("function clause");
let lambda = just(Token::Reserved("fn")) let lambda = just(Token::Reserved("fn"))
.ignore_then(fn_clause) .ignore_then(fn_clause.clone())
.map_with(|clause, e| (Ast::Fn("anonymous", vec![clause]), e.span())); .map_with(|clause, e| (Ast::Fn("anonymous", vec![clause]), e.span()));
let loop_ = just(Token::Reserved("loop")); nonbinding.define(
simple simple
.clone() .clone()
.or(conditional) .or(conditional)
@ -660,8 +644,9 @@ where
.or(lambda) .or(lambda)
.or(panic) .or(panic)
.or(do_) .or(do_)
.labelled("nonbinding expression") .or(repeat)
}); .labelled("nonbinding expression"),
);
let let_ = just(Token::Reserved("let")) let let_ = just(Token::Reserved("let"))
.ignore_then(pattern.clone()) .ignore_then(pattern.clone())
@ -695,21 +680,14 @@ where
(Ast::FnDeclaration(name), e.span()) (Ast::FnDeclaration(name), e.span())
}); });
let tuple_pattern = pattern // let tuple_pattern = pattern
.clone() // .clone()
.separated_by(separators.clone()) // .separated_by(separators.clone())
.allow_leading() // .allow_leading()
.allow_trailing() // .allow_trailing()
.collect() // .collect()
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")"))) // .delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
.map_with(|tuple, e| (Pattern::Tuple(tuple), e.span())); // .map_with(|tuple, e| (Pattern::Tuple(tuple), e.span()));
let fn_clause = tuple_pattern
.then_ignore(just(Token::Punctuation("->")))
.then(nonbinding.clone())
.map_with(|(pattern, body), e| {
(Ast::FnClause(Box::new(pattern), Box::new(body)), e.span())
});
let fn_named = just(Token::Reserved("fn")) let fn_named = just(Token::Reserved("fn"))
.ignore_then(word.clone()) .ignore_then(word.clone())
@ -728,7 +706,7 @@ where
.then( .then(
fn_clause fn_clause
.clone() .clone()
.separated_by(terminators) .separated_by(terminators.clone())
.allow_leading() .allow_leading()
.allow_trailing() .allow_trailing()
.collect() .collect()
@ -747,12 +725,20 @@ where
let binding = let_.or(box_).or(fn_); let binding = let_.or(box_).or(fn_);
nonbinding.or(binding) expr.define(binding.or(nonbinding));
})
let script = expr
.separated_by(terminators.clone())
.allow_trailing()
.allow_leading()
.collect()
.map_with(|exprs, e| (Ast::Block(exprs), e.span()));
script
} }
pub fn main() { pub fn main() {
let src = "let #{a, :b b} = foo"; let src = "let #{a, :b b} = foo\na(b(c),d)";
let (tokens, lex_errs) = lexer().parse(src).into_output_errors(); let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
if lex_errs.len() > 0 { if lex_errs.len() > 0 {
println!("{:?}", lex_errs); println!("{:?}", lex_errs);
@ -764,7 +750,7 @@ pub fn main() {
println!("{}", token) println!("{}", token)
} }
let (ast, _) = parser() let (ast, _) = parser()
.parse(Stream::from_iter(to_parse).spanned(SimpleSpan::new(0, src.len()))) .parse(Stream::from_iter(to_parse).map((0..src.len()).into(), |(t, s)| (t, s)))
.unwrap(); .unwrap();
println!("{}", ast); println!("{}", ast);
} }