Less confusing branches #1
|
@ -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)?;
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue