Function call parsing

This commit is contained in:
Erin 2023-09-03 17:48:27 +02:00 committed by ondra05
parent d588c6b230
commit 01cdcf249e
5 changed files with 152 additions and 22 deletions

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
bumpalo = "3"
bumpalo = { version = "3", features = ["collections"] }
chumsky = "1.0.0-alpha"
lasso = "0.7"
logos = "0.13"

View file

@ -14,12 +14,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let lexer = syntax::token::Token::lexer_with_extras(&buf, default());
let arena = Bump::new();
syntax::parser::parse(
lexer
.spanned()
.map(|(item, span)| (item.unwrap_or(syntax::token::Token::Invalid), span.into())),
&arena,
);
syntax::parser::parse_lexer(lexer, &arena);
Ok(())
}

View file

@ -1,12 +1,47 @@
use lasso::Spur;
use {super::token::IntLit, chumsky::span::SimpleSpan, lasso::Spur};
use super::token::IntLit;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Spanned<T> {
pub item: T,
pub span: SimpleSpan,
}
impl<T> Spanned<T> {
#[inline]
pub fn new(item: T, span: SimpleSpan) -> Self {
Self { item, span }
}
}
pub type SpanExpr<'a> = Spanned<Expr<'a>>;
pub type ExprRef<'a> = &'a SpanExpr<'a>;
pub type ExprList<'a> = &'a [SpanExpr<'a>];
pub type Ident = Spur;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Expr<'a> {
Binary(BinaryOperator, &'a Self, &'a Self),
Unary(UnaryOperator, &'a Self),
Ident(Ident),
Path(ExprList<'a>),
Literal(Literal),
Call(ExprRef<'a>, ExprList<'a>),
Binary(Spanned<BinaryOperator>, ExprRef<'a>, ExprRef<'a>),
Unary(Spanned<UnaryOperator>, ExprRef<'a>),
BindLocal(ExprRef<'a>, Spanned<Pattern>, Option<ExprList<'a>>),
BindIn(
ExprRef<'a>,
Spanned<Pattern>,
ExprList<'a>,
Option<ExprList<'a>>,
),
Match(ExprRef<'a>, &'a [(Spanned<Pattern>, SpanExpr<'a>)]),
Set(ExprRef<'a>, ExprRef<'a>),
Func(Ident, &'a [Spanned<Pattern>], ExprRef<'a>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Pattern {
Ident(Ident),
None,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

View file

@ -1,18 +1,107 @@
use super::{ast::Expr, token::Token};
use bumpalo::Bump;
use chumsky::{extra::Full, input::Stream, prelude::*};
use super::ast::{Literal, SpanExpr};
type Item = (Token, SimpleSpan);
type Extra<'s> = Full<Rich<'s, Item, SimpleSpan>, State<'s>, ()>;
struct State<'a> {
use {
super::{
ast::{Expr, Spanned},
token::Token,
},
crate::utils::Pipe,
bumpalo::Bump,
chumsky::{
extra::Full,
input::{Stream, ValueInput},
prelude::*,
},
logos::Lexer,
};
fn expr<'a, I>() -> impl Parser<'a, I, SpanExpr<'a>, Extra<'a>> + Clone
where
I: Input<'a, Token = Token, Span = SimpleSpan> + ValueInput<'a>,
{
recursive(|expr| {
let ident = select!(Token::Ident(id) => Expr::Ident(id));
let atom = {
// Literal
select! {
Token::Int(a) => Literal::Integer(a),
Token::String(a) => Literal::String(a)
}
.map(Expr::Literal)
}
.or(ident)
.map_with_span(Spanned::new)
.or(expr
.clone()
.delimited_by(just(Token::LeftParen), just(Token::RightParen)));
let call = atom
.clone()
.pipe(arena_box)
.then(
expr.clone()
.separated_by(just(Token::Comma))
.allow_trailing()
.pipe(arena_collect)
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
)
.map(|(expr, params)| Expr::Call(expr, params));
call.map_with_span(Spanned::new).or(atom)
})
}
pub struct State<'a> {
pub arena: &'a Bump,
}
pub type Extra<'a> = Full<Rich<'a, Token>, State<'a>, ()>;
pub fn parse_input<'a>(
input: impl ValueInput<'a, Token = Token, Span = SimpleSpan>,
arena: &'a Bump,
) {
println!("{:?}", expr().parse_with_state(input, &mut State { arena }));
}
pub fn parse(input: impl Iterator<Item = Item>, arena: &Bump) {
expr().parse_with_state(Stream::from_iter(input), &mut State { arena });
pub fn parse_iter(
input: impl Iterator<Item = (Token, SimpleSpan)>,
eoi: impl Into<SimpleSpan>,
arena: &Bump,
) {
parse_input(Stream::from_iter(input).spanned(eoi.into()), arena)
}
fn expr<'s, 'a, I: Iterator<Item = (Token, SimpleSpan)> + 's>(
) -> impl Parser<'s, Stream<I>, Expr<'a>, Extra<'s>> {
todo()
pub fn parse_lexer(input: Lexer<Token>, arena: &Bump) {
let end = input.span().end;
parse_iter(
input
.spanned()
.map(|(token, span)| (token.unwrap_or(Token::Invalid), span.into())),
end..end + 1,
arena,
)
}
fn arena_collect<'a, I, O: 'a>(
parser: impl IterParser<'a, I, O, Extra<'a>> + Clone,
) -> impl Parser<'a, I, &'a [O], Extra<'a>> + Clone
where
I: Input<'a, Span = SimpleSpan, Token = Token>,
{
empty()
.map_with_state(|_, _, state: &mut State| bumpalo::vec![in state.arena])
.foldl(parser, |mut v, o| {
v.push(o);
v
})
.map(bumpalo::collections::Vec::into_bump_slice)
}
fn arena_box<'a, I, O: 'a>(
parser: impl Parser<'a, I, O, Extra<'a>> + Clone,
) -> impl Parser<'a, I, &'a O, Extra<'a>> + Clone
where
I: Input<'a, Span = SimpleSpan, Token = Token>,
{
parser.map_with_state(|item, _, state| &*state.arena.alloc(item))
}

View file

@ -2,3 +2,14 @@
pub fn default<T: Default>() -> T {
Default::default()
}
pub trait Pipe {
fn pipe<R>(self, mut f: impl FnMut(Self) -> R) -> R
where
Self: Sized,
{
f(self)
}
}
impl<T> Pipe for T {}