(* We do not declare this lemma as an instance, and use [Hint Extern]
instead, because the typeclass mechanism has trouble instantiating
some evars if we do not explicitely call [eassumption]. *)
Hint Extern 2 (IsValidator (state_has_future _ _ _ _) _) =>
eapply is_validator_state_has_future_subset; [eassumption|eassumption || reflexivity|]
: typeclass_instances.
Proof. intros Hlset%TerminalSet.elements_1 Hval Val. apply Hval. revert Val. rewrite TerminalSet.fold_1. generalize true at 1. clear -Hlset. induction Hlset as [? l <-%compare_eq|? l ? IH]=> /= b' Val. - destruct (b lookahead). by destruct b'. exfalso. by induction l; destruct b'. - eauto. Qed.
Hint Extern 100 (IsValidator _ _) =>
match goal with
| H : TerminalSet.In ?lookahead ?lset |- _ =>
eapply (is_validator_iterate_lset _ (fun lookahead => _) _ _ H); clear H
end
: typeclass_instances.
Proof. Admitted.
Proof. intros -> Hval1 Hval2 Val st prod fut lookahead (pos & -> & Hlookahead). rewrite /forallb_items StateProdPosMap.fold_1 in Val. assert (match future_of_prod prod pos with
| [] => b1 st prod pos (find_items_map (items_map ()) st prod pos)
| s :: fut' => b2 st prod pos (find_items_map (items_map ()) st prod pos) s fut'
end = true). - unfold find_items_map in *. assert (Hfind := @StateProdPosMap.find_2 _ (items_map ()) (st, prod, pos)). destruct StateProdPosMap.find as [lset|]; [|by edestruct (TerminalSet.empty_1); eauto]. specialize (Hfind _ eq_refl). apply StateProdPosMap.elements_1 in Hfind. revert Val. generalize true at 1. induction Hfind as [[? ?] l [?%compare_eq ?]|??? IH]=>?. + simpl in *; subst. match goal with |- _ -> ?X = true => destruct X end; [done|]. rewrite Bool.andb_false_r. clear. induction l as [|[[[??]?]?] l IH]=>//. + apply IH. - destruct future_of_prod eqn:EQ. by eapply Hval1; eauto. eapply Hval2 with (pos := pos); eauto; []. revert EQ. unfold future_of_prod=>-> //. Qed.
(* We need a hint for expplicitely instantiating b1 and b2 with lambdas. *)
Hint Extern 0 (IsValidator
(forall st prod fut lookahead,
state_has_future st prod fut lookahead -> _)
_) =>
eapply (is_validator_forall_items _ (fun st prod pos lset => _)
_ (fun st prod pos lset s fut' => _))
: typeclass_instances.
Proof. Admitted.
Proof. move=> -> /forallb_forall Val look. specialize (Val look (all_list_forall _)). exists 0. split=>//. by apply TerminalSet.mem_2. Qed.
(** * Validation for completeness **)
(** The nullable predicate is a fixpoint : it is correct. **)
Definition nullable_stable :=
forall p:production,
if nullable_word (prod_rhs_rev p) then
nullable_nterm (prod_lhs p) = true
else True. (** The first predicate is a fixpoint : it is correct. **)
Definition first_stable:=
forall (p:production),
TerminalSet.Subset (first_word_set (rev' (prod_rhs_rev p)))
(first_nterm_set (prod_lhs p)). (** The initial state has all the S=>.u items, where S is the start non-terminal **)
Definition start_future :=
forall (init:initstate) (p:production),
prod_lhs p = start_nt init ->
forall (t:terminal),
state_has_future init p (rev' (prod_rhs_rev p)) t. (** If a state contains an item of the form A->_.av[[b]], where a is a
terminal, then reading an a does a [Shift_act], to a state containing
an item of the form A->_.v[[b]]. **)
Definition terminal_shift :=
forall (s1:state) prod fut lookahead,
state_has_future s1 prod fut lookahead ->
match fut with
| T t::q =>
match action_table s1 with
| Lookahead_act awp =>
match awp t with
| Shift_act s2 _ =>
state_has_future s2 prod q lookahead
| _ => False
end
| _ => False
end
| _ => True
end. (** If a state contains an item of the form A->_.[[a]], then either we do a
[Default_reduce_act] of the corresponding production, either a is a
terminal (ie. there is a lookahead terminal), and reading a does a
[Reduce_act] of the corresponding production. **)
Definition end_reduce :=
forall (s:state) prod fut lookahead,
state_has_future s prod fut lookahead ->
match fut with
| [] =>
match action_table s with
| Default_reduce_act p => p = prod
| Lookahead_act awt =>
match awt lookahead with
| Reduce_act p => p = prod
| _ => False
end
end
| _ => True
end. Definition is_end_reduce items_map :=
forallb_items items_map (fun s prod pos lset =>
match future_of_prod prod pos with
| [] =>
match action_table s with
| Default_reduce_act p => compare_eqb p prod
| Lookahead_act awt =>
TerminalSet.fold (fun lookahead acc =>
match awt lookahead with
| Reduce_act p => (acc && compare_eqb p prod)%bool
| _ => false
end) lset true
end
| _ => true
end). (** If a state contains an item of the form A->_.Bv[[b]], where B is a
non terminal, then the goto table says we have to go to a state containing
an item of the form A->_.v[[b]]. **)
Definition non_terminal_goto :=
forall (s1:state) prod fut lookahead,
state_has_future s1 prod fut lookahead ->
match fut with
| NT nt::q =>
match goto_table s1 nt with
| Some (exist _ s2 _) =>
state_has_future s2 prod q lookahead
| None => False
end
| _ => True
end. Definition start_goto :=
forall (init:initstate),
match goto_table init (start_nt init) with
| None => True
| Some _ => False
end. (** Closure property of item sets : if a state contains an item of the form
A->_.Bv[[b]], then for each production B->u and each terminal a of
first(vb), the state contains an item of the form B->_.u[[a]] **)
Definition non_terminal_closed :=
forall s1 prod fut lookahead,
state_has_future s1 prod fut lookahead ->
match fut with
| NT nt::q =>
forall p, prod_lhs p = nt ->
(if nullable_word q then
state_has_future s1 p (future_of_prod p 0) lookahead
else True) /\
(forall lookahead2,
TerminalSet.In lookahead2 (first_word_set q) ->
state_has_future s1 p (future_of_prod p 0) lookahead2)
| _ => True
end. (** The automaton is complete **)
Definition complete :=
nullable_stable /\ first_stable /\ start_future /\ terminal_shift
/\ end_reduce /\ non_terminal_goto /\ start_goto /\ non_terminal_closed.
Proof. intros im. subst is_complete_0. instantiate (1:=fun im => _). apply _. Qed.