backup commit

This commit is contained in:
2022-10-24 03:16:04 +01:00
parent fbbd6ed256
commit 778c87db77
43 changed files with 1156 additions and 174 deletions

View File

@@ -1,3 +1,9 @@
/// Produces parsers for tokenized sequences of enum types:
/// ```rs
/// enum_parser!(Foo::Bar | "Some error!") // Parses Foo::Bar(T) into T
/// enum_parser!(Foo::Bar) // same as above but with the default error "Expected Foo::Bar"
/// enum_parser!(Foo >> Quz; Bar, Baz) // Parses Foo::Bar(T) into Quz::Bar(T) and Foo::Baz(U) into Quz::Baz(U)
/// ```
#[macro_export]
macro_rules! enum_parser {
($p:path | $m:tt) => {

View File

@@ -1,11 +1,11 @@
use chumsky::{self, prelude::*, Parser};
use mappable_rc::Mrc;
use crate::enum_parser;
use crate::expression::{Clause, Expr, Literal};
use crate::utils::to_mrc_slice;
use crate::representations::{Literal, ast::{Clause, Expr}};
use crate::utils::{to_mrc_slice, one_mrc_slice};
use super::lexer::Lexeme;
/// Parses any number of expr wrapped in (), [] or {}
fn sexpr_parser<P>(
expr: P
) -> impl Parser<Lexeme, Clause, Error = Simple<Lexeme>> + Clone
@@ -13,6 +13,8 @@ where P: Parser<Lexeme, Expr, Error = Simple<Lexeme>> + Clone {
Lexeme::paren_parser(expr.repeated()).map(|(del, b)| Clause::S(del, to_mrc_slice(b)))
}
/// Parses `\name.body` or `\name:type.body` where name is any valid name and type and body are
/// both expressions. Comments are allowed and ignored everywhere in between the tokens
fn lambda_parser<P>(
expr: P
) -> impl Parser<Lexeme, Clause, Error = Simple<Lexeme>> + Clone
@@ -37,6 +39,7 @@ where P: Parser<Lexeme, Expr, Error = Simple<Lexeme>> + Clone {
})
}
/// see [lambda_parser] but `@` instead of `\` and the name is optional
fn auto_parser<P>(
expr: P
) -> impl Parser<Lexeme, Clause, Error = Simple<Lexeme>> + Clone
@@ -50,17 +53,22 @@ where P: Parser<Lexeme, Expr, Error = Simple<Lexeme>> + Clone {
.then_ignore(enum_parser!(Lexeme::Comment).repeated())
.ignore_then(expr.clone().repeated())
.then_ignore(enum_parser!(Lexeme::Comment).repeated())
.or_not().map(Option::unwrap_or_default)
)
.then_ignore(just(Lexeme::name(".")))
.then_ignore(enum_parser!(Lexeme::Comment).repeated())
.then(expr.repeated().at_least(1))
.try_map(|((name, typ), body), s| if name.is_none() && typ.is_empty() {
Err(Simple::custom(s, "Auto without name or type has no effect"))
} else {
Ok(Clause::Auto(name, to_mrc_slice(typ), to_mrc_slice(body)))
.try_map(|((name, typ), body): ((Option<String>, Vec<Expr>), Vec<Expr>), s| {
if name.is_none() && typ.is_empty() {
Err(Simple::custom(s, "Auto without name or type has no effect"))
} else {
Ok(Clause::Auto(name, to_mrc_slice(typ), to_mrc_slice(body)))
}
})
}
/// Parses a sequence of names separated by :: <br/>
/// Comments are allowed and ignored in between
fn name_parser() -> impl Parser<Lexeme, Vec<String>, Error = Simple<Lexeme>> + Clone {
enum_parser!(Lexeme::Name).separated_by(
enum_parser!(Lexeme::Comment).repeated()
@@ -69,6 +77,7 @@ fn name_parser() -> impl Parser<Lexeme, Vec<String>, Error = Simple<Lexeme>> + C
).at_least(1)
}
/// Parse any legal argument name starting with a `$`
fn placeholder_parser() -> impl Parser<Lexeme, String, Error = Simple<Lexeme>> + Clone {
enum_parser!(Lexeme::Name).try_map(|name, span| {
name.strip_prefix('$').map(&str::to_string)
@@ -76,7 +85,7 @@ fn placeholder_parser() -> impl Parser<Lexeme, String, Error = Simple<Lexeme>> +
})
}
/// Parse an expression without a type annotation
/// Parse an expression
pub fn xpr_parser() -> impl Parser<Lexeme, Expr, Error = Simple<Lexeme>> {
recursive(|expr| {
let clause =
@@ -102,12 +111,17 @@ pub fn xpr_parser() -> impl Parser<Lexeme, Expr, Error = Simple<Lexeme>> {
}),
sexpr_parser(expr.clone()),
lambda_parser(expr.clone()),
auto_parser(expr.clone())
auto_parser(expr.clone()),
just(Lexeme::At).to(Clause::Name {
local: Some("@".to_string()),
qualified: one_mrc_slice("@".to_string())
})
))).then_ignore(enum_parser!(Lexeme::Comment).repeated());
clause.clone().then(
just(Lexeme::Type)
.ignore_then(expr.clone()).or_not()
.ignore_then(clause.clone())
.repeated()
)
.map(|(val, typ)| Expr(val, typ.map(Mrc::new)))
.map(|(val, typ)| Expr(val, to_mrc_slice(typ)))
}).labelled("Expression")
}

View File

@@ -10,6 +10,7 @@ use super::lexer::Lexeme;
#[derive(Debug, Clone)]
pub struct Import {
pub path: Mrc<[String]>,
/// If name is None, this is a wildcard import
pub name: Option<String>
}

View File

@@ -19,6 +19,7 @@ fn op_parser<'a, T: AsRef<str> + Clone>(ops: &[T]) -> BoxedParser<'a, char, Stri
/// - `"` and `'` are read as primitives and would never match.
/// - `(` and `)` are strictly balanced and this must remain the case for automation and streaming.
/// - `.` is the discriminator for parametrics.
/// - ',' is always a standalone single operator, so it can never be part of a name
///
/// FIXME: `@name` without a dot should be parsed correctly for overrides. Could be an operator but
/// then parametrics should take precedence, which might break stuff. investigate.

View File

@@ -4,7 +4,7 @@ use chumsky::{prelude::{Simple, end}, Stream, Parser};
use itertools::Itertools;
use thiserror::Error;
use crate::{expression::Rule, parse::lexer::LexedText};
use crate::{ast::Rule, parse::lexer::LexedText};
use super::{Lexeme, FileEntry, lexer, line_parser, LexerEntry};

View File

@@ -1,7 +1,7 @@
use std::collections::HashSet;
use crate::{enum_parser, box_chain};
use crate::expression::{Expr, Clause, Rule};
use crate::ast::{Expr, Clause, Rule};
use crate::utils::to_mrc_slice;
use crate::utils::Stackframe;
use crate::utils::iter::box_empty;
@@ -74,8 +74,8 @@ fn visit_all_names_expr_recur<'a, F>(
) where F: FnMut(&'a [String]) {
let Expr(val, typ) = expr;
visit_all_names_clause_recur(val, binds.clone(), cb);
if let Some(t) = typ {
visit_all_names_expr_recur(t, binds, cb)
for typ in typ.as_ref() {
visit_all_names_clause_recur(typ, binds.clone(), cb);
}
}