use crate::Item;
use crate::Rule;
use crate::SymbolOrRule;
use crate::Var;
use crate::{Symbol, Token};
use syn::Ident;
pub const TOKEN: u8 = 0;
pub const UNDEFINED: i16 = -1;
pub(crate) struct Grammar {
pub nsyms: usize,
pub ntokens: usize,
pub nvars: usize,
pub name: Vec<Ident>,
pub value: Vec<i16>,
pub prec: Vec<i16>,
pub assoc: Vec<u8>,
pub nrules: usize,
pub ritem: Vec<SymbolOrRule>,
pub rlhs: Vec<Symbol>,
pub rrhs: Vec<Item>,
pub rprec: Vec<i16>,
pub rassoc: Vec<u8>,
}
impl Grammar {
pub fn is_var(&self, s: Symbol) -> bool {
s.index() >= self.ntokens
}
pub fn is_token(&self, s: Symbol) -> bool {
s.index() < self.ntokens
}
pub fn start(&self) -> Symbol {
Symbol(self.ntokens as i16)
}
pub fn nitems(&self) -> usize {
self.ritem.len()
}
pub fn ritem(&self, item: Item) -> SymbolOrRule {
self.ritem[item.index()]
}
pub fn name(&self, symbol: Symbol) -> &Ident {
&self.name[symbol.index()]
}
pub fn rule_to_str(&self, r: Rule) -> String {
let mut s = String::new();
s.push_str(&format!("(r{}) {} :", r, self.name(self.rlhs(r))));
for &sym in self.rule_rhs_syms(r).iter() {
let sym = sym.as_symbol();
s.push_str(&format!(" {}", self.name(sym)));
}
s
}
pub fn rule_rhs_syms(&self, rule: Rule) -> &[SymbolOrRule] {
let start = self.rrhs[rule.index()].index();
let end = self.rrhs[rule.index() + 1].index() - 1;
&self.ritem[start..end]
}
pub fn get_rhs_items(&self, r: Rule) -> &[SymbolOrRule] {
let rhs = self.rrhs[r.index()];
assert!(rhs.0 >= 0);
let mut end = rhs.index();
while self.ritem[end].is_symbol() {
end += 1;
}
&self.ritem[rhs.index()..end]
}
pub fn symbol_to_var(&self, sym: Symbol) -> Var {
let su = sym.index();
assert!(su >= self.ntokens);
Var((su - self.ntokens) as i16)
}
pub fn symbol_to_token(&self, sym: Symbol) -> Token {
assert!(sym.index() < self.ntokens);
Token(sym.0)
}
pub fn var_to_symbol(&self, var: Var) -> Symbol {
assert!(var.index() < self.nvars);
Symbol(self.ntokens as i16 + var.0)
}
pub fn iter_vars(&self) -> impl Iterator<Item = Var> {
(0..self.nvars).map(move |i| Var(i as i16))
}
pub fn iter_var_syms(&self) -> impl Iterator<Item = Symbol> {
(self.ntokens..self.nsyms).map(move |i| Symbol(i as i16))
}
#[allow(dead_code)] pub fn iter_token_syms(&self) -> impl Iterator<Item = Symbol> {
(0..self.ntokens).map(move |i| Symbol(i as i16))
}
pub fn iter_rules(&self) -> impl Iterator<Item = Rule> {
(0..self.nrules).map(move |i| Rule(i as i16))
}
pub fn rlhs(&self, rule: Rule) -> Symbol {
self.rlhs[rule.index()]
}
pub fn rrhs(&self, rule: Rule) -> Item {
self.rrhs[rule.index()]
}
}