This commit is contained in:
Erin 2023-09-12 19:54:59 +02:00 committed by ondra05
parent 2c2322bb6c
commit 1846fe41ae
4 changed files with 59 additions and 21 deletions

View file

@ -8,6 +8,7 @@ use utils::default;
mod syntax; mod syntax;
mod utils; mod utils;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut buf = default(); let mut buf = default();
stdin().read_to_string(&mut buf)?; stdin().read_to_string(&mut buf)?;

View file

@ -36,6 +36,7 @@ pub enum Expr<'a> {
Match(ExprRef<'a>, &'a [(Spanned<Pattern>, SpanExpr<'a>)]), Match(ExprRef<'a>, &'a [(Spanned<Pattern>, SpanExpr<'a>)]),
Set(ExprRef<'a>, ExprRef<'a>), Set(ExprRef<'a>, ExprRef<'a>),
Func(Ident, &'a [Spanned<Pattern>], ExprRef<'a>), Func(Ident, &'a [Spanned<Pattern>], ExprRef<'a>),
Block(ExprList<'a>),
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -57,7 +58,7 @@ pub enum BinaryOperator {
Star, Star,
Slash, Slash,
And, And,
Or, VLine,
Lt, Lt,
Gt, Gt,
Equ, Equ,
@ -68,7 +69,7 @@ pub enum BinaryOperator {
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UnaryOperator { pub enum UnaryOperator {
Not, Tilde,
Neg, Minus,
Deref, Star,
} }

View file

@ -1,4 +1,4 @@
use super::ast::{Literal, SpanExpr}; use super::ast::{BinaryOperator, Literal, SpanExpr, UnaryOperator};
use { use {
super::{ super::{
@ -15,39 +15,70 @@ use {
logos::Lexer, logos::Lexer,
}; };
/// Equivalently-named unit variant mapping
macro_rules! equivmap {
($src:ident, $target:ident, [$variant0:ident $(, $variant:ident)* $(,)?] $(,)?) => {
just($src::$variant0).to($target::$variant0)
$(.or(just($src::$variant).to($target::$variant)))*
};
}
fn expr<'a, I>() -> impl Parser<'a, I, SpanExpr<'a>, Extra<'a>> + Clone fn expr<'a, I>() -> impl Parser<'a, I, SpanExpr<'a>, Extra<'a>> + Clone
where where
I: Input<'a, Token = Token, Span = SimpleSpan> + ValueInput<'a>, I: Input<'a, Token = Token, Span = SimpleSpan> + ValueInput<'a>,
{ {
recursive(|expr| { recursive(|expr| {
let ident = select!(Token::Ident(id) => Expr::Ident(id)); let ident = select!(Token::Ident(id) => Expr::Ident(id));
let atom = {
// Literal let literal = select! {
select! {
Token::Int(a) => Literal::Integer(a), Token::Int(a) => Literal::Integer(a),
Token::String(a) => Literal::String(a) Token::String(a) => Literal::String(a)
} }
.map(Expr::Literal) .map(Expr::Literal);
}
.or(ident) let atom = literal.or(ident).map_with_span(Spanned::new).or(expr
.map_with_span(Spanned::new)
.or(expr
.clone() .clone()
.delimited_by(just(Token::LeftParen), just(Token::RightParen))); .delimited_by(just(Token::LeftParen), just(Token::RightParen)));
let call = atom let call = atom
.clone() .clone()
.pipe(arena_box) .foldl_with_state(
.then(
expr.clone() expr.clone()
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.allow_trailing() .allow_trailing()
.pipe(arena_collect) .pipe(arena_collect)
.delimited_by(just(Token::LeftParen), just(Token::RightParen)), .delimited_by(just(Token::LeftParen), just(Token::RightParen))
.map_with_span(Spanned::new)
.repeated(),
|expr, paramlist, state: &mut State| {
Spanned::new(
Expr::Call(state.arena.alloc(expr), paramlist.item),
merge_spans(expr.span, paramlist.span),
) )
.map(|(expr, params)| Expr::Call(expr, params)); },
)
.boxed();
call.map_with_span(Spanned::new).or(atom) let unary = call;
let binary = unary.clone().foldl_with_state(
equivmap!(
Token,
BinaryOperator,
[Plus, Minus, Star, Slash, And, VLine, Lt, Gt, Equ, Nequ, LtEqu, GtEqu],
)
.map_with_span(Spanned::new)
.then(unary)
.repeated(),
|l, (op, r), state: &mut State| {
Spanned::new(
Expr::Binary(op, state.arena.alloc(l), state.arena.alloc(r)),
merge_spans(l.span, r.span),
)
},
);
binary.or(atom)
}) })
} }
@ -105,3 +136,8 @@ where
{ {
parser.map_with_state(|item, _, state| &*state.arena.alloc(item)) parser.map_with_state(|item, _, state| &*state.arena.alloc(item))
} }
#[inline]
fn merge_spans(start: SimpleSpan, end: SimpleSpan) -> SimpleSpan {
SimpleSpan::new(start.start, end.end)
}

View file

@ -39,7 +39,7 @@ pub enum Token {
#[token("*")] Star, #[token("*")] Star,
#[token("/")] Slash, #[token("/")] Slash,
#[token("&")] And, #[token("&")] And,
#[token("|")] Or, #[token("|")] VLine,
#[token("~")] Tilde, #[token("~")] Tilde,
#[token("<")] Lt, #[token("<")] Lt,