definition firstKeysForProd :: "('n, 't) prod ==> 'n set ==> ('n, 't) first_map ==> ('n, 't) table_key list"where "firstKeysForProd ≡ (λ(x, gamma) nu fi. map (λla. (x, la)) (firstGamma gamma nu fi))"
definition followKeysForProd :: "('n, 't) prod ==> 'n set ==> ('n, 't) first_map ==> ('n, 't) follow_map ==> ('n, 't) table_key list"where "followKeysForProd ≡ (λ(x, gamma) nu fi fo. map (λla. (x, la)) (if nullableGamma gamma nu then findOrEmpty x fo else []))"
abbreviation keysForProd :: "'n set ==> ('n, 't) first_map ==> ('n, 't) follow_map ==> ('n, 't) prod ==> ('n, 't) table_key list"where "keysForProd nu fi fo xp ≡ (firstKeysForProd xp nu fi) @ (followKeysForProd xp nu fi fo)"
fun addEntries :: "('n × 't lookahead) list ==> ('n, 't) prod ==> ('n, 't) ll1_parse_table ==> ('n, 't) ll1_parse_table"where "addEntries (k # keys) xp (PT pt) = (case fmlookup pt k of None ==> addEntries keys xp (PT (fmupd k xp pt)) | Some xp' ==> (if xp = xp' then addEntries keys xp (PT pt) else ERROR_GRAMMAR_NOT_LL1_AMB_LA (snd k, xp, xp')))"
| "addEntries keys xp pt = pt"
fun mkParseTable' :: "('n, 't) prods ==> 'n set ==> ('n, 't) first_map ==> ('n, 't) follow_map ==> ('n, 't) ll1_parse_table ==> ('n, 't) ll1_parse_table"where "mkParseTable' [] nu fi fo pt = pt"
| "mkParseTable' (p # ps) nu fi fo pt = (let las = keysForProd nu fi fo p in mkParseTable' ps nu fi fo (addEntries las p pt))"
definition mkParseTable :: "('n, 't) grammar ==> ('n, 't) ll1_parse_table"where "mkParseTable g = (let nu = mkNullableSet g; fi = mkFirstMap g nu; fo = mkFollowMap g nu fi in mkParseTable' (prods g) nu fi fo (PT fmempty))"
subsection‹Correctness Definitions›
definition pt_sound :: "('n, 't) parse_table ==> ('n, 't) grammar ==> bool"where "pt_sound pt g ≡ (∀x x' la gamma. fmlookup pt (x', la) = Some (x, gamma) ⟶ x' = x ∧ (x, gamma) ∈ set (prods g) ∧ lookahead_for la x gamma g)"
definition pt_complete :: "('n, 't) parse_table ==> ('n, 't) grammar ==> bool"where "pt_complete pt g ≡ (∀x la gamma. (x, gamma) ∈ set (prods g) ∧ lookahead_for la x gamma g ⟶ fmlookup pt (x, la) = Some (x, gamma))"
lemma firstKeysForProd_lookaheads: assumes"nullable_set_for nu g""first_map_for fi g""follow_map_for fo g" "(x, la) ∈ set (firstKeysForProd (y, gamma) nu fi)" shows"x = y ∧ lookahead_for la x gamma g" using assms firstGamma_first_gamma unfolding firstKeysForProd_def lookahead_for_def byfastforce
lemma followKeysForProd_lookaheads: assumes"nullable_set_for nu g""first_map_for fi g""follow_map_for fo g" "(x, la) ∈ set (followKeysForProd (y, gamma) nu fi fo)" shows"x = y ∧ lookahead_for la x gamma g" proof (cases "nullableGamma gamma nu") case True with assms(4) have"la ∈ set (findOrEmpty x fo)"by (auto simp add: followKeysForProd_def) thenhave"follow_sym g la (NT x)"using assms(3) follow_map_sound_def in_findOrEmpty_exists_set by fast thenhave"nullable_gamma g gamma ∧ follow_sym g la (NT x)" using True assms(1) nu_sound_nullableGamma_sound by blast moreoverhave"x = y"using assms(4) by (auto simp add: followKeysForProd_def) ultimatelyshow ?thesis by (simp add: lookahead_for_def) next case False thenshow ?thesis using assms unfolding followKeysForProd_def lookahead_for_def by simp qed
lemma keys_are_lookaheads: assumes"nullable_set_for nu g""first_map_for fi g""follow_map_for fo g" "(x, la) ∈ set (keysForProd nu fi fo (y, gamma))" shows"x = y ∧ lookahead_for la y gamma g" using assms firstKeysForProd_lookaheads followKeysForProd_lookaheads by fastforce
lemma findOrEmpty_sset_laOf_fi: "first_map_for fi g ==> set (findOrEmpty x fi) ⊆ lookaheadsOf g" proof fix y assume A: "first_map_for fi g""y ∈ set (findOrEmpty x fi)" thenobtain s where"fmlookup fi x = Some s""y ∈ set s"using in_findOrEmpty_exists_set by
fastforce thenshow"y ∈ lookaheadsOf g"using A by (auto intro: first_map_la_in_lookaheadsOf) qed
lemma follow_sym_in_lookaheadsOf: "follow_sym g la (NT x) ==> la ∈ lookaheadsOf g" proof (induction rule: follow_sym.induct) case (FollowRight x1 gpre x2 gsuf la) have"la ∈ lookaheadsOf g" using FollowRight.hyps mkFirstMap_correct mkNullableSet_correct by - (rule in_firstGamma_in_lookaheadsOf[where ?gpre="gpre @ [NT x2]"],
auto intro: first_gamma_firstGamma) thenshow ?caseunfolding lookaheadsOf_def by auto qed (simp add: lookaheadsOf_def)
lemma follow_map_la_in_lookaheadsOf: "follow_map_for fo g ==> fmlookup fo x = Some s ==> la ∈ set s ==> la ∈ lookaheadsOf g" unfolding follow_map_sound_def using follow_sym_in_lookaheadsOf by fastforce
lemma findOrEmpty_sset_laOf_fo: "follow_map_for fo g ==> set (findOrEmpty x fo) ⊆lookaheadsOf g" proof fix y assume A: "follow_map_for fo g""y ∈ set (findOrEmpty x fo)" thenobtain s where"fmlookup fo x = Some s""y ∈ set s"using in_findOrEmpty_exists_set by
fastforce thenshow"y ∈ lookaheadsOf g"using A by (auto intro: follow_map_la_in_lookaheadsOf) qed
lemma addEntries_preserves_soundness: assumes"nullable_set_for nu g""first_map_for fi g""follow_map_for fo g""p ∈ set (prods g)" shows"pt_sound pt g ==> set las ⊆ set (keysForProd nu fi fo p) ==> addEntries las p (PT pt) = PT pt' ==> pt_sound pt' g" proof (induction las arbitrary: pt pt') case Nil thenshow ?caseby auto next case (Cons k las)
consider (lookup_pt_None) "fmlookup pt k = None"
| (lookup_pt_Same) "fmlookup pt k = Some p"using Cons.prems(3) by fastforce thenshow ?case proof cases case lookup_pt_None have"pt_sound (fmupd k p pt) g"unfolding pt_sound_def proof clarify fix x x' la gamma assume assm: "fmlookup (fmupd k p pt) (x', la) = Some (x, gamma)" show"x' = x ∧ (x, gamma) ∈ set (prods g) ∧ lookahead_for la x gamma g" proof (cases "k = (x', la)") case True thenhave"p = (x, gamma)"using assm by auto thenshow ?thesis using assms(1-4) Cons.prems(2) keys_are_lookaheads True by fastforce next case False thenshow ?thesis using Cons.prems(1) assm unfolding pt_sound_def by auto qed qed thenshow ?thesis using Cons.IH Cons.prems(2,3) lookup_pt_None by auto next case lookup_pt_Same thenshow ?thesis using Cons by auto qed qed
lemma mkParseTable'_nested: "mkParseTable' suf nu fi fo (mkParseTable' pre nu fi fo pt) = mkParseTable' (pre @ suf) nu fi fo pt" by (inductionpre arbitrary: pt) auto
lemma mkParseTable'_failure_preserved: "mkParseTable' pre nu fi fo pt = ERROR_GRAMMAR_NOT_LL1_AMB_LA e ==> mkParseTable' (pre @ suf) nu fi fo pt = ERROR_GRAMMAR_NOT_LL1_AMB_LA e" proof (induction suf arbitrary: pre) case Nil thenshow ?caseby auto next case (Cons p suf) have"mkParseTable' (pre @ [p]) nu fi fo pt = mkParseTable' [p] nu fi fo (mkParseTable' pre nu fi fo pt)" by (simp add: mkParseTable'_nested) thenshow ?caseusing Cons.IH[wherepre = "pre @ [p]"] Cons.prems by
(auto simp add: mkParseTable'_nested) qed
lemma all_pre_pt_non_failure: "mkParseTable' (pre @ suf) nu fi fo (PT pt) = PT pt' ==>∃pre_pt'. mkParseTable' pre nu fi fo (PT pt) = PT pre_pt'" by (cases "mkParseTable' pre nu fi fo (PT pt)")
(auto simp add: mkParseTable'_failure_preserved)
lemma mkParseTable'_preserves_soundness: assumes"nullable_set_for nu g""first_map_for fi g""follow_map_for fo g" shows"set ps ⊆ set (prods g) ==> pt_sound pt g ==> mkParseTable' ps nu fi fo (PT pt) = PT pt' ==> pt_sound pt' g" proof (induction ps arbitrary: pt) case Nil show ?caseusing Nil.prems(2,3) by auto next case (Cons p ps) obtain pre_pt' where pre_pt'_def: "mkParseTable' [p] nu fi fo (PT pt) = PT pre_pt'" using all_pre_pt_non_failure[wherepre = "[p]"] Cons.prems(3) by fastforce thenhave"pt_sound pre_pt' g"using assms Cons.prems pre_pt'_defby
(auto intro: addEntries_preserves_soundness) thenshow ?caseusing Cons.IH Cons.prems(1,3) pre_pt'_defby auto qed
lemma initial_pt_sound: "pt_sound fmempty g" unfolding pt_sound_def by simp
theorem mkParseTable_sound: "mkParseTable g = PT pt ==> pt_sound pt g" proof - assume assm: "mkParseTable g = PT pt" let ?nu = "mkNullableSet g" let ?fi = "mkFirstMap g ?nu" let ?fo = "mkFollowMap g ?nu ?fi" have"nullable_set_for ?nu g"by (rule mkNullableSet_correct) moreoverhave"first_map_for ?fi g"using calculation(1) by (rule mkFirstMap_correct) moreoverhave"follow_map_for ?fo g"using calculation(1,2) by - (rule mkFollowMap_correct) ultimatelyshow"pt_sound pt g"by
(metis assm initial_pt_sound mkParseTable'_preserves_soundness mkParseTable_def order_refl) qed
subsection‹Completeness›
lemma la_in_keysForProd: assumes"nullable_set_for nu g""first_map_for fi g""follow_map_for fo g" "lookahead_for la x gamma g" shows"(x, la) ∈ set (keysForProd nu fi fo (x, gamma))" proof (cases "first_gamma g la gamma") case True thenshow ?thesis using assms(1,2) by
(auto intro: first_gamma_firstGamma simp add: firstKeysForProd_def) next case False have"nullableGamma gamma nu"using assms(1,4) False by
(auto intro: nullable_gamma_nullableGamma simp add: lookahead_for_def) moreoverhave"la ∈ set (findOrEmpty x fo)"using assms(3,4) False by
(auto simp add: lookahead_for_def follow_map_complete_def in_findOrEmpty_exists_set) ultimatelyshow ?thesis by (simp add: followKeysForProd_def) qed
lemma addEntries_lookup_same_or_none: "addEntries las xp (PT pt) = PT pt' ==> fmlookup pt k = Some x ==> fmlookup pt' k = Some x" proof (induction las arbitrary: pt pt') case Nil thenshow ?caseby auto next case (Cons k' las) thenshow ?caseby (cases "k' = k") (auto split: option.splits if_splits) qed
lemma mkParseTable'_lookup_same_or_none: "mkParseTable' ps nu fi fo (PT pt) = PT pt' ==> fmlookup pt k = Some x ==> fmlookup pt' k = Some x" proof (induction ps arbitrary: pt pt') case Nil thenshow ?caseby auto next case (Cons p ps) obtain pre_pt' where pre_pt'_def: "mkParseTable' [p] nu fi fo (PT pt) = PT pre_pt'" using Cons.prems(1) all_pre_pt_non_failure[wherepre = "[p]"] by fastforce thenhave"fmlookup pre_pt' k = Some x"by
(simp add: Cons.prems(2) addEntries_lookup_same_or_none) thenshow ?caseusing Cons.IH Cons.prems(1) pre_pt'_defby auto qed
lemma addEntries_in_pt: "k ∈ set las ==> addEntries las xp (PT pt) = PT pt' ==> fmlookup pt' k = Some xp" proof (induction las arbitrary: pt pt') case Nil thenshow ?caseby auto next case (Cons k' las)
consider (is_k) "k = k'" | (in_las) "k ∈ set las"using Cons.prems(1) by auto thenshow ?case proof cases case is_k obtain pre_pt' where pre_pt'_def: "addEntries [k'] xp (PT pt) = PT pre_pt'"using Cons.prems(2) by (auto split: option.splits if_splits) thenhave"fmlookup pre_pt' k' = Some xp"by (auto split: option.splits if_splits) moreoverhave"addEntries las xp (PT pre_pt') = PT pt'"using Cons.prems(2) by
(auto simp add: pre_pt'_def[symmetric] split: option.split) ultimatelyshow ?thesis using addEntries_lookup_same_or_none[where pt = pre_pt'] pre_pt'_def is_k by auto next case in_las thenshow ?thesis using Cons.IH Cons.prems(2) by (auto split: option.splits if_splits) qed qed
lemma mkParseTable'_complete': "nullable_set_for nu g ==> first_map_for fi g ==> follow_map_for fo g ==> prods g = ppre @ psuf ==> (x, gamma) ∈ set psuf ==> lookahead_for la x gamma g ==> mkParseTable' psuf nu fi fo (PT pt) = PT pt' ==> fmlookup pt' (x, la) = Some (x, gamma)" proof (induction psuf arbitrary: ppre pt) case Nil thenshow ?caseby auto next case (Cons p psuf) obtain x' gamma' where"p = (x', gamma')"by fastforce obtain pre_pt' where pre_pt'_def: "mkParseTable' [p] nu fi fo (PT pt) = PT pre_pt'" using Cons.prems(7) all_pre_pt_non_failure[wherepre = "[p]"] by fastforce from Cons.prems(5) consider (in_psuf) "(x, gamma) ∈ set psuf" | (is_p) "p = (x, gamma)"by auto thenshow ?case proof cases case in_psuf thenshow ?thesis using Cons pre_pt'_defby auto next case is_p thenhave"(x, la) ∈ set (keysForProd nu fi fo p)"using Cons.prems(1-3,6) la_in_keysForProd by
fastforce thenhave"fmlookup pre_pt' (x, la) = Some (x, gamma)" using addEntries_in_pt is_p pre_pt'_defby fastforce thenshow ?thesis using Cons.prems(7) mkParseTable'_lookup_same_or_none pre_pt'_defby fastforce qed qed
lemma mkParseTable'_complete: "nullable_set_for nu g ==> first_map_for fi g ==> follow_map_for fo g ==> (x, gamma) ∈ set (prods g) ==> lookahead_for la x gamma g ==> mkParseTable' (prods g) nu fi fo (PT fmempty) = PT pt ==> fmlookup pt (x, la) = Some (x, gamma)" by (auto intro: mkParseTable'_complete'[where ?ppre = "[]"])
theorem mkParseTable_complete: "mkParseTable g = PT pt ==> pt_complete pt g" unfolding pt_complete_def mkParseTable_def by (meson mkFirstMap_correct mkFollowMap_correct mkNullableSet_correct mkParseTable'_complete)
theorem mkParseTable_correct: "mkParseTable g = PT pt ==> parse_table_correct pt g" by (auto simp add: mkParseTable_complete mkParseTable_sound)
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.