implement comments

This commit is contained in:
Matthieu Jolimaitre 2024-10-25 14:33:55 +02:00
parent 7febf91d3c
commit d3095d5980
2 changed files with 50 additions and 23 deletions

View file

@ -1,7 +1,9 @@
// recursion
fn fibo(n) { fn fibo(n) {
if (n < 1) return n; if (n <= 0) return 0;
if (n <= 1) return 1;
return fibo(n - 1) + fibo(n - 2); return fibo(n - 1) + fibo(n - 2);
} }
fibo(3) fibo(10)

View file

@ -6,8 +6,8 @@ use libm::floor;
use crate::{util::Boxable, Context, EvalError, FunImpl, Function, Value}; use crate::{util::Boxable, Context, EvalError, FunImpl, Function, Value};
use chumsky::{ use chumsky::{
error::Simple, error::Simple,
prelude::{end, just, none_of, one_of, recursive, Recursive}, prelude::{end, filter, just, none_of, one_of, recursive, Recursive},
text::TextParser, text::whitespace,
Parser, Parser,
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
@ -17,8 +17,23 @@ extern crate alloc;
pub trait Parse<O>: Parser<char, O, Error = Simple<char>> + Clone + 'static {} pub trait Parse<O>: Parser<char, O, Error = Simple<char>> + Clone + 'static {}
impl<T: Parser<char, O, Error = Simple<char>> + Clone + 'static, O> Parse<O> for T {} impl<T: Parser<char, O, Error = Simple<char>> + Clone + 'static, O> Parse<O> for T {}
fn pad<O: 'static>(parser: impl Parse<O>) -> impl Parse<O> {
let comment = just("//")
.ignore_then(none_of("\n").repeated())
.ignore_then(just("\n"))
.ignored();
let padding = filter(|c| char::is_whitespace(*c))
.ignored()
.or(comment)
.repeated()
.ignored()
.or(whitespace().ignored());
padding.clone().ignore_then(parser).then_ignore(padding)
}
fn lx(word: &'static str) -> impl Parse<&'static str> { fn lx(word: &'static str) -> impl Parse<&'static str> {
just(word).padded().labelled("token") pad(just(word)).labelled("token")
} }
fn id() -> impl Parse<String> { fn id() -> impl Parse<String> {
@ -82,8 +97,8 @@ pub struct FunDef {
impl FunDef { impl FunDef {
pub fn parser_def(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<(String, Self)> { pub fn parser_def(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<(String, Self)> {
let arguments = id().padded().separated_by(lx(",")); let arguments = pad(id()).separated_by(lx(","));
(lx("fn").ignore_then(id().padded())) (lx("fn").ignore_then(pad(id())))
.then(lx("(").ignore_then(arguments).then_ignore(lx(")"))) .then(lx("(").ignore_then(arguments).then_ignore(lx(")")))
.then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}"))) .then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}")))
.map(|((id, args), body)| (id, Self { args, body })) .map(|((id, args), body)| (id, Self { args, body }))
@ -91,7 +106,7 @@ impl FunDef {
} }
pub fn parser_lamb(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<Self> { pub fn parser_lamb(instr: impl Parse<Instr>, expr: impl Parse<Expr>) -> impl Parse<Self> {
let arguments = id().padded().separated_by(lx(",")); let arguments = pad(id()).separated_by(lx(","));
(lx("(").ignore_then(arguments).then_ignore(lx(")"))) (lx("(").ignore_then(arguments).then_ignore(lx(")")))
.then_ignore(lx("=>")) .then_ignore(lx("=>"))
.then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}"))) .then(lx("{").ignore_then(Block::parser(instr, expr)).then_ignore(lx("}")))
@ -248,31 +263,41 @@ pub enum Expr {
impl Expr { impl Expr {
pub fn parser(instr: impl Parse<Instr>) -> impl Parse<Self> { pub fn parser(instr: impl Parse<Instr>) -> impl Parse<Self> {
recursive(|expr: Recursive<'_, _, Self, _>| { recursive(|expr: Recursive<'_, _, Self, _>| {
let left = (Litteral::parser(instr, expr.clone()).map(Self::Litteral)) let atom = (Litteral::parser(instr, expr.clone()).map(Self::Litteral))
.or((lx("(").ignore_then(expr.clone()).then_ignore(lx(")"))).map(|e| Self::Parens(e.to_box()))) .or((lx("(").ignore_then(expr.clone()).then_ignore(lx(")"))).map(|e| Self::Parens(e.to_box())))
.or((UniOp::parser().then(expr.clone())).map(|(o, e)| Self::UniOp(o, e.to_box()))) .or((UniOp::parser().then(expr.clone())).map(|(o, e)| Self::UniOp(o, e.to_box())))
.or(id().map(Self::Var).padded()); .or(pad(id()).map(Self::Var));
(left let call = atom
.clone() .clone()
.then(Op::parser().then(expr.clone()).repeated().at_least(1)))
.map(|(f, o)| Self::BinOps(f.to_box(), o))
.or((left.clone())
.then_ignore(lx("."))
.then(id().padded())
.map(|(e, a)| Self::Access(e.to_box(), a)))
.or((left.clone())
.then_ignore(lx("(")) .then_ignore(lx("("))
.then(expr.clone().separated_by(lx(","))) .then(expr.clone().separated_by(lx(",")))
.then_ignore(lx(")")) .then_ignore(lx(")"))
.map(|(e, a)| Self::Call(e.to_box(), a))) .map(|(e, a)| Self::Call(e.to_box(), a))
.or((left.clone()) .or(atom);
let index = call
.clone()
.then_ignore(lx("[")) .then_ignore(lx("["))
.then(expr.clone()) .then(expr.clone())
.then_ignore(lx("]")) .then_ignore(lx("]"))
.map(|(e, i)| Self::Index(e.to_box(), i.to_box()))) .map(|(e, i)| Self::Index(e.to_box(), i.to_box()))
.or(left) .or(call);
.labelled("expression")
let access = index
.clone()
.then_ignore(lx("."))
.then(pad(id()))
.map(|(e, a)| Self::Access(e.to_box(), a))
.or(index);
let ops = access
.clone()
.then(Op::parser().then(expr.clone()).repeated().at_least(1))
.map(|(f, o)| Self::BinOps(f.to_box(), o))
.or(access);
ops.labelled("expression")
}) })
} }