Definition t := terminal.Instance tComparable : Comparable t := _.Module TerminalOrderedType := OrderedType_from_ComparableM TerminalComparableM.Definition t := (state*production*nat)%type.Instance tComparable : Comparable t := _.Module StateProdPosOrderedType :=
  OrderedType_from_ComparableM StateProdPosComparableM.Module TerminalSet := FSetAVL.Make TerminalOrderedType.Module StateProdPosMap := FMapAVL.Make StateProdPosOrderedType.(** Nullable predicate for symbols and list of symbols. **)
Definition nullable_symb (symbol:symbol) :=
  match symbol with
    | NT nt => nullable_nterm nt
    | _ => false
  end.Definition nullable_word (word:list symbol) :=
  forallb nullable_symb word.(** First predicate for non terminal, symbols and list of symbols, given as FSets. **)
Definition first_nterm_set (nterm:nonterminal) :=
  fold_left (fun acc t => TerminalSet.add t acc)
    (first_nterm nterm) TerminalSet.empty.Definition first_symb_set (symbol:symbol) :=
  match symbol with
    | NT nt => first_nterm_set nt
    | T t => TerminalSet.singleton t
  end.(** We build a fast map to store all the items of all the states. **)
Definition items_map (_:unit): StateProdPosMap.t TerminalSet.t :=
  fold_left (fun acc state =>
    fold_left (fun acc item =>
      let key := (state, prod_item item, dot_pos_item item) in
        let data := fold_left (fun acc t => TerminalSet.add t acc)
          (lookaheads_item item) TerminalSet.empty
        in
        let old :=
          match StateProdPosMap.find key acc with
            | Some x => x | None => TerminalSet.empty
          end
        in
        StateProdPosMap.add key (TerminalSet.union data old) acc
    ) (items_of_state state) acc
  ) all_list (StateProdPosMap.empty TerminalSet.t).(** Accessor. **)
Definition find_items_map items_map state prod dot_pos : TerminalSet.t :=
  match StateProdPosMap.find (state, prod, dot_pos) items_map with
    | None => TerminalSet.empty
    | Some x => x
  end.Definition state_has_future state prod (fut:list symbol) (lookahead:terminal) :=
  exists dot_pos:nat,
    fut = future_of_prod prod dot_pos /\
    TerminalSet.In lookahead (find_items_map (items_map ()) state prod dot_pos).(** Iterator over items. **)
Definition forallb_items items_map (P:state -> production -> nat -> TerminalSet.t -> bool): bool:=
  StateProdPosMap.fold (fun key set acc =>
    match key with (st, p, pos) => (acc && P st p pos set)%bool end
  ) items_map true.

(* Specifications: *)
Lemma forallb_items_spec : forall p, forallb_items (items_map ()) p = true -> forall st prod fut lookahead, state_has_future st prod fut lookahead -> forall P:state -> production -> list symbol -> terminal -> Prop, (forall st prod pos set lookahead, TerminalSet.In lookahead set -> p st prod pos set = true -> P st prod (future_of_prod prod pos) lookahead) -> P st prod fut lookahead.