parse docstrings
This commit is contained in:
parent
a35d5293a9
commit
ad76f41b52
|
@ -30,7 +30,7 @@
|
|||
// * [x] `loop` and `recur`
|
||||
// * [ ] string patterns
|
||||
// * [ ] string interpolation
|
||||
// * [ ] docstrings
|
||||
// * [x] docstrings
|
||||
// * [~] write `base` in Rust
|
||||
// * [ ] turn this into a library function
|
||||
// * [ ] compile this into WASM
|
||||
|
@ -58,7 +58,12 @@ use crate::base::*;
|
|||
|
||||
pub fn main() {
|
||||
let src = "
|
||||
true
|
||||
fn foo {
|
||||
\"this is a docstring\"
|
||||
() -> :foo
|
||||
(_) -> :bar
|
||||
}
|
||||
foo ()
|
||||
";
|
||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||
if !lex_errs.is_empty() {
|
||||
|
|
|
@ -54,7 +54,7 @@ pub enum Ast<'src> {
|
|||
Synthetic(Box<Spanned<Self>>, Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
When(Vec<Spanned<WhenClause<'src>>>),
|
||||
Match(Box<Spanned<Self>>, Vec<MatchClause<'src>>),
|
||||
Fn(&'src str, Vec<MatchClause<'src>>),
|
||||
Fn(&'src str, Vec<MatchClause<'src>>, Option<&'src str>),
|
||||
FnDeclaration(&'src str),
|
||||
Panic(Box<Spanned<Self>>),
|
||||
Do(Vec<Spanned<Self>>),
|
||||
|
@ -149,7 +149,7 @@ impl fmt::Display for Ast<'_> {
|
|||
.join("\n")
|
||||
)
|
||||
}
|
||||
Ast::Fn(name, clauses) => {
|
||||
Ast::Fn(name, clauses, _) => {
|
||||
write!(
|
||||
f,
|
||||
"fn: {}\n{}",
|
||||
|
@ -407,10 +407,11 @@ where
|
|||
Token::Nil => Ast::Nil,
|
||||
Token::Boolean(b) => Ast::Boolean(b),
|
||||
Token::Number(n) => Ast::Number(n),
|
||||
Token::String(s) => Ast::String(s),
|
||||
}
|
||||
.map_with(|v, e| (v, e.span()));
|
||||
|
||||
let string = select! {Token::String(s) => Ast::String(s)}.map_with(|s, e| (s, e.span()));
|
||||
|
||||
let tuple = simple
|
||||
.clone()
|
||||
.separated_by(separators.clone())
|
||||
|
@ -505,6 +506,7 @@ where
|
|||
.or(tuple.clone())
|
||||
.or(list)
|
||||
.or(dict)
|
||||
.or(string)
|
||||
.labelled("simple expression"),
|
||||
);
|
||||
|
||||
|
@ -599,12 +601,6 @@ where
|
|||
|
||||
let conditional = when.or(if_).or(match_);
|
||||
|
||||
//todo:
|
||||
// * [x] do
|
||||
// * [ ] loop
|
||||
// * [x] repeat
|
||||
// * [x] panic!
|
||||
|
||||
let panic = just(Token::Reserved("panic!"))
|
||||
.ignore_then(nonbinding.clone())
|
||||
.map_with(|expr, e| (Ast::Panic(Box::new(expr)), e.span()));
|
||||
|
@ -653,14 +649,17 @@ where
|
|||
|
||||
let lambda = just(Token::Reserved("fn"))
|
||||
.ignore_then(fn_unguarded.clone())
|
||||
.map_with(|clause, e| (Ast::Fn("anonymous", vec![clause]), e.span()));
|
||||
.map_with(|clause, e| (Ast::Fn("anonymous", vec![clause], None), e.span()));
|
||||
|
||||
let fn_multiclause = fn_clause
|
||||
let fn_clauses = fn_clause
|
||||
.clone()
|
||||
.separated_by(terminators.clone())
|
||||
.allow_leading()
|
||||
.allow_trailing()
|
||||
.collect()
|
||||
.collect();
|
||||
|
||||
let loop_multiclause = fn_clauses
|
||||
.clone()
|
||||
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}")));
|
||||
|
||||
let fn_single_clause = fn_clause.clone().map_with(|c, _| vec![c]);
|
||||
|
@ -668,7 +667,7 @@ where
|
|||
let r#loop = just(Token::Reserved("loop"))
|
||||
.ignore_then(tuple.clone())
|
||||
.then_ignore(just(Token::Reserved("with")))
|
||||
.then(fn_multiclause.clone().or(fn_single_clause.clone()))
|
||||
.then(loop_multiclause.clone().or(fn_single_clause.clone()))
|
||||
.map_with(|(init, body), e| (Ast::Loop(Box::new(init), body), e.span()));
|
||||
|
||||
nonbinding.define(
|
||||
|
@ -725,19 +724,29 @@ where
|
|||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::Fn(name, vec![clause]), e.span())
|
||||
(Ast::Fn(name, vec![clause], None), e.span())
|
||||
});
|
||||
|
||||
let docstr = select! {Token::String(s) => s};
|
||||
|
||||
let fn_multiclause = separators
|
||||
.clone()
|
||||
.or_not()
|
||||
.ignore_then(docstr.or_not())
|
||||
.then(fn_clauses.clone())
|
||||
.delimited_by(just(Token::Punctuation("{")), just(Token::Punctuation("}")))
|
||||
.map_with(|(docstr, clauses), e| (docstr, clauses, e.span()));
|
||||
|
||||
let fn_compound = just(Token::Reserved("fn"))
|
||||
.ignore_then(word)
|
||||
.then(fn_multiclause.clone())
|
||||
.map_with(|(word, clauses), e| {
|
||||
.then(fn_multiclause)
|
||||
.map_with(|(word, (docstr, clauses, _)), e| {
|
||||
let name = if let Ast::Word(word) = word.0 {
|
||||
word
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
(Ast::Fn(name, clauses), e.span())
|
||||
(Ast::Fn(name, clauses, docstr), e.span())
|
||||
});
|
||||
|
||||
let fn_ = fn_named.or(fn_compound).or(fn_decl);
|
||||
|
|
Loading…
Reference in New Issue
Block a user