Function call parsing
This commit is contained in:
parent
d588c6b230
commit
01cdcf249e
|
@ -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"
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
11
src/utils.rs
11
src/utils.rs
|
@ -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 {}
|
||||
|
|
Loading…
Reference in a new issue