use super::grammarparser::{Grammar, GrammarBuilder};
use crate::error::Result;
use crate::lexer::{LexedStream, Token};
use crate::span::Span;
use newty::newty;
use std::collections::HashMap;
use std::rc::Rc;
newty! {
#[derive(PartialOrd, Ord)]
pub id RuleId
}
newty! {
pub id NonTerminalId
impl {
pub fn next(&mut self) -> Self {
self.0 += 1;
NonTerminalId(self.0-1)
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Int(i32),
Str(Rc<str>),
Float(f32),
Bool(bool),
}
#[derive(Debug, Clone, PartialEq)]
pub enum AST {
Node {
nonterminal: NonTerminalId,
attributes: HashMap<Rc<str>, AST>,
span: Span,
},
Literal {
value: Value,
span: Option<Span>,
},
Terminal(Token),
}
#[derive(Debug)]
pub struct ParseResult {
pub tree: AST,
}
pub trait Parser<'deserializer> {
type Grammar: Grammar<'deserializer>;
type GrammarBuilder: GrammarBuilder<'deserializer, Grammar = Self::Grammar>;
fn grammar(&self) -> &Self::Grammar;
fn new(grammar: Self::Grammar) -> Self;
fn parse<'input>(
&self,
input: &'input mut LexedStream<'input, 'input>,
) -> Result<ParseResult>;
fn is_valid<'input>(
&self,
input: &'input mut LexedStream<'input, 'input>,
) -> bool {
self.parse(input).is_ok()
}
}
#[macro_export]
macro_rules! include_parser {
(lexer => compiled $path:literal, $($rest:tt)*) => {{
let driver_function =
|| -> $crate::error::Result<($crate::lexer::Lexer, $crate::parser::earley::EarleyParser)> {
let mut warnings = $crate::error::WarningSet::empty();
let lexer_grammar_source = include_bytes!($path);
let lexer_grammar =
$crate::lexer::LexerGrammar::deserialize(lexer_grammar_source)?
.unpack_into(&mut warnings);
let lexer =
$crate::lexer::LexerBuilder::from_grammar(lexer_grammar).build();
let parser = include_parser!(@parser(&mut warnings, lexer) $($rest)*);
warnings.with_ok((lexer, parser))
};
driver_function()
}};
(lexer => $path:literal, $($rest:tt)*) => {{
let driver_function =
|| -> $crate::error::Result<($crate::lexer::Lexer, $crate::parser::earley::EarleyParser)> {
let mut warnings = $crate::error::WarningSet::empty();
let lexer_grammar_source = include_str!($path);
let lexer_grammar_stream = StringStream::new(
::std::path::Path::new($path),
lexer_grammar_source.to_string(),
);
let lexer_grammar =
$crate::lexer::LexerGrammar::from_stream(lexer_grammar_stream)
.build()?
.unpack_into(&mut warnings);
let lexer =
$crate::lexer::LexerBuilder::from_grammar(lexer_grammar).build();
let parser = include_parser!(@parser(&mut warnings, lexer) $($rest)*);
warnings.with_ok((lexer, parser))
};
driver_function()
}};
(@parser($warnings:expr, $lexer:expr) parser => compiled $path:literal $(,)?) => {{
let parser_grammar_source = include_bytes!($path);
let parser_grammar =
<$crate::parser::earley::EarleyGrammar
as $crate::parser::Grammar>::deserialize(parser_grammar_source)?
.unpack_into($warnings);
let parser =
<$crate::parser::earley::EarleyParser
as $crate::parser::Parser>::new(parser_grammar);
parser
}};
(@parser($warnings:expr, $lexer:expr) parser => $path:literal $(,)?) => {{
let parser_grammar_source = include_str!($path);
let parser_grammar_stream = StringStream::new(
::std::path::Path::new($path),
parser_grammar_source.to_string(),
);
let parser_grammar =
$crate::parser::earley::EarleyGrammarBuilder::default()
.with_stream(parser_grammar_stream)
.build(&lexer)?
.unpack_into($warnings);
let parser =
<$crate::parser::earley::EarleyParser
as $crate::parser::Parser>::new(parser_grammar);
parser
}};
}