use std::cmp::{self, Ord, Ordering};
use std::iter;
use std::mem;
use std::slice;
use bit_vec::BitVec;
use analysis::RhsClosure;
use grammar::{ContextFree, ContextFreeRef, ContextFreeMut};
use history::{Binarize, EliminateNulling, NullHistory};
use history::BinarizedRhsSubset::*;
use rule::{GrammarRule, RuleRef};
use rule::container::{RuleContainer, EmptyRuleContainer};
use symbol::{Symbol, SymbolSource};
use symbol::source::SymbolContainer;
use self::BinarizedRuleRhs::*;
#[derive(Clone)]
pub struct BinarizedCfg<H = NullHistory> {
sym_source: SymbolSource,
rules: Vec<BinarizedRule<H>>,
nulling: Vec<Option<H>>,
}
#[derive(Copy, Clone)]
pub struct BinarizedRule<H> {
lhs: Symbol,
rhs: BinarizedRuleRhs,
history: H,
}
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub enum BinarizedRuleRhs {
One([Symbol; 1]),
Two([Symbol; 2]),
}
impl<H> Default for BinarizedCfg<H> {
fn default() -> Self {
Self::with_sym_source(SymbolSource::new())
}
}
impl<H> BinarizedCfg<H> {
pub fn new() -> Self {
Self::default()
}
pub fn with_sym_source(sym_source: SymbolSource) -> Self {
BinarizedCfg {
sym_source: sym_source,
rules: vec![],
nulling: vec![],
}
}
pub fn from_context_free<'a, G>(this: &'a G) -> BinarizedCfg<H>
where G: ContextFree<History = H>,
&'a G: ContextFreeRef<'a, Target = G>,
H: Binarize + Clone + 'static
{
let mut new_rule_count = 0;
for rule in this.rules() {
if !rule.rhs().is_empty() {
new_rule_count += cmp::max(1, rule.rhs().len() - 1);
}
}
let mut grammar = BinarizedCfg::with_sym_source(this.sym_source().clone());
grammar.rules = Vec::with_capacity(new_rule_count);
for rule in this.rules() {
grammar.rule(rule.lhs()).rhs_with_history(rule.rhs(), rule.history().clone());
}
grammar
}
pub fn sort(&mut self) {
self.rules.sort();
}
pub fn sort_by<F>(&mut self, compare: F)
where F: FnMut(&BinarizedRule<H>, &BinarizedRule<H>) -> Ordering
{
self.rules.sort_by(compare);
}
pub fn dedup(&mut self) {
self.rules.dedup();
}
}
impl<H> BinarizedCfg<H>
where H: Binarize
{
pub fn sym<T>(&mut self) -> T
where T: SymbolContainer
{
self.sym_source_mut().sym()
}
pub fn next_sym(&mut self) -> Symbol {
self.sym_source_mut().next_sym()
}
pub fn num_syms(&self) -> usize {
self.sym_source().num_syms()
}
}
impl<H> BinarizedCfg<H>
where H: Binarize + Clone + EliminateNulling
{
pub fn eliminate_nulling_rules(&mut self) -> BinarizedCfg<H> {
let mut nulling_grammar = BinarizedCfg::with_sym_source(self.sym_source.clone());
if self.nulling.iter().any(|h| h.is_some()) {
let mut nulling = mem::replace(&mut self.nulling, vec![]);
let nulling_len = nulling.len();
nulling.extend(iter::repeat(None).take(self.sym_source().num_syms() - nulling_len));
let mut nullable: BitVec = nulling.iter().map(|n| n.is_some()).collect();
let mut productive: BitVec = BitVec::from_elem(self.sym_source().num_syms(), true);
nulling_grammar.nulling = nulling;
for rule in nulling_grammar.rules().chain(self.rules()) {
productive.set(rule.lhs().into(), false);
}
RhsClosure::new(self).rhs_closure(&mut nullable);
let mut rewritten_rules = Vec::new();
for rule in &self.rules {
let left_nullable = nullable[rule.rhs0().into()];
let right_nullable = rule.rhs1().map_or(true, |s| nullable[s.into()]);
if left_nullable && right_nullable {
let history = rule.history().eliminate_nulling(rule, All);
nulling_grammar.rule(rule.lhs()).rhs_with_history(rule.rhs(), history);
}
if rule.rhs().len() == 2 {
let which = &[(rule.rhs()[0], Right), (rule.rhs()[1], Left)];
let with_rhs0 = right_nullable as usize;
let with_rhs1 = left_nullable as usize;
for &(sym, direction) in &which[1 - with_rhs0..1 + with_rhs1] {
rewritten_rules.push(BinarizedRule::new(rule.lhs(),
&[sym],
rule.history()
.eliminate_nulling(rule,
direction)));
}
}
}
self.rules.extend(rewritten_rules);
RhsClosure::new(self).rhs_closure(&mut productive);
self.rules.retain(|rule| {
let left_productive = productive[rule.rhs0().into()];
let right_productive = rule.rhs1().map_or(true, |s| productive[s.into()]);
left_productive && right_productive
});
}
nulling_grammar
}
}
impl<H> ContextFree for BinarizedCfg<H>
where H: Binarize
{
}
pub type BinarizedRules<'a, H> =
iter::Chain<
LhsWithHistoryToRuleRef<
iter::Enumerate<
slice::Iter<'a, Option<H>>
>
>,
BinarizedRuleToRuleRef<
slice::Iter<'a, BinarizedRule<H>>
>
>;
impl<'a, H> ContextFreeRef<'a> for &'a BinarizedCfg<H>
where H: Binarize + 'a
{
type RuleRef = RuleRef<'a, H>;
type Rules = BinarizedRules<'a, H>;
fn rules(self) -> Self::Rules {
LhsWithHistoryToRuleRef::new(self.nulling.iter().enumerate())
.chain(BinarizedRuleToRuleRef::new(self.rules.iter()))
}
}
impl<'a, H> ContextFreeMut<'a> for &'a mut BinarizedCfg<H> where H: Binarize + 'a {}
impl<H> RuleContainer for BinarizedCfg<H>
where H: Binarize
{
type History = H;
fn sym_source(&self) -> &SymbolSource {
&self.sym_source
}
fn sym_source_mut(&mut self) -> &mut SymbolSource {
&mut self.sym_source
}
fn retain<F>(&mut self, mut f: F)
where F: FnMut(Symbol, &[Symbol], &Self::History) -> bool
{
self.rules.retain(|rule| f(rule.lhs(), rule.rhs(), rule.history()));
}
fn add_rule(&mut self, lhs: Symbol, rhs: &[Symbol], history: Self::History) {
let this_rule_ref = RuleRef {
lhs: lhs,
rhs: rhs,
history: &(),
};
if rhs.is_empty() {
while self.nulling.len() <= lhs.into() {
self.nulling.push(None);
}
assert!(self.nulling[lhs.usize()].is_none(),
"Duplicate nulling rule");
self.nulling[lhs.usize()] = Some(history.binarize(&this_rule_ref, 0));
} else {
let mut rhs_iter = rhs.iter().cloned();
let sym_range = cmp::max(rhs.len(), 2) - 2;
let left_iter = self.sym_source.generate().take(sym_range).chain(rhs_iter.next());
let right_iter = rhs_iter.rev().map(Some).chain(iter::once(None));
let mut next_lhs = lhs;
self.rules.extend(left_iter.zip(right_iter)
.enumerate()
.map(|(depth, (left, right))| {
let lhs = next_lhs;
next_lhs = left;
BinarizedRule {
lhs: lhs,
rhs: if let Some(r) = right {
Two([left, r])
} else {
One([left])
},
history: history.binarize(&this_rule_ref, depth),
}
}));
}
}
}
impl<H> EmptyRuleContainer for BinarizedCfg<H> {
fn empty(&self) -> Self {
BinarizedCfg::default()
}
}
impl<H> GrammarRule for BinarizedRule<H> {
type History = H;
fn lhs(&self) -> Symbol {
self.lhs
}
fn rhs(&self) -> &[Symbol] {
match self.rhs {
One(ref slice) => slice,
Two(ref slice) => slice,
}
}
fn history(&self) -> &H {
&self.history
}
}
impl<H> BinarizedRule<H> {
pub fn new(lhs: Symbol, rhs: &[Symbol], history: H) -> Self {
BinarizedRule {
history: history,
lhs: lhs,
rhs: if rhs.len() == 1 {
One([rhs[0]])
} else if rhs.len() == 2 {
Two([rhs[0], rhs[1]])
} else {
unreachable!()
},
}
}
pub fn rhs0(&self) -> Symbol {
match self.rhs {
One(slice) => slice[0],
Two(slice) => slice[0],
}
}
pub fn rhs1(&self) -> Option<Symbol> {
match self.rhs {
One(_) => None,
Two(slice) => Some(slice[1]),
}
}
}
impl<H> PartialEq for BinarizedRule<H> {
fn eq(&self, other: &Self) -> bool {
(self.lhs, &self.rhs) == (other.lhs, &other.rhs)
}
}
impl<H> PartialOrd for BinarizedRule<H> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(self.lhs, &self.rhs).partial_cmp(&(other.lhs, &other.rhs))
}
}
impl<H> Ord for BinarizedRule<H> {
fn cmp(&self, other: &Self) -> Ordering {
(self.lhs, &self.rhs).cmp(&(other.lhs, &other.rhs))
}
}
impl<H> Eq for BinarizedRule<H> {}
pub struct BinarizedRuleToRuleRef<I> {
iter: I,
}
impl<I> BinarizedRuleToRuleRef<I> {
pub fn new(iter: I) -> Self {
BinarizedRuleToRuleRef { iter: iter }
}
}
impl<'a, I, R, H> Iterator for BinarizedRuleToRuleRef<I>
where I: Iterator<Item = &'a R>,
R: GrammarRule<History = H> + 'a,
H: 'a
{
type Item = RuleRef<'a, H>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|rule| {
RuleRef {
lhs: rule.lhs(),
rhs: rule.rhs(),
history: rule.history(),
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
pub type LhsWithHistory<'a, H> = (usize, &'a Option<H>);
pub struct LhsWithHistoryToRuleRef<I> {
iter: I,
}
impl<I> LhsWithHistoryToRuleRef<I> {
pub fn new(iter: I) -> Self {
LhsWithHistoryToRuleRef { iter: iter }
}
}
impl<'a, I, H> Iterator for LhsWithHistoryToRuleRef<I>
where I: Iterator<Item = LhsWithHistory<'a, H>>,
H: 'a
{
type Item = RuleRef<'a, H>;
fn next(&mut self) -> Option<Self::Item> {
for (lhs, history_opt) in &mut self.iter {
if let Some(history) = history_opt.as_ref() {
return Some(RuleRef {
lhs: Symbol::from(lhs),
rhs: &[],
history: history,
});
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}