2024-04-02 22:08:00 +00:00
|
|
|
use chumsky::{
|
|
|
|
error::Rich,
|
|
|
|
input::{Stream, ValueInput},
|
|
|
|
prelude::*,
|
|
|
|
primitive::just,
|
|
|
|
recursive::recursive,
|
|
|
|
span::SimpleSpan,
|
2024-04-06 22:55:12 +00:00
|
|
|
IterParser,
|
2024-04-02 22:08:00 +00:00
|
|
|
};
|
|
|
|
use indexmap::IndexMap;
|
2024-04-11 01:23:03 +00:00
|
|
|
use logos::Logos;
|
2024-04-02 22:08:00 +00:00
|
|
|
|
|
|
|
use crate::tokens::Token;
|
|
|
|
|
|
|
|
pub mod ast;
|
2024-04-02 22:30:11 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
2024-04-11 01:23:03 +00:00
|
|
|
use self::ast::{
|
|
|
|
raw_ast::{RawExpr, RawExpression},
|
|
|
|
File,
|
|
|
|
};
|
2024-04-02 22:08:00 +00:00
|
|
|
|
2024-04-03 15:00:20 +00:00
|
|
|
pub type Span = SimpleSpan;
|
|
|
|
pub type Spanned<T> = (T, Span);
|
2024-04-02 22:08:00 +00:00
|
|
|
|
2024-04-11 01:23:03 +00:00
|
|
|
pub fn parse(src: &str) -> ParseResult<File<'_>, Rich<'_, Token<'_>>> {
|
2024-04-02 22:08:00 +00: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-06 22:55:12 +00:00
|
|
|
parser().parse(tok_stream)
|
2024-04-02 22:08:00 +00:00
|
|
|
}
|
2024-04-06 22:55:12 +00: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>>> {
|
2024-04-11 01:23:03 +00:00
|
|
|
let word = select! { Token::Word(word) = e => (word, e.span())};
|
2024-04-02 22:08:00 +00:00
|
|
|
|
|
|
|
let expr = recursive(|expr| {
|
2024-04-08 13:43:42 +00:00
|
|
|
let lit = select! {
|
2024-04-11 01:23:03 +00:00
|
|
|
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 13:43:42 +00:00
|
|
|
};
|
2024-04-11 01:23:03 +00: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-02 22:08:00 +00:00
|
|
|
let var = select! {
|
2024-04-11 01:23:03 +00:00
|
|
|
Token::VarIdent(name) => (RawExpr::Var as fn(_) -> _, name),
|
|
|
|
Token::InputIdent(name) => (RawExpr::InputVar as fn(_) -> _, name)
|
2024-04-02 22:08:00 +00:00
|
|
|
}
|
2024-04-11 01:23:03 +00:00
|
|
|
.map_with(|(item_type, name), extra| RawExpression::new(item_type(name), extra.span()))
|
2024-04-03 15:00:20 +00:00
|
|
|
.labelled("variable");
|
2024-04-02 22:08:00 +00:00
|
|
|
|
|
|
|
let attrset = word
|
2024-04-03 15:00:20 +00:00
|
|
|
.labelled("attr name")
|
2024-04-02 22:08:00 +00:00
|
|
|
.then_ignore(just(Token::Colon))
|
|
|
|
.then(expr)
|
2024-04-03 15:00:20 +00:00
|
|
|
.labelled("attr body")
|
2024-04-02 22:08:00 +00:00
|
|
|
.separated_by(just(Token::Comma))
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.map(IndexMap::from_iter)
|
2024-04-08 12:04:52 +00:00
|
|
|
.delimited_by(just(Token::BraceOpen), just(Token::BraceClose))
|
2024-04-03 15:00:20 +00:00
|
|
|
.map_with(|v, e| (v, e.span()))
|
|
|
|
.labelled("attrset");
|
2024-04-02 22:08:00 +00:00
|
|
|
|
|
|
|
let node = word
|
2024-04-11 01:23:03 +00:00
|
|
|
.repeated()
|
|
|
|
.collect()
|
2024-04-02 22:08:00 +00:00
|
|
|
.then(attrset.clone().or_not())
|
2024-04-06 22:55:12 +00:00
|
|
|
.map_with(|(name, params), extra| {
|
2024-04-11 01:23:03 +00:00
|
|
|
RawExpression::new(RawExpr::Node(name, params), extra.span())
|
2024-04-06 22:55:12 +00:00
|
|
|
})
|
2024-04-11 01:23:03 +00:00
|
|
|
// .or(var)
|
|
|
|
// .or(attrset
|
|
|
|
// .map_with(|attrset, extra| Expression::new(Expr::AttrSet(attrset), extra.span())))
|
|
|
|
// .or(lit)
|
|
|
|
// .or(mat)
|
2024-04-03 15:00:20 +00:00
|
|
|
.labelled("node");
|
2024-04-02 22:08:00 +00:00
|
|
|
|
2024-04-11 01:23:03 +00: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-06 22:55:12 +00:00
|
|
|
#[allow(clippy::let_and_return)]
|
2024-04-11 01:23:03 +00:00
|
|
|
let pipeline = atom
|
2024-04-02 22:08:00 +00:00
|
|
|
.clone()
|
|
|
|
.then(choice((
|
2024-04-11 01:23:03 +00:00
|
|
|
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-02 22:08:00 +00:00
|
|
|
)))
|
|
|
|
.repeated()
|
2024-04-11 01:23:03 +00:00
|
|
|
.foldr_with(atom, |(curr, pipe), next, extra| {
|
|
|
|
RawExpression::new(pipe(curr, next), extra.span())
|
2024-04-02 22:08:00 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
pipeline
|
|
|
|
});
|
|
|
|
|
2024-04-11 01:23:03 +00:00
|
|
|
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-06 22:55:12 +00:00
|
|
|
decls: IndexMap::from_iter([(("main", (0..0).into()), expr)]),
|
2024-04-11 01:23:03 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
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-02 22:08:00 +00:00
|
|
|
}
|
2024-04-08 12:04:52 +00:00
|
|
|
|
|
|
|
pub mod asg {
|
|
|
|
use petgraph::graph::DiGraph;
|
|
|
|
|
|
|
|
use super::Spanned;
|
|
|
|
}
|