139 lines
3.3 KiB
Rust
139 lines
3.3 KiB
Rust
use pest::Parser;
|
|
use pest_derive::Parser;
|
|
|
|
pub mod ast;
|
|
pub mod error;
|
|
pub mod parser;
|
|
pub mod rev_mapper;
|
|
pub mod semantics;
|
|
|
|
use ast::*;
|
|
|
|
use crate::error::{IntoErr, ParseError};
|
|
|
|
#[derive(Parser)]
|
|
#[grammar = "./src/grammar.pest"]
|
|
pub struct MistParser;
|
|
|
|
pub struct Program {
|
|
pub mod_attributes: Vec<TopLevel>,
|
|
pub items: Vec<TopLevel>,
|
|
}
|
|
|
|
pub fn parse<'a>(source: &'a str) -> Result<Program, ParseError<'a, Vec<TopLevel>>> {
|
|
let mut pairs = MistParser::parse(Rule::program, source)?;
|
|
|
|
let mut statements = vec![];
|
|
|
|
let mut analyzer = error::AstErrorAnalyzer(None);
|
|
|
|
for pair in pairs.next().unwrap().into_inner() {
|
|
if pair.as_rule() != Rule::EOI {
|
|
statements.push(analyzer.get(TopLevel::try_from(pair)).get()?);
|
|
}
|
|
}
|
|
|
|
match analyzer.build(statements) {
|
|
Ok(v) => {
|
|
let (mod_attributes, items): (Vec<_>, Vec<_>) = v
|
|
.into_iter()
|
|
.partition(|item| matches!(item.0.item, TopLevelKind::ModAttribute));
|
|
|
|
Ok(Program {
|
|
items,
|
|
mod_attributes,
|
|
})
|
|
}
|
|
Err(e) => {
|
|
let rec = e.recovered.clone();
|
|
|
|
let mut e2 = e.get();
|
|
|
|
e2.recovered = rec;
|
|
|
|
Err(ParseError::Ast(e2))
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn parse_module<'a>(
|
|
source: &'a str,
|
|
) -> Result<Option<(Visibility, Identifier)>, ParseError<'a, Option<(Visibility, Identifier)>>> {
|
|
let mut pairs = MistParser::parse(Rule::module_program, source)?;
|
|
|
|
if let Some(v) = pairs
|
|
.next()
|
|
.unwrap()
|
|
.into_inner()
|
|
.next()
|
|
.map(TopLevel::try_from)
|
|
.transpose()
|
|
.get()?
|
|
{
|
|
if let TopLevelKind::DeclareModule(vis, name) = &v.0.item {
|
|
Ok(Some((vis.clone(), name.clone())))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! ast_ensure {
|
|
($pair:expr, $rule:expr $(, $rules:expr)* => $body:block) => {
|
|
if $pair.as_rule() == $rule $(|| $pair.as_rule() == $rules)*
|
|
$body
|
|
else {
|
|
Err(AstError {
|
|
span: $pair.as_span(),
|
|
error_code: crate::error::ErrorCode::AstGenBug,
|
|
error_message: format!("Possible bug: expected {:?}, got {:?}", $rule, $pair.as_rule()),
|
|
recovered: None,
|
|
})
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! ast_expr {
|
|
(use $r:expr, $($v:expr),* $(,)?) => {{
|
|
let mut analyzer = $crate::error::AstErrorAnalyzer(None);
|
|
|
|
$(
|
|
analyzer.get($v).get()?;
|
|
)*
|
|
|
|
analyzer.build($r)
|
|
}};
|
|
|
|
($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{
|
|
let mut analyzer = $crate::error::AstErrorAnalyzer(None);
|
|
|
|
let v = $($item)::+ { $($k: analyzer.get($v).get()?),* };
|
|
|
|
analyzer.build(v)
|
|
}};
|
|
|
|
($($item:ident)::+ ( $($v:expr),* $(,)? )) => {{
|
|
let mut analyzer = $crate::error::AstErrorAnalyzer(None);
|
|
|
|
let v = $($item)::+ ( $(analyzer.get($v).get()?),* );
|
|
|
|
analyzer.build(v)
|
|
}};
|
|
|
|
(( $($v:expr),* $(,)? )) => {{
|
|
let mut analyzer = $crate::error::AstErrorAnalyzer(None);
|
|
|
|
let v = ( $(analyzer.get($v).get()?),* );
|
|
|
|
analyzer.build(v)
|
|
}};
|
|
|
|
($($item:ident)::+) => {
|
|
$($item)::+
|
|
};
|
|
}
|