Function call parsing
This commit is contained in:
parent
d588c6b230
commit
01cdcf249e
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bumpalo = "3"
|
bumpalo = { version = "3", features = ["collections"] }
|
||||||
chumsky = "1.0.0-alpha"
|
chumsky = "1.0.0-alpha"
|
||||||
lasso = "0.7"
|
lasso = "0.7"
|
||||||
logos = "0.13"
|
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 lexer = syntax::token::Token::lexer_with_extras(&buf, default());
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
syntax::parser::parse(
|
syntax::parser::parse_lexer(lexer, &arena);
|
||||||
lexer
|
|
||||||
.spanned()
|
|
||||||
.map(|(item, span)| (item.unwrap_or(syntax::token::Token::Invalid), span.into())),
|
|
||||||
&arena,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
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)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum Expr<'a> {
|
pub enum Expr<'a> {
|
||||||
Binary(BinaryOperator, &'a Self, &'a Self),
|
Ident(Ident),
|
||||||
Unary(UnaryOperator, &'a Self),
|
Path(ExprList<'a>),
|
||||||
Literal(Literal),
|
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)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,18 +1,107 @@
|
||||||
use super::{ast::Expr, token::Token};
|
use super::ast::{Literal, SpanExpr};
|
||||||
use bumpalo::Bump;
|
|
||||||
use chumsky::{extra::Full, input::Stream, prelude::*};
|
|
||||||
|
|
||||||
type Item = (Token, SimpleSpan);
|
use {
|
||||||
type Extra<'s> = Full<Rich<'s, Item, SimpleSpan>, State<'s>, ()>;
|
super::{
|
||||||
struct State<'a> {
|
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,
|
arena: &'a Bump,
|
||||||
|
) {
|
||||||
|
println!("{:?}", expr().parse_with_state(input, &mut State { arena }));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(input: impl Iterator<Item = Item>, arena: &Bump) {
|
pub fn parse_iter(
|
||||||
expr().parse_with_state(Stream::from_iter(input), &mut State { arena });
|
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>(
|
pub fn parse_lexer(input: Lexer<Token>, arena: &Bump) {
|
||||||
) -> impl Parser<'s, Stream<I>, Expr<'a>, Extra<'s>> {
|
let end = input.span().end;
|
||||||
todo()
|
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 {
|
pub fn default<T: Default>() -> T {
|
||||||
Default::default()
|
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