pub use identifier::*;
pub use syn::spanned::Spanned;
use std::fmt::{Formatter, Display, Error};
pub use partial::Partial;
pub use middle::typing::ast::IType;
pub use middle::typing::ast::Type;
use middle::analysis::ast::GrammarAttributes;
use std::collections::HashMap;
use std::default::Default;
use std::ops::{Index, IndexMut};
use syn::parse_quote;
pub trait ExprByIndex
{
fn expr_by_index(&self, index: usize) -> Expression;
}
pub struct Grammar<ExprInfo>
{
pub start_span: Span,
pub rules: Vec<Rule>,
pub exprs: Vec<Expression>,
pub exprs_info: Vec<ExprInfo>,
pub stream_alias: syn::ItemType,
pub rust_functions: HashMap<Ident, syn::ItemFn>,
pub rust_items: Vec<syn::Item>,
pub attributes: GrammarAttributes
}
impl<ExprInfo> Grammar<ExprInfo>
{
pub fn new(start_span: Span, exprs: Vec<Expression>,
exprs_info: Vec<ExprInfo>) -> Grammar<ExprInfo>
{
Grammar {
start_span,
rules: vec![],
exprs,
exprs_info,
stream_alias: parse_quote!(pub type Stream<'a> = StrStream<'a>;),
rust_functions: HashMap::new(),
rust_items: vec![],
attributes: GrammarAttributes::default()
}
}
pub fn find_rule_by_ident(&self, id: &Ident) -> Rule {
self.rules.iter()
.find(|r| r.ident().to_string() == id.to_string())
.expect("Rule ident not registered in the known rules.")
.clone()
}
pub fn expr_index_of_rule(&self, id: &Ident) -> usize {
self.find_rule_by_ident(id).expr_idx
}
pub fn stream_generics(&self) -> syn::Generics {
self.stream_alias.generics.clone()
}
pub fn stream_type(&self) -> syn::Type {
let name = self.stream_alias.ident.clone();
let (_, ty_generics, _) = self.stream_alias.generics.split_for_impl();
let stream_ty: syn::Type = parse_quote!(#name #ty_generics);
stream_ty
}
pub fn span_type(&self) -> syn::Type {
let range_ty: syn::Type = self.range_type();
parse_quote!(<#range_ty as StreamSpan>::Output)
}
pub fn range_type(&self) -> syn::Type {
let stream_ty = self.stream_type();
parse_quote!(Range<#stream_ty>)
}
}
impl<ExprInfo> Index<usize> for Grammar<ExprInfo>
{
type Output = ExprInfo;
fn index<'a>(&'a self, index: usize) -> &'a Self::Output {
&self.exprs_info[index]
}
}
impl<ExprInfo> IndexMut<usize> for Grammar<ExprInfo>
{
fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Self::Output {
&mut self.exprs_info[index]
}
}
impl<ExprInfo> ExprByIndex for Grammar<ExprInfo>
{
fn expr_by_index(&self, index: usize) -> Expression {
self.exprs[index].clone()
}
}
#[derive(Clone)]
pub struct Rule
{
pub name: Ident,
pub expr_idx: usize,
}
impl Rule
{
pub fn new(name: Ident, expr_idx: usize) -> Rule {
Rule { name, expr_idx }
}
}
impl ItemIdent for Rule
{
fn ident(&self) -> Ident {
self.name.clone()
}
}
impl Spanned for Rule
{
fn span(&self) -> Span {
self.name.span().clone()
}
}
#[derive(Clone, Debug)]
pub enum Expression
{
StrLiteral(String), AnySingleChar, CharacterClass(CharacterClassExpr), NonTerminalSymbol(Ident), ExternalNonTerminalSymbol(syn::Path), Sequence(Vec<usize>), Choice(Vec<usize>), ZeroOrMore(usize), OneOrMore(usize), ZeroOrOne(usize), NotPredicate(usize), AndPredicate(usize), SemanticAction(usize, bool, syn::Expr), TypeAscription(usize, IType), SpannedExpr(usize), RangeExpr(usize), }
#[derive(Clone, Debug)]
pub struct CharacterClassExpr
{
pub intervals: Vec<CharacterInterval>
}
impl CharacterClassExpr
{
pub fn new(intervals: Vec<CharacterInterval>) -> CharacterClassExpr {
CharacterClassExpr {
intervals: intervals
}
}
}
impl Display for CharacterClassExpr
{
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
formatter.write_str("[\"")?;
for interval in &self.intervals {
interval.fmt(formatter)?;
}
formatter.write_str("\"]")
}
}
#[derive(Clone, Debug)]
pub struct CharacterInterval
{
pub lo: char,
pub hi: char
}
impl CharacterInterval
{
pub fn new(lo: char, hi: char) -> CharacterInterval {
CharacterInterval {
lo: lo,
hi: hi
}
}
pub fn escape_lo(&self) -> String {
self.lo.escape_default().collect()
}
pub fn escape_hi(&self) -> String {
self.hi.escape_default().collect()
}
}
impl Display for CharacterInterval
{
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
if self.lo == self.hi {
formatter.write_str(self.escape_lo().as_str())
}
else {
formatter.write_fmt(format_args!("{}-{}", self.escape_lo(), self.escape_hi()))
}
}
}
pub fn display_path_cycle(path: &Vec<Ident>) -> String {
let mut path_desc = String::new();
for rule in path {
path_desc.extend(format!("{} -> ", rule).chars());
}
path_desc.extend(format!("{}", path[0]).chars());
path_desc
}