iowo/crates/lang/src/parser.rs

153 lines
5.2 KiB
Rust
Raw Normal View History

2024-04-03 00:08:00 +02:00
use chumsky::{
error::Rich,
input::{Stream, ValueInput},
prelude::*,
primitive::just,
recursive::recursive,
span::SimpleSpan,
2024-04-07 00:55:12 +02:00
IterParser,
2024-04-03 00:08:00 +02:00
};
use indexmap::IndexMap;
use logos::Logos;
2024-04-03 00:08:00 +02:00
use crate::tokens::Token;
pub mod ast;
2024-04-03 00:30:11 +02:00
#[cfg(test)]
mod tests;
use self::ast::{
raw_ast::{RawExpr, RawExpression},
File,
};
2024-04-03 00:08:00 +02:00
pub type Span = SimpleSpan;
pub type Spanned<T> = (T, Span);
2024-04-03 00:08:00 +02:00
pub fn parse(src: &str) -> ParseResult<File<'_>, Rich<'_, Token<'_>>> {
2024-04-03 00:08:00 +02:00
let toks: Vec<_> = Token::lexer(src)
.spanned()
.map(|(t, s)| (t.expect("TODO: add lexer error(s)"), Span::from(s)))
.collect();
let tok_stream = Stream::from_iter(toks).spanned((src.len()..src.len()).into());
2024-04-07 00:55:12 +02:00
parser().parse(tok_stream)
2024-04-03 00:08:00 +02:00
}
2024-04-07 00:55:12 +02:00
pub(crate) fn parser<
'tokens,
'src: 'tokens,
I: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
>() -> impl Parser<'tokens, I, File<'src>, extra::Err<Rich<'tokens, Token<'src>, Span>>> {
let word = select! { Token::Word(word) = e => (word, e.span())};
2024-04-03 00:08:00 +02:00
let expr = recursive(|expr| {
2024-04-08 15:43:42 +02:00
let lit = select! {
Token::Int(i) = e => RawExpression::new(RawExpr::Lit(ast::Lit::Int(i.parse().expect("TODO: handle better"))), e.span()),
Token::Float(f) = e => RawExpression::new(RawExpr::Lit(ast::Lit::Float(f.parse().expect("TODO: handle better"))), e.span()),
Token::String(s) = e => RawExpression::new(RawExpr::Lit(ast::Lit::String(s.strip_prefix('"').expect("a").strip_suffix('"').expect("b"))), e.span())
2024-04-08 15:43:42 +02:00
};
let mat = just(Token::Mat)
.ignore_then(select! { Token::Dimensions(dimensions) = e => (dimensions, e.span())})
.then(
lit.separated_by(just(Token::Comma))
.collect::<Vec<_>>()
.separated_by(just(Token::Semicolon))
.collect::<Vec<_>>()
.delimited_by(just(Token::BracketOpen), just(Token::BracketClose)),
)
.map_with(|(dimensions, data), e| {
// TODO: Validation and proper error handling/reporting
// (validation = validating the matrix dimensions)
RawExpression::new(
RawExpr::Matrix(dimensions, data.into_iter().flatten().collect()),
e.span(),
)
});
2024-04-03 00:08:00 +02:00
let var = select! {
Token::VarIdent(name) => (RawExpr::Var as fn(_) -> _, name),
Token::InputIdent(name) => (RawExpr::InputVar as fn(_) -> _, name)
2024-04-03 00:08:00 +02:00
}
.map_with(|(item_type, name), extra| RawExpression::new(item_type(name), extra.span()))
.labelled("variable");
2024-04-03 00:08:00 +02:00
let attrset = word
.labelled("attr name")
2024-04-03 00:08:00 +02:00
.then_ignore(just(Token::Colon))
.then(expr)
.labelled("attr body")
2024-04-03 00:08:00 +02:00
.separated_by(just(Token::Comma))
.collect::<Vec<_>>()
.map(IndexMap::from_iter)
2024-04-08 14:04:52 +02:00
.delimited_by(just(Token::BraceOpen), just(Token::BraceClose))
.map_with(|v, e| (v, e.span()))
.labelled("attrset");
2024-04-03 00:08:00 +02:00
let node = word
.repeated()
.collect()
2024-04-03 00:08:00 +02:00
.then(attrset.clone().or_not())
2024-04-07 00:55:12 +02:00
.map_with(|(name, params), extra| {
RawExpression::new(RawExpr::Node(name, params), extra.span())
2024-04-07 00:55:12 +02:00
})
// .or(var)
// .or(attrset
// .map_with(|attrset, extra| Expression::new(Expr::AttrSet(attrset), extra.span())))
// .or(lit)
// .or(mat)
.labelled("node");
2024-04-03 00:08:00 +02:00
let atom = var
.or(lit)
.or(mat)
.or(attrset.map_with(|attrset, extra| {
RawExpression::new(RawExpr::AttrSet(attrset), extra.span())
}))
.or(node.clone());
2024-04-07 00:55:12 +02:00
#[allow(clippy::let_and_return)]
let pipeline = atom
2024-04-03 00:08:00 +02:00
.clone()
.then(choice((
just(Token::Pipe).to(RawExpr::SimplePipe as fn(_, _) -> _),
just(Token::MappingPipe).to(RawExpr::MappingPipe as fn(_, _) -> _),
just(Token::NullPipe).to(RawExpr::NullPipe as fn(_, _) -> _),
2024-04-03 00:08:00 +02:00
)))
.repeated()
.foldr_with(atom, |(curr, pipe), next, extra| {
RawExpression::new(pipe(curr, next), extra.span())
2024-04-03 00:08:00 +02:00
});
pipeline
});
let decls = just(Token::Def)
.ignore_then(
word.then_ignore(just(Token::Equals))
.then(expr.clone().map(|expr| expr))
.then_ignore(just(Token::Semicolon)),
)
.repeated()
.collect::<Vec<_>>()
.map(|decls| File {
decls: IndexMap::from_iter(decls),
});
let single_expr = expr.map(|expr| File {
2024-04-07 00:55:12 +02:00
decls: IndexMap::from_iter([(("main", (0..0).into()), expr)]),
});
just(Token::Def).rewind().ignore_then(decls).or(single_expr)
// single_expr.or(decls)
// expr.map(|expr| File {
// decls: IndexMap::from_iter([(("main", (0..0).into()), expr)]),
// })
// .or(decl.repeated().collect::<Vec<_>>().map(|decls| File {
// decls: IndexMap::from_iter(decls),
// }))
2024-04-03 00:08:00 +02:00
}
2024-04-08 14:04:52 +02:00
pub mod asg {
use petgraph::graph::DiGraph;
use super::Spanned;
}