Compare commits
No commits in common. "e4f70dde42342e71583f20b14153beeffc6e9bf3" and "01a052f37a9cc4fd584d14a369b2f4befcbf0f10" have entirely different histories.
e4f70dde42
...
01a052f37a
162
src/main.rs
162
src/main.rs
|
@ -9,9 +9,9 @@
|
||||||
// * ignored words
|
// * ignored words
|
||||||
|
|
||||||
// todo:
|
// todo:
|
||||||
// * [x] rewrite fn parser to use chumsky::Recursive::declare/define
|
// * [ ] rewrite fn parser to use chumsky::Recursive::declare/define
|
||||||
// - [x] do this to extract/simplify/DRY things like tuple patterns, fn clauses, etc.
|
// - [ ] do this to extract/simplify/DRY things like tuple patterns, fn clauses, etc.
|
||||||
// * [x] Work around chumsky::Stream::from_iter().spanned disappearing in most recent version
|
// * [ ] 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,7 +28,6 @@
|
||||||
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;
|
||||||
|
@ -345,33 +344,21 @@ fn parser<'src, I>(
|
||||||
where
|
where
|
||||||
I: ValueInput<'src, Token = Token<'src>, Span = Span>,
|
I: ValueInput<'src, Token = Token<'src>, Span = Span>,
|
||||||
{
|
{
|
||||||
let mut expr = Recursive::declare();
|
recursive(|expr| {
|
||||||
|
|
||||||
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 terminators = recursive(|terminators| {
|
let pattern = recursive(|pattern| {
|
||||||
just(Token::Punctuation(";"))
|
let placeholder = select! {Token::Punctuation("_") => Pattern::Placeholder}
|
||||||
.or(just(Token::Punctuation("\n")))
|
.map_with(|p, e| (p, e.span()));
|
||||||
.then(terminators.clone().repeated())
|
|
||||||
});
|
|
||||||
|
|
||||||
let placeholder_pattern =
|
let word =
|
||||||
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_pattern = select! {
|
let atom = 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)),
|
||||||
|
@ -379,17 +366,16 @@ where
|
||||||
}
|
}
|
||||||
.map_with(|a, e| (a, e.span()));
|
.map_with(|a, e| (a, e.span()));
|
||||||
|
|
||||||
let tuple_pattern = pattern
|
let tuple = 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 = pattern
|
let list = pattern
|
||||||
.clone()
|
.clone()
|
||||||
.separated_by(separators.clone())
|
.separated_by(separators.clone())
|
||||||
.allow_leading()
|
.allow_leading()
|
||||||
|
@ -398,19 +384,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_pattern = select! {Token::Keyword(k) => Value::Keyword(k)}
|
let pair = 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_pattern = select! {Token::Word(w) => w}.map_with(|w, e| {
|
let shorthand = 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_pattern = pair_pattern
|
let dict = pair
|
||||||
.or(shorthand_pattern)
|
.or(shorthand)
|
||||||
.separated_by(separators.clone())
|
.separated_by(separators.clone())
|
||||||
.allow_leading()
|
.allow_leading()
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
|
@ -421,15 +407,13 @@ where
|
||||||
)
|
)
|
||||||
.map_with(|dict, e| (Pattern::Dict(dict), e.span()));
|
.map_with(|dict, e| (Pattern::Dict(dict), e.span()));
|
||||||
|
|
||||||
pattern.define(
|
atom.or(word)
|
||||||
atom_pattern
|
.or(placeholder)
|
||||||
.or(word_pattern)
|
.or(tuple)
|
||||||
.or(placeholder_pattern)
|
.or(list)
|
||||||
.or(tuple_pattern.clone())
|
.or(dict)
|
||||||
.or(list_pattern)
|
.labelled("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()));
|
||||||
|
@ -438,6 +422,7 @@ 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)),
|
||||||
|
@ -449,6 +434,8 @@ 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())
|
||||||
|
@ -458,6 +445,9 @@ 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)
|
||||||
|
@ -514,7 +504,6 @@ 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)
|
||||||
|
@ -522,9 +511,17 @@ 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())
|
||||||
|
@ -564,7 +561,9 @@ where
|
||||||
.clone()
|
.clone()
|
||||||
.then_ignore(just(Token::Punctuation("->")))
|
.then_ignore(just(Token::Punctuation("->")))
|
||||||
.then(expr.clone())
|
.then(expr.clone())
|
||||||
.map_with(|(cond, body), e| (Ast::WhenClause(Box::new(cond), Box::new(body)), e.span()));
|
.map_with(|(cond, body), e| {
|
||||||
|
(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(
|
||||||
|
@ -581,7 +580,9 @@ where
|
||||||
.clone()
|
.clone()
|
||||||
.then_ignore(just(Token::Punctuation("->")))
|
.then_ignore(just(Token::Punctuation("->")))
|
||||||
.then(expr.clone())
|
.then(expr.clone())
|
||||||
.map_with(|(patt, body), e| (Ast::MatchClause(Box::new(patt), Box::new(body)), e.span()));
|
.map_with(|(patt, body), e| {
|
||||||
|
(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())
|
||||||
|
@ -614,7 +615,8 @@ where
|
||||||
nonbinding
|
nonbinding
|
||||||
.clone()
|
.clone()
|
||||||
.separated_by(
|
.separated_by(
|
||||||
just(Token::Punctuation(">")).then(just(Token::Punctuation("\n")).repeated()),
|
just(Token::Punctuation(">"))
|
||||||
|
.then(just(Token::Punctuation("\n")).repeated()),
|
||||||
)
|
)
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
|
@ -623,20 +625,34 @@ 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| (Ast::Repeat(Box::new(count), Box::new(body)), e.span()));
|
.map_with(|(count, body), e| {
|
||||||
|
(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| (Ast::FnClause(Box::new(pattern), Box::new(body)), e.span()))
|
.map_with(|(pattern, body), e| {
|
||||||
|
(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.clone())
|
.ignore_then(fn_clause)
|
||||||
.map_with(|clause, e| (Ast::Fn("anonymous", vec![clause]), e.span()));
|
.map_with(|clause, e| (Ast::Fn("anonymous", vec![clause]), e.span()));
|
||||||
|
|
||||||
nonbinding.define(
|
let loop_ = just(Token::Reserved("loop"));
|
||||||
|
|
||||||
simple
|
simple
|
||||||
.clone()
|
.clone()
|
||||||
.or(conditional)
|
.or(conditional)
|
||||||
|
@ -644,9 +660,8 @@ where
|
||||||
.or(lambda)
|
.or(lambda)
|
||||||
.or(panic)
|
.or(panic)
|
||||||
.or(do_)
|
.or(do_)
|
||||||
.or(repeat)
|
.labelled("nonbinding expression")
|
||||||
.labelled("nonbinding expression"),
|
});
|
||||||
);
|
|
||||||
|
|
||||||
let let_ = just(Token::Reserved("let"))
|
let let_ = just(Token::Reserved("let"))
|
||||||
.ignore_then(pattern.clone())
|
.ignore_then(pattern.clone())
|
||||||
|
@ -680,14 +695,21 @@ 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())
|
||||||
|
@ -706,7 +728,7 @@ where
|
||||||
.then(
|
.then(
|
||||||
fn_clause
|
fn_clause
|
||||||
.clone()
|
.clone()
|
||||||
.separated_by(terminators.clone())
|
.separated_by(terminators)
|
||||||
.allow_leading()
|
.allow_leading()
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -725,20 +747,12 @@ where
|
||||||
|
|
||||||
let binding = let_.or(box_).or(fn_);
|
let binding = let_.or(box_).or(fn_);
|
||||||
|
|
||||||
expr.define(binding.or(nonbinding));
|
nonbinding.or(binding)
|
||||||
|
})
|
||||||
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\na(b(c),d)";
|
let src = "let #{a, :b b} = foo";
|
||||||
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);
|
||||||
|
@ -750,7 +764,7 @@ pub fn main() {
|
||||||
println!("{}", token)
|
println!("{}", token)
|
||||||
}
|
}
|
||||||
let (ast, _) = parser()
|
let (ast, _) = parser()
|
||||||
.parse(Stream::from_iter(to_parse).map((0..src.len()).into(), |(t, s)| (t, s)))
|
.parse(Stream::from_iter(to_parse).spanned(SimpleSpan::new(0, src.len())))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
println!("{}", ast);
|
println!("{}", ast);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user