definition mismatchMessage :: "'t ==> 't × 's ==> string"where "mismatchMessage a ≡ λ(a', s). ''Token mismatch. Expected '' @ showT a @ '', saw '' @ showT a' @ '' ('' @ showS s @ '')''"
function (domintros) parseSymbol :: "('n, 't) parse_table ==> ('n, 't) symbol ==> ('t × 's) list ==> 'n fset ==> ('n, 't, 's) return_type" and
parseGamma :: "('n, 't) parse_table ==> 'n ==> ('n, 't) symbol list ==> ('t × 's) list ==> 'n fset ==> ('n, 't, 's) return_type" where "parseSymbol _ (T a) [] _ = REJECT ''input exhausted'' []"
| "parseSymbol pt (T a) (t#ts) vis = (if fst t = a then RESULT (Leaf t) ts else REJECT (mismatchMessage a t) (t#ts))"
| "parseSymbol pt (NT x) ts vis = (if x |∈| vis then ERROR ''left recursion detected'' x ts else (case fmlookup pt (x, peek ts) of None ==> REJECT ''lookup failure'' ts | Some (x', gamma) ==> (if x ≠ x' then ERROR ''malformed parse table'' x ts else parseGamma pt x gamma ts (finsert x vis)) ))"
| "parseGamma pt n [] ts vis = RESULT (Node n []) ts"
| "parseGamma pt n (s#gamma') ts vis = (let parse_s = parseSymbol pt s ts vis in (case parse_s of RESULT t r ==> (let parse_g = parseGamma pt n gamma' r (if length r < length ts then {||} else vis) in (case parse_g of RESULT (Node n tls) r' ==> RESULT (Node n (t # tls)) r' | e ==> e)) | e ==> e))" proof (goal_cases) case (1 P x) show ?case proof (cases x) case (Inl a) thenshow ?thesis proof (cases a) case (fields t u v w) thenshow ?thesis using"1" Inl by (cases u; cases v) auto qed next case (Inr b) thenshow ?thesis proof (cases b) case (fields t u v w) thenshow ?thesis using"1" Inr by (cases v) auto qed qed qed auto
definition parse_ind_meas_sym :: "('n, 't) parse_table ==> ('n, 't) symbol ==> ('t × 's) list ==> 'n fset ==> nat× nat × nat"where "parse_ind_meas_sym pt s ts vis = (length ts, fcard (nt_from_pt pt |-| vis), 0)"
definition parse_ind_meas_sym_list :: "('n, 't) parse_table ==> ('n, 't) symbol list ==> ('t × 's) list ==> 'n fset ==> nat × nat × nat" where "parse_ind_meas_sym_list pt ss ts vis = (length ts, fcard (nt_from_pt pt |-| vis), length ss + 1)"
definition parse_ind_meas :: "('n, 't) parse_table ==> ('n, 't) symbol + ('n, 't) symbol list ==> ('t × 's) list ==> 'n fset ==> nat × nat × nat"where "parse_ind_meas pt ss ts vis = (length ts, fcard (nt_from_pt pt |-| vis), (case ss of Inl ss' ==> 0 | Inr ss' ==> length ss' + 1))"
definition lex_triple :: "('a × 'a) set ==> ('b × 'b) set ==> ('c × 'c) set ==> (('a × 'b × 'c) × ('a × 'b × 'c)) set" where"lex_triple ra rb rc = ra <*lex*> (rb <*lex*> rc)"
lemma in_lex_triple[simp]: "((a, b, c), (a', b', c')) ∈ lex_triple r s t ⟷ (a, a') ∈ r ∨ a = a' ∧ (b, b') ∈ s ∨ a = a' ∧ b = b' ∧ (c, c') ∈ t" by (auto simp:lex_triple_def)
lemma wf_lex_triple[intro!]: assumes"wf ra""wf rb""wf rc" shows"wf (lex_triple ra rb rc)" by (simp add: assms parse.lex_triple_def wf_lex_prod)
lemma parseSymbol_length_bound_partial: "parseSymbol_parseGamma_dom (Inl (pt, s, ts, vis)) ==> (∧tr r. parseSymbol pt s ts vis = RESULT tr r ==> length r ≤ length ts)"and
parseGamma_length_bound_partial: "parseSymbol_parseGamma_dom (Inr (pt, n, gamma, ts, vis)) ==> (∧tr r. parseGamma pt n gamma ts vis = RESULT tr r ==> length r ≤ length ts)" proof (induction rule: parseSymbol_parseGamma.pinduct) case (1 pt a vis) thenshow ?case by (simp add: parseSymbol.psimps(1)) next case (2 pt a t ts vis) thenshow ?case by (simp add: parseSymbol.psimps(2) split: if_splits) next case (3 pt x ts vis) thenshow ?caseby (auto simp add: parseSymbol.psimps(3) split: if_splits option.splits) next case (4 pt n ts vis) thenshow ?caseby (auto simp add: parseGamma.psimps(1)) next case (5 pt n s gamma' ts vis) thenshow ?case by (fastforce simp add: parseGamma.psimps(2) split: return_type.splits parse_tree.splits) qed
lemma fcard_diff_insert_less: assumes"x |∉| vis""fmlookup pt (x,peek ts) = Some (x,ss)" shows"fcard (nt_from_pt pt - (finsert x vis)) < fcard (nt_from_pt pt - vis)" proof - from assms(2) have"x |∈| nt_from_pt pt"by (metis fimage_eqI fmdomI fst_conv nt_from_pt_def) thenhave"x |∈| nt_from_pt pt - vis"using assms(1) by simp thenshow ?thesis by (metis fcard_fminus1_less fminus_finsert) qed
termination proof (relation "mlex_triple (λx. case x of Inl (pt, s, ts, vis) ==> parse_ind_meas_sym pt s ts vis | Inr (pt, n, ss, ts, vis) ==> parse_ind_meas_sym_list pt ss ts vis)", goal_cases) case1 thenshow ?caseby (simp add: mlex_triple_def wf_lex_triple) next case (2 pt x ts vis s x' gamma) have"fcard (nt_from_pt pt - (finsert x vis)) < fcard (nt_from_pt pt - vis)" using"2" fcard_diff_insert_less by fastforce thenshow ?caseunfolding mlex_triple_def parse_ind_meas_sym_list_def parse_ind_meas_sym_def by
auto next case (3 pt s gamma' ts vis) thenshow ?caseunfolding mlex_triple_def parse_ind_meas_sym_list_def parse_ind_meas_sym_def by
auto next case (4 pt s gamma' ts vis y z str r) thenshow ?caseunfolding mlex_triple_def parse_ind_meas_sym_list_def parse_ind_meas_sym_def by (fastforce dest: parseSymbol_length_bound_partial) qed
fun parse :: "('n, 't) ll1_parse_table ==> ('n, 't) symbol ==> ('t × 's) list ==> ('n, 't, 's) return_type" where "parse (PT pt) s ts = parseSymbol pt s ts {||}"
| "parse (ERROR_GRAMMAR_NOT_LL1_AMB_LA l) s ts = (case l of (a, p1, p) ==> GRAMMAR_NOT_LL1 ''Grammar not LL1, ambigous lookahead '' a)"
fun concatWithSep :: "string ==> string ==> string"where "concatWithSep [] [] = []"
| "concatWithSep [] acc = acc"
| "concatWithSep s [] = s"
| "concatWithSep s (c # acc) = (if c = CHR '' '' then s @ c # acc else s @ '' '' @ c # acc)"
fun parseTreeToString :: "('n, 't × 's) parse_tree ==> string"where "parseTreeToString (Leaf (a, s)) = ''('' @ showT a @ '', '' @ showS s @ '')''"
| "parseTreeToString (Node n ls) = foldr concatWithSep (map parseTreeToString ls) ''''"
fun parseToString :: "('n, 't) ll1_parse_table ==> ('n, 't) symbol ==> ('t × 's) list ==> string"where "parseToString (PT pt) s ts = (case parseSymbol pt s ts {||} of RESULT t [] ==> parseTreeToString t)"
| "parseToString (ERROR_GRAMMAR_NOT_LL1_AMB_LA l) s ts = ''Grammar not LL1, ambigous lookahead '' @ (case l of (a, p1, p) ==> (case a of LA t ==> showT t | EOF ==> ''EOF''))"
subsection‹Soundness›
inductive sym_derives_prefix :: "('n, 't) grammar ==> ('n, 't) symbol ==> ('t × 's) list ==> ('n, 't × 's) parse_tree ==> ('t × 's) list ==> bool" and gamma_derives_prefix :: "('n, 't) grammar ==> 'n ==> ('n, 't) symbol list ==> ('t × 's) list ==> ('n, 't × 's) parse_tree ==> ('t × 's) list ==> bool"for g where
T_sdp: "sym_derives_prefix g (T a) [(a, s)] (Leaf (a, s)) r"
| NT_sdp: "(x, gamma) ∈ set (prods g) ==> lookahead_for (peek (w @ r)) x gamma g ==> gamma_derives_prefix g x gamma w t r ==> sym_derives_prefix g (NT x) w t r"
| Nil_gdp: "gamma_derives_prefix g x [] [] (Node x []) r"
| Cons_gdp: "sym_derives_prefix g s wpre v (wsuf @ r) ==> gamma_derives_prefix g n ss wsuf (Node n vs) r ==> gamma_derives_prefix g n (s#ss) (wpre @ wsuf) (Node n (v # vs)) r"
lemma parseSymbol_ts_contains_remainder: "∧t r. parseSymbol pt s ts vis = RESULT t r ==>∃ts'. ts' @ r = ts"and
parseGamma_ts_contains_remainder: "∧t r. parseGamma pt n gamma ts vis = RESULT t r ==>∃ts'. ts' @ r = ts" proof (induction pt s ts vis and pt n gamma ts vis rule: parseSymbol_parseGamma.induct) case (5 pt n s gamma' ts vis) thenshow ?caseby (fastforce split: return_type.splits parse_tree.splits option.splits if_splits) qed (auto split: return_type.splits parse_tree.splits option.splits if_splits)
lemma parse_meas_induct: assumes"∧y. (∧x. ((x,y) ∈ mlex_triple (λx. case x of Inl (pt, s, ts, vis) ==> parse_ind_meas_sym pt s ts vis | Inr (pt, x, ss, ts, vis) ==> parse_ind_meas_sym_list pt ss ts vis) ==> P x)) ==> P y" shows"P z" using assms by (auto intro: wf_induct_rule[where r = "mlex_triple (λx. case x of Inl (pt, s, ts, vis) ==> parse_ind_meas_sym pt s ts vis | Inr (pt, x, ss, ts, vis) ==> parse_ind_meas_sym_list pt ss ts vis)"]
simp add: mlex_triple_def wf_lex_triple)
lemma parseGamma_node: "parseSymbol pt s ts vis = RESULT v r ==> True" "parseGamma pt x gamma ts vis = RESULT v r ==>∃ls. v = Node x ls" proof (induction pt s ts vis and pt x gamma ts vis arbitrary: and v r
rule: parseSymbol_parseGamma.induct) case (5 pt n s' gamma' ts vis) obtain a b where A: "parseSymbol pt s' ts vis = RESULT a b" using5(2,3) by (auto split: return_type.splits parse_tree.splits if_splits) show ?case proof (cases gamma') case Nil thenhave"parseGamma pt n gamma' b (if length b < length ts then {||} else vis) = RESULT (Node n []) b" by auto thenshow ?thesis using5(3) A by (auto split: return_type.splits parse_tree.splits) next case (Cons x'' gamma'') obtain ls where"v = Node n ls"using5(2,3) A by
(auto split: return_type.splits parse_tree.splits) thenshow ?thesis by auto qed qed auto
lemma parseSymbol_parseGamma_sound: "case x of Inl (pt, s, ts, vis) ==> parse_table_correct pt g ⟶ parseSymbol pt s ts vis = RESULT v r ⟶ (∃w. w @ r = ts ∧ sym_derives_prefix g s w v r) | Inr (pt, n, gamma, ts, vis) ==> parse_table_correct pt g ⟶ (parseGamma pt n gamma ts vis = RESULT v r ⟶ (∃w. w @ r = ts ∧ gamma_derives_prefix g n gamma w v r))" proof (induction arbitrary: v r rule: parse_meas_induct) case (1 y) note IH = "1"
{ fix pt s ts vis assume A: "y = Inl (pt, s, ts, vis)""parse_table_correct pt g" "parseSymbol pt s ts vis = RESULT v r"
consider (T) a lex ts' where"s = T a""ts = (a,lex)#ts'""v = Leaf (a, lex)""r = ts'"
| (NT) x ss where"s = NT x""x |∉| vis""fmlookup pt (x, peek ts) = Some (x, ss)" "parseSymbol pt s ts vis = parseGamma pt x ss ts (finsert x vis)" using A(3) by (cases s; cases ts) (auto split: if_splits option.splits) thenhave"∃w. w @ r = ts ∧ sym_derives_prefix g s w v r" proof cases case T thenshow ?thesis by (auto simp add: T_sdp) next case NT thenhave"(Inr (pt, x, ss, ts, (finsert x vis)), y) ∈ mlex_triple (λx. case x of Inl (pt, s, ts, vis) ==> parse_ind_meas_sym pt s ts vis | Inr (pt, x, ss, ts, vis) ==> parse_ind_meas_sym_list pt ss ts vis)" unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def using A(1) fcard_diff_insert_less by simp thenobtain w where" w @ r = ts""gamma_derives_prefix g x ss w v r" using IH[of "Inr (pt, x, ss, ts, (finsert x vis))"] A NT by auto thenshow ?thesis using A(2) NT(1,3) NT_sdp pt_sound_def by fastforce qed
} note1 = this
{ fix pt x ss ts vis assume A: "y = Inr (pt, x, ss, ts, vis)""parse_table_correct pt g" "parseGamma pt x ss ts vis = RESULT v r"
consider (Nil) "ss = []"
| (ConsLe) s ss' t tls r1 where"ss = s#ss'" "parseSymbol pt s ts vis = RESULT t r1""length r1 < length ts" "parseGamma pt x ss' r1 {||} = RESULT (Node x tls) r""v = Node x (t # tls)"
| (ConsEq) s ss' t tls where"ss = s#ss'""parseSymbol pt s ts vis = RESULT t ts" "parseGamma pt x ss' ts vis = RESULT (Node x tls) r""v = Node x (t # tls)" proof (cases ss) case Nil thenshow ?thesis by (simp add: that(1)) next case (Cons s ss') thenshow ?thesis using parseSymbol_ts_contains_remainder parseGamma_node(2) A(3) by (fastforce simp: ConsLe ConsEq split: return_type.splits if_splits) qed thenhave"∃w. w @ r = ts ∧ gamma_derives_prefix g x ss w v r" proof (cases) case Nil thenshow ?thesis using A(3) Nil_gdp by auto next case ConsLe obtain wpre wsuf where"ts = wpre @ wsuf @ r""wsuf @ r = r1" using parseGamma_ts_contains_remainder A(3) parseSymbol_ts_contains_remainder ConsLe(2,4) by metis thenhave"gamma_derives_prefix g x ss' wsuf (Node x tls) r" using IH[of "Inr (pt, x, ss', r1, {||})"] A(1,2) ConsLe(3,4) unfolding mlex_triple_def parse_ind_meas_sym_list_def by (auto simp add: A(1)) moreoverhave"sym_derives_prefix g s wpre t (wsuf @ r)" using IH[of "Inl (pt, s, ts, vis)"] ‹ts = wpre @ wsuf @ r›‹wsuf @ r = r1› A ConsLe(2) unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp add: A(1)) ultimatelyshow ?thesis by (simp add: ConsLe(1,5) Cons_gdp ‹ts = wpre @ wsuf @ r›) next case ConsEq obtain w where"ts = w @ r"using ConsEq(3) parseGamma_ts_contains_remainder by
fastforce have"length ss' < length ss"by (cases w) (auto simp add: ‹ts = w @ r› ConsEq(1)) thenhave"gamma_derives_prefix g x ss' w (Node x tls) r" using IH[of "Inr (pt, x, ss', ts, vis)"] A(1,2) ConsEq(3) unfolding mlex_triple_def parse_ind_meas_sym_list_def by (auto simp add: A(1) ‹ts = w @ r›) moreoverhave"sym_derives_prefix g s [] t ts" using IH[of "Inl (pt, s, ts, vis)"] ‹ts = w @ r› A ConsEq(2) unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp add: A(1)) ultimatelyshow ?thesis using ConsEq(1,4) Cons_gdp ‹ts = w @ r›by fastforce qed
} note2 = this thenshow ?caseusing12by (cases y) (auto split: prod.splits) qed
theorem parse_sound: "parse_table_correct pt g ==> parse (PT pt) s (w @ r) = RESULT v r ==> sym_derives_prefix g s w v r" using parseSymbol_parseGamma_sound[where x = "Inl (pt, s, (w @ r), {||})"] by auto
subsection"Completeness"
lemma parseSymbol_parseGamma_complete_or_error: assumes"parse_table_correct pt g" shows"sym_derives_prefix g s w v r ==> (∀vis. (∃m x ts'. parseSymbol pt s (w @ r) vis = ERROR m x ts') ∨ (parseSymbol pt s (w @ r) vis = RESULT v r))" and"gamma_derives_prefix g y ss w v r ==> (∀vis. (∃m x ts'. parseGamma pt y ss (w @ r) vis = ERROR m x ts') ∨ (parseGamma pt y ss (w @ r) vis = RESULT v r))" proof (induction rule: sym_derives_prefix_gamma_derives_prefix.inducts) case (T_sdp a r) thenshow ?caseby auto next case (NT_sdp x gamma w r v) have"fmlookup pt (x,peek (w @ r)) = Some (x, gamma)" using NT_sdp.IH(1) NT_sdp.IH(2) assms pt_complete_def by fastforce thenhave"(∃m y ts'. parseSymbol pt (NT x) (w @ r) vis = ERROR m y ts') ∨ parseSymbol pt (NT x) (w @ r) vis = RESULT v r"for vis proof (cases "x |∈| vis") case True thenshow ?thesis by simp next case False thenhave"parseSymbol pt (NT x) (w @ r) vis = parseGamma pt x gamma (w @ r) (finsert x vis)" using‹fmlookup pt (x, peek (w @ r)) = Some (x, gamma)›by auto thenshow ?thesis using NT_sdp.IH(4) by auto qed thenshow ?caseby auto next case (Nil_gdp r) thenshow ?caseby auto next case (Cons_gdp s wpre v wsuf r n ss vs) thenhave"(∃m x ts'. parseGamma pt n (s # ss) ((wpre @ wsuf) @ r) vis = ERROR m x ts') ∨ parseGamma pt n (s # ss) ((wpre @ wsuf) @ r) vis = RESULT (Node n (v # vs)) r"for vis proof - have"∃m x ts'. parseSymbol pt s (wpre @ wsuf @ r) vis = ERROR m x ts' ∨ parseSymbol pt s (wpre @ wsuf @ r) vis = RESULT v (wsuf @ r)"using Cons_gdp.IH(2) by auto moreoverhave"∃m x ts'. parseGamma pt n ss (wsuf @ r) vis = ERROR m x ts' ∨ parseGamma pt n ss (wsuf @ r) vis = RESULT (Node n vs) r"using Cons_gdp(4) by auto moreoverhave"∃m x ts'. parseGamma pt n ss (wsuf @ r) {||} = ERROR m x ts' ∨ parseGamma pt n ss (wsuf @ r) {||} = RESULT (Node n vs) r"using Cons_gdp(4) by auto ultimatelyshow ?thesis by (cases "parseSymbol pt s (wpre @ wsuf @ r) vis") auto qed thenshow ?caseby auto qed
lemma parse_complete_or_error: "parse_table_correct pt g ==> sym_derives_prefix g s w v r ==>∃m x ts'. parse (PT pt) s (w @ r) = ERROR m x ts' ∨ (parse (PT pt) s (w @ r) = RESULT v r)" using parseSymbol_parseGamma_complete_or_error by fastforce
subsection‹Error-free Termination›
inductive sized_first_sym :: "('n, 't) grammar ==> 't lookahead ==> ('n, 't) symbol==> nat ==> bool" for g where
SzFirstT: "sized_first_sym g (LA y) (T y) 0"
| SzFirstNT: "(x, gpre @ s # gsuf) ∈ set (prods g) ==> nullable_gamma g gpre ==> sized_first_sym g la s n ==> sized_first_sym g la (NT x) (Suc n)"
lemma first_sym_exists_size: "first_sym g la s ==>∃n. sized_first_sym g la s n" using SzFirstT SzFirstNT by -(induction rule: first_sym.induct; fastforce)
lemma sized_fs_fs: "sized_first_sym g la s n ==> first_sym g la s" by (induction rule: sized_first_sym.induct) (auto simp add: FirstT FirstNT)
lemma medial : "pre @ s # suf = pre' @ s' # suf' ==> s ∈ set pre'∨ s' ∈ set pre ∨ pre = pre' ∧ s = s' ∧ suf = suf'" proof (inductionpre arbitrary: pre') case Nil thenshow ?caseby (cases pre') auto next case (Cons a pre) thenshow ?caseby (cases pre') auto qed
lemma nullable_sym_in: "nullable_gamma g gamma ==> s ∈ set gamma ==> nullable_sym g s" proof (induction gamma) case (Cons s' gamma) have"nullable_gamma g gamma"using Cons.prems(1) by (cases rule: nullable_gamma.cases) moreoverhave"nullable_sym g s'"using Cons.prems(1) by (cases rule: nullable_gamma.cases) ultimatelyshow ?caseusing Cons.IH Cons.prems(2) by (cases "s = s'") auto qed simp
lemma nullable_split: "nullable_gamma g (xs @ ys) ==> nullable_gamma g ys" proof (induction xs arbitrary: ys) case Nil thenshow ?caseby auto next case (Cons s xs) from Cons.prems have"nullable_gamma g (xs @ ys)"by (cases rule: nullable_gamma.cases) auto thenshow ?caseusing Cons.IH by auto qed
lemma first_gamma_split: "first_gamma g la ys ==> nullable_gamma g xs ==> first_gamma g la (xs @ ys)" proof (induction xs) case Nil thenshow ?caseby auto next case (Cons s xs) from Cons.prems(2) have"nullable_gamma g xs"by (cases) auto thenhave"first_gamma g la (xs @ ys)"using Cons.IH Cons.prems(1) by auto thenobtain xs' s' ys' where"first_sym g la s'""nullable_gamma g xs'""xs @ ys = xs' @ s' # ys'" by (cases rule: first_gamma.cases) auto have"nullable_sym g s"using Cons.prems(2) by (cases) auto thenhave"nullable_gamma g (s # xs')"by (simp add: NullableCons ‹nullable_gamma g xs'›) thenshow ?caseusing FirstGamma[where gpre = "s # xs'"and s = s' and gsuf = "ys'"] by
(simp add: ‹first_sym g la s'›‹xs @ ys = xs' @ s' # ys'›) qed
lemma follow_pre: "(x, pre @ suf) ∈ set (prods g) ==> s ∈ set pre ==> nullable_gamma g pre ==> first_gamma g la suf ==> follow_sym g la s" proof goal_cases case1 thenobtain l1 l2 where l1_l2_def: "pre = l1 @ s # l2"by (metis split_list) thenshow ?case proof (cases s) case (NT x) have"nullable_gamma g (l1 @ NT x # l2)"using"1"(3) by (auto simp add: l1_l2_def NT) thenhave"nullable_gamma g l2"using nullable_split[where xs = "l1 @ [NT x]"] by auto thenhave"first_gamma g la (l2 @ suf)"by (simp add: "1"(4) first_gamma_split) thenshow ?thesis using FollowRight[where gsuf = "l2 @ suf"] NT "1"(1) l1_l2_def by auto next case (T t) thenshow ?thesis using"1"(2,3) nullable_sym.cases nullable_sym_in by blast qed qed
lemma no_first_follow_conflicts: assumes"parse_table_correct tbl g" shows"first_sym g la s ==> nullable_sym g s ==>¬ follow_sym g la s" unfolding not_def proof (intro impI, induction rule: first_sym.induct) case (FirstT y) thenshow ?caseby (cases rule: nullable_sym.cases) next case (FirstNT x gpre s gsuf la) from FirstNT.prems(1) obtain ys where ys_props: "(x, ys) ∈ set (prods g)""nullable_gamma g ys"by
cases auto have ys_eq: "ys = gpre @ s # gsuf" proof - have"lookahead_for la x (gpre @ s # gsuf) g" by (simp add: FirstGamma FirstNT.hyps(2,3) lookahead_for_def) moreoverhave"lookahead_for la x ys g" by (simp add: FirstNT.prems(2) ys_props(2) lookahead_for_def) ultimatelyshow ?thesis using assms by
(metis FirstNT.hyps(1) Pair_inject ys_props(1) option.inject pt_complete_def) qed have"nullable_sym g s"using ys_props(2) ys_eq nullable_sym_in by fastforce thenshow ?case proof (cases s) case (NT x) have"nullable_gamma g gsuf"using nullable_split[where xs = "gpre @ [s]"] ys_props(2) ys_eq by
auto thenhave"follow_sym g la s"using FirstNT.hyps(1) FirstNT.prems(2) FollowLeft NT by fastforce thenshow ?thesis using FirstNT.IH ‹nullable_sym g s›by auto next case (T t) show ?thesis using‹nullable_sym g s› T by (cases rule: nullable_sym.cases) auto qed qed
lemma first_sym_rhs_eqs: "parse_table_correct t g ==> (x, pre @ s # suf) ∈ set (prods g) ==> (x, pre' @ s' # suf') ∈ set (prods g) ==> nullable_gamma g pre ==> nullable_gamma g pre' ==> first_sym g la s ==> first_sym g la s' ==> pre = pre' ∧ s = s' ∧ suf = suf'" proof (goal_cases) case1 have"pre @ s # suf = pre' @ s' # suf'" proof - have"lookahead_for la x (pre @ s # suf) g"by (simp add: "1"(4,6) FirstGamma lookahead_for_def) moreoverhave"lookahead_for la x (pre' @ s' # suf') g"by
(simp add: "1"(5,7) FirstGamma lookahead_for_def) ultimatelyshow ?thesis using"1"(1-3) unfolding pt_complete_def by (metis Pair_inject option.inject) qed then consider (s_in_pre') "s ∈ set pre'" | (s'_in_pre) "s' ∈ set pre"
| (eq) "pre = pre' ∧ s = s' ∧ suf = suf'"using medial by fastforce thenshow ?case proof cases case s_in_pre' thenhave"nullable_sym g s"using"1"(5) using nullable_sym_in by auto moreoverhave"follow_sym g la s" proof - have"first_gamma g la (s' # suf')"using"1"(7) FirstGamma[of _ "[]" _ s'] NullableNil by
auto thenshow ?thesis using"1"(3,5) s_in_pre' follow_pre[where suf = "s' # suf'"] by auto qed ultimatelyshow ?thesis using"1"(1,6) no_first_follow_conflicts by auto next case s'_in_pre thenhave"nullable_sym g s'"using"1"(4) using nullable_sym_in by auto moreoverhave"follow_sym g la s'" proof - have"first_gamma g la (s # suf)"using"1"(6) FirstGamma[of _ "[]" _ s] NullableNil by auto thenshow ?thesis using"1"(2,4) s'_in_pre follow_pre[where suf = "s # suf"] by auto qed ultimatelyshow ?thesis using"1"(1,7) no_first_follow_conflicts by auto next case eq thenshow ?thesis by blast qed qed
lemma sized_first_sym_det: assumes"parse_table_correct t g" shows"sized_first_sym g la s n ==> (∀n'. s = s' ⟶ sized_first_sym g la s' n' ⟶ n = n')" proof (induction arbitrary: s' rule: sized_first_sym.inducts) case (SzFirstT g y) thenshow ?caseby (auto, cases rule: sized_first_sym.cases) auto next case (SzFirstNT x pre s suf la n) have"s' = NT x ⟶ sized_first_sym g la s' n' ⟶ Suc n = n'"for n' proof (intro impI, goal_cases) case1 obtain gpre gsuf s0 n0 where s0_props: "(x, gpre @ s0 # gsuf) ∈ set (prods g)" "nullable_gamma g gpre""sized_first_sym g la s0 n0""n' = Suc n0" using1(1) by (cases rule: sized_first_sym.cases[OF 1(2)]) auto thenhave"first_sym g la s""first_sym g la s0"using SzFirstNT.hyps(3) sized_fs_fs byauto thenhave"s = s0"using first_sym_rhs_eqs SzFirstNT.hyps s0_props assms by fastforce thenhave"n = n0"using SzFirstNT.IH ‹sized_first_sym g la s0 n0›by auto thenshow ?caseusing‹n' = Suc n0›by auto qed thenshow ?caseby auto qed
lemma sized_first_sym_np: "nullable_path g la x y ==> first_sym g la y ==>∃nx ny. sized_first_sym g la x nx ∧ sized_first_sym g la y ny ∧ ny < nx" proof (induction rule: nullable_path.induct) case (DirectPath x gamma g gpre z gsuf la) thenobtain n where"sized_first_sym g la (NT z) n"using first_sym_exists_size by blast thenhave"sized_first_sym g la (NT x) (Suc n)"using DirectPath.hyps by (simp add: SzFirstNT) thenshow ?caseusing‹sized_first_sym g la (NT z) n›by blast next case (IndirectPath x gamma g gpre y gsuf la z) thenobtain nx ny where nx_ny_ex: "sized_first_sym g la (NT y) nx ∧ sized_first_sym g la (NT z) ny ∧ ny < nx"by auto thenhave"sized_first_sym g la (NT x) (Suc nx)"using IndirectPath.hyps by (simp add: SzFirstNT) thenshow ?caseusing nx_ny_ex less_SucI by blast qed
inductive sized_nullable_sym :: "('n, 't) grammar ==> ('n, 't) symbol ==> nat ==> bool" and sized_nullable_gamma :: "('n, 't) grammar ==> ('n, 't) symbol list ==> nat ==>bool"for g where
SzNullableSym: "(x, gamma) ∈ set (prods g) ==> sized_nullable_gamma g gamma n ==> sized_nullable_sym g (NT x) (Suc n)"
| SzNullableNil: "sized_nullable_gamma g [] 0"
| SzNullableCons: "sized_nullable_sym g s n ==> sized_nullable_gamma g ss n' ==> sized_nullable_gamma g (s # ss) (n + n')"
lemma sized_ng_ng: "sized_nullable_sym g s n ==> nullable_sym g s" "sized_nullable_gamma g gamma n ==> nullable_gamma g gamma" by (induction rule: sized_nullable_sym_sized_nullable_gamma.inducts)
(auto simp add: NullableSym NullableNil NullableCons)
lemma ng_sized_ng: "nullable_sym g s ==>∃n. sized_nullable_sym g s n" "nullable_gamma g gamma ==>∃n. sized_nullable_gamma g gamma n" using SzNullableSym SzNullableNil SzNullableCons by (induction rule: nullable_sym_nullable_gamma.inducts) fastforce+
lemma sized_nullable_sym_det': assumes"parse_table_correct pt g" shows"sized_nullable_sym g s n ==> (∧n'. follow_sym g la s ==> sized_nullable_sym g s n' ==> n = n')" and"sized_nullable_gamma g gsuf n ==> (∧x gpre n'. (x, gpre @ gsuf) ∈ set (prods g) ==> follow_sym g la (NT x) ==> sized_nullable_gamma g gsuf n' ==> n = n')" proof (induction rule: sized_nullable_sym_sized_nullable_gamma.inducts) case (SzNullableSym x gamma n) from SzNullableSym.prems(2) obtain n0 gamma0 where"(x, gamma0) ∈ set (prods g)" "sized_nullable_gamma g gamma0 n0""n' = Suc n0"by (cases) auto have"gamma0 = gamma" proof - have"lookahead_for la x gamma0 g"unfolding lookahead_for_def using sized_ng_ng SzNullableSym.prems(1) ‹sized_nullable_gamma g gamma0 n0›by blast thenhave lookup_1: "fmlookup pt (x, la) = Some (x, gamma0)" using assms ‹(x, gamma0) ∈ set (prods g)›by (auto simp add: pt_complete_def) have"lookahead_for la x gamma g"unfolding lookahead_for_def using sized_ng_ng SzNullableSym.prems(1) SzNullableSym.IH(2) by blast thenhave lookup_2: "fmlookup pt (x, la) = Some (x, gamma)"using assms SzNullableSym.IH(1) by (auto simp add: pt_complete_def) show ?thesis using lookup_1 lookup_2 by auto qed thenhave"n0 = n" using‹sized_nullable_gamma g gamma0 n0› SzNullableSym.IH(3)[of _ "[]"] SzNullableSym.IH(1)
SzNullableSym.prems(1) by auto thenshow ?caseby (simp add: ‹n' = Suc n0›) next case SzNullableNil thenshow ?caseby (cases rule: parse.sized_nullable_gamma.cases) auto next case (SzNullableCons s n1 ss n2 x) from SzNullableCons.prems(3) obtain n1' n2' where "sized_nullable_sym g s n1'""sized_nullable_gamma g ss n2'""n' = n1' + n2'"by (cases) auto have"follow_sym g la s" proof (cases s) case (NT x1) have"nullable_gamma g ss"using sized_ng_ng SzNullableCons.IH(3) by fastforce thenshow ?thesis using FollowLeft NT SzNullableCons.prems(1,2) by fastforce next case (T x2) from‹sized_nullable_sym g s n1›show ?thesis using T by (cases) auto qed thenhave"n1 = n1'"using SzNullableCons.IH(2)[of n1'] ‹sized_nullable_sym g s n1'›by auto moreoverhave"n2 = n2'" using SzNullableCons.IH(4)[of x "gpre @ [s]" n2'] ‹sized_nullable_gamma g ss n2'› by (simp add: SzNullableCons.prems(1,2)) ultimatelyshow ?caseusing‹n' = n1' + n2'›by auto qed
lemma sized_nullable_sym_det: assumes"parse_table_correct t g" shows"sized_nullable_sym g s n ==> follow_sym g la s ==> sized_nullable_sym g s n' ==> n = n'" using sized_nullable_sym_det' assms by blast
lemma sym_in_gamma_size_le: "nullable_gamma g gamma ==> s ∈ set gamma ==>∃n n'. sized_nullable_sym g s n ∧ sized_nullable_gamma g gamma n' ∧ n ≤ n'" proof (induction gamma) case Nil thenshow ?caseby auto next case (Cons a gamma) from Cons.prems(1) have nullable: "nullable_sym g a""nullable_gamma g gamma"by
(cases rule: nullable_gamma.cases, auto)+ thenshow ?case proof (cases "a = s") case True thenshow ?thesis using SzNullableCons nullable ng_sized_ng by fastforce next case False thenshow ?thesis using Cons.IH Cons.prems(2) SzNullableCons nullable ng_sized_ng(1) by
fastforce qed qed
lemma sized_ns_np: assumes"(x, pre @ NT y # suf) ∈ set (prods g)""nullable_gamma g (pre @ NT y # suf)" "nullable_sym g (NT y)" shows"∃nx ny. sized_nullable_sym g (NT x) nx ∧ sized_nullable_sym g (NT y) ny ∧ny < nx" proof - obtain n n' where "sized_nullable_sym g (NT y) n""sized_nullable_gamma g (pre @ NT y # suf) n'""n ≤ n'" using sym_in_gamma_size_le[of g "pre @ NT y # suf""NT y"] assms(2) by auto thenhave"sized_nullable_sym g (NT x) (Suc n')" using SzNullableSym[where gamma = "pre @ NT y # suf"] assms(1) by auto thenshow ?thesis using‹n ≤ n'›‹sized_nullable_sym g (NT y) n› le_imp_less_Suc by blast qed
lemma exist_decreasing_nullable_sym_sizes_in_null_path: shows"nullable_path g la x y ==> parse_table_correct t g ==> nullable_sym g x ==> follow_sym g la x ==>∃nx ny. sized_nullable_sym g x nx ∧ sized_nullable_sym g y ny ∧ ny < nx" proof (induction rule: nullable_path.induct) case (DirectPath x gamma g pre y suf la) from DirectPath.prems(2) obtain ys where"(x, ys) ∈ set (prods g)""nullable_gamma g ys"by
(cases rule: nullable_sym.cases) auto from DirectPath.hyps(4) consider (fst_gamma) "first_gamma g la gamma"
| (null_gamma) "nullable_gamma g gamma""follow_sym g la (NT x)" unfolding lookahead_for_def by auto thenshow ?case proof cases case fst_gamma thenhave"first_sym g la (NT x)"using DirectPath.hyps(1) FirstNT by cases auto thenhave"¬ follow_sym g la (NT x)"using DirectPath.prems(1,2) by
(auto simp add: no_first_follow_conflicts) thenshow ?thesis using DirectPath.prems(3) by auto next case null_gamma have"nullable_sym g (NT y)"using DirectPath.hyps(2) null_gamma(1) nullable_sym_in byfastforce thenshow ?thesis using DirectPath.hyps(1,2) null_gamma(1) parse.sized_ns_np by fastforce qed next case (IndirectPath x gamma g gpre y gsuf la z) from IndirectPath.hyps(4) consider (fst_gamma) "first_gamma g la gamma"
| (null_gamma) "nullable_gamma g gamma""follow_sym g la (NT x)" unfolding lookahead_for_def by auto thenshow ?case proof cases case fst_gamma thenhave"first_sym g la (NT x)"using IndirectPath.hyps(1) FirstNT by cases auto thenhave"¬ follow_sym g la (NT x)"using IndirectPath.prems(1,2) by
(auto simp add: no_first_follow_conflicts) thenshow ?thesis using IndirectPath.prems(3) by auto next case null_gamma have"nullable_sym g (NT y)"using IndirectPath.hyps(2) null_gamma(1) nullable_sym_in by
fastforce have"nullable_gamma g gsuf" using null_gamma(1) IndirectPath.hyps(2) nullable_split[where xs = "gpre @ [NT y]"] by auto thenhave"follow_sym g la (NT y)"using null_gamma IndirectPath.hyps(1,2) by
(auto simp add: FollowLeft) thenobtain ny nz where "sized_nullable_sym g (NT y) ny""sized_nullable_sym g (NT z) nz""nz < ny" using IndirectPath.IH IndirectPath.prems(1) ‹nullable_sym g (NT y)›by auto obtain nx ny' where "sized_nullable_sym g (NT x) nx""sized_nullable_sym g (NT y) ny'""ny' < nx" using IndirectPath.hyps(1,2) null_gamma(1) sized_ns_np ‹nullable_sym g (NT y)›by fastforce thenhave"ny = ny'"using IndirectPath.prems(1) ‹follow_sym g la (NT y)› ‹sized_nullable_sym g (NT y) ny› sized_nullable_sym_det by blast thenhave"nz < nx"using‹ny' < nx›‹nz < ny›by auto thenshow ?thesis using‹sized_nullable_sym g (NT x) nx›‹sized_nullable_sym g (NT z) nz›by
auto qed qed
lemma nullable_path_exists_production: "nullable_path g la (NT x) y ==>∃gamma. (x, gamma) ∈ set (prods g) ∧ lookahead_for la x gamma g" by (cases rule: nullable_path.cases) auto
lemma ll1_parse_table_impl_no_left_recursion: assumes"parse_table_correct tbl (g :: ('n, 't) grammar)" shows"¬ left_recursive g (NT x) la" proof assume x_left_rec: "left_recursive g (NT x) la" thenobtain gamma where"(x, gamma) ∈ set (prods g)""lookahead_for la x gamma g" using nullable_path_exists_production by fastforce then consider "first_gamma g la gamma" | "nullable_gamma g gamma""follow_sym g la (NT x)" by (auto simp: lookahead_for_def) thenshow"False" proof (cases) case1 thenhave"first_sym g la (NT x)"using FirstNT ‹(x, gamma) ∈ set (prods g)›by (cases) auto thenobtain nx ny where"sized_first_sym g la (NT x) nx""sized_first_sym g la (NT x) ny" "ny < nx"using sized_first_sym_np x_left_rec by blast thenhave"ny = nx"using assms sized_first_sym_det by fastforce thenshow ?thesis using‹ny < nx›by auto next case2 thenhave"nullable_sym g (NT x)"using‹(x, gamma) ∈ set (prods g)›by
(auto simp add: NullableSym) thenobtain n n' where"sized_nullable_sym g (NT x) n""sized_nullable_sym g (NT x) n'""n' < n" using"2"(2) x_left_rec assms exist_decreasing_nullable_sym_sizes_in_null_path by blast thenshow ?thesis using"2"(2) assms sized_nullable_sym_det by blast qed qed
lemma input_length_lt_or_nullable_sym: "case x of Inl (pt, s, ts, vis) ==> parse_table_correct pt g ⟶ parseSymbol pt s ts vis = RESULT v r ⟶ length r < length ts ∨ nullable_sym g s | Inr (pt, x, ss, ts, vis) ==> parse_table_correct pt g ⟶ parseGamma pt x ss ts vis = RESULT v r ⟶ length r < length ts ∨ nullable_gamma g ss" proof (induction arbitrary: v r rule: parse_meas_induct) case (1 y) note IH = 1 thenshow ?case proof (cases y) case (Inl a) thenobtain pt s ts vis where"a = (pt, s, ts, vis)"by (cases y) auto have"length r < length ts ∨ nullable_sym g s" if"parseSymbol pt s ts vis = RESULT v r"and"parse_table_correct pt g" proof (cases s) case (NT x) from that obtain ss where parse_ss_simp: "x |∉| vis""fmlookup pt (x, peek ts) = Some (x, ss)" "parseGamma pt x ss ts (finsert x vis) = RESULT v r" by (auto simp: NT split: if_splits option.splits) thenhave"(x, ss) ∈ set (prods g)"using that(2) by (auto simp add: pt_sound_def) have"fcard (nt_from_pt pt |-| finsert x vis) < fcard (nt_from_pt pt |-| vis)" using fcard_diff_insert_less parse_ss_simp(1,2) by fastforce thenhave"length r < length ts ∨ nullable_gamma g ss" using IH[of "Inr (pt, x, ss, ts, finsert x vis)"] parse_ss_simp(3) unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp: Inl ‹a = (pt, s, ts, vis)› that(2)) thenshow ?thesis using NT NullableSym ‹(x, ss) ∈ set (prods g)›by force next case (T t) from that obtain s where"ts = (t, s) # r" by (cases ts, auto simp: T split: if_splits option.splits) thenshow ?thesis by simp qed thenshow ?thesis by (simp add: Inl ‹a = (pt, s, ts, vis)›) next case (Inr a) thenobtain pt x ss ts vis where"a = (pt, x, ss, ts, vis)"by (cases y) auto have"length r < length ts ∨ nullable_gamma g ss"if "parseGamma pt x ss ts vis = RESULT v r""parse_table_correct pt g" proof (cases ss) case Nil thenshow ?thesis by (simp add: NullableNil) next case (Cons s ss') from that(1) consider v0 v1 where"parseSymbol pt s ts vis = RESULT v0 ts" "parseGamma pt x ss' ts vis = RESULT (Node x v1) r""v = Node x (v0 # v1)"
| v0 v1 r0 where"parseSymbol pt s ts vis = RESULT v0 r0""length r0 < length ts" "parseGamma pt x ss' r0 {||} = RESULT (Node x v1) r""v = Node x (v0 # v1)" using parseSymbol_ts_contains_remainder[of pt s ts vis] Cons parseGamma_node(2)[of pt x ss'] by (fastforce split: return_type.splits parse_tree.splits if_splits) thenshow ?thesis proof cases case1 thenhave"length ts < length ts ∨ nullable_sym g s" using IH[of "Inl (pt, s, ts, vis)"] that(2) unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp add: Inr ‹a = (pt, x, ss, ts, vis)›) moreoverhave"length r < length ts ∨ nullable_gamma g ss'" using IH[of "Inr (pt, x, ss', ts, vis)"] that(2) 1 unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp add: Inr ‹a = (pt, x, ss, ts, vis)› Cons) ultimatelyshow ?thesis using NullableCons Cons by blast next case2 have"length r ≤ length r0"using parseGamma_ts_contains_remainder "2"(3) by fastforce thenshow ?thesis using"2"(2) by auto qed qed thenshow ?thesis by (simp add: Inr ‹a = (pt, x, ss, ts, vis)›) qed qed
lemma input_length_eq_nullable_sym: "parse_table_correct tbl g ==> parseSymbol tbl s ts vis = RESULT v ts ==> nullable_sym g s" using input_length_lt_or_nullable_sym[where x = "Inl (tbl, s, ts, vis)"] by auto
lemma error_conditions: "case y of Inl (pt, s, ts, vis) ==> parse_table_correct pt g ⟶ parseSymbol pt s ts vis = ERROR m z ts' ⟶ ((z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z))) ∨ (∃la. left_recursive g (NT z) la)) | Inr (pt, x, ss, ts, vis) ==> parse_table_correct pt g ⟶ parseGamma pt x ss ts vis = ERROR m z ts' ⟶ (∃pre s suf. ss = pre @ s # suf ∧ nullable_gamma g pre ∧ z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z))) ∨ (∃la. (left_recursive g (NT z) la))" proof (induction arbitrary: m z ts' rule: parse_meas_induct) case (1 y) note IH = "1" thenshow ?case proof (cases y) case (Inl a) thenobtain pt s ts vis where"a = (pt, s, ts, vis)"using prod_cases4 by blast thenshow ?thesis proof (cases s) case (NT x)
consider (x_in_vis) "x |∈| vis" | (lookup_none) "fmlookup pt (x, peek ts) = None"
| (lookup_some_neq) x' ss' where"x |∉| vis""x ≠ x'" "fmlookup pt (x, peek ts) = Some (x',ss')"
| (lookup_some_eq )ss' where"x |∉| vis""fmlookup pt (x, peek ts) = Some (x, ss')" by fastforce thenshow ?thesis proof (cases) case lookup_some_eq thenhave"fcard (nt_from_pt pt |-| finsert x vis) < fcard (nt_from_pt pt |-| vis)" using fcard_diff_insert_less[of x] by auto thenhave IH': "parse_table_correct pt g ==> parseGamma pt x ss' ts (finsert x vis) = ERROR m z ts' ==> ((∃pre s suf. ss' = pre @ s # suf ∧ nullable_gamma g pre ∧ z |∈| (finsert x vis) ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z))) ∨ (∃la. left_recursive g (NT z) la))" using IH[of "Inr (pt, x, ss', ts, (finsert x vis))" m z ts'] unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp add: Inl ‹a = (pt, s, ts, vis)›) have"parse_table_correct pt g ==> parseSymbol pt s ts vis = ERROR m z ts' ==> z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z)) ∨ (∃la. left_recursive g (NT z) la)" proof - assume assms: "parse_table_correct pt g""parseSymbol pt s ts vis = ERROR m z ts'" have"parseGamma pt x ss' ts (finsert x vis) = ERROR m z ts'" using assms(2) lookup_some_eq NT by auto then consider pre s' suf where"ss' = pre @ s' # suf""nullable_gamma g pre" "z |∈| (finsert x vis)""s' = NT z ∨ nullable_path g (peek ts) s' (NT z)"
| la where"left_recursive g (NT z) la"using IH' assms(1,2) by auto thenshow"z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z)) ∨ (∃la. left_recursive g (NT z) la)" proof (cases) case1 have"fmlookup pt (x,(peek ts)) = Some (x, pre @ s' # suf)" using"1"(1) lookup_some_eq(2) by blast thenhave x_la: "(x, pre @ s' # suf) ∈ set (prods g)" "lookahead_for (peek ts) x (pre @ s' # suf) g"using‹parse_table_correct pt g› by (simp_all add: pt_sound_def)
consider (s'_is_ntz) "s' = NT z" | (null_path) "nullable_path g (peek ts) s' (NT z)" using"1"(4) by auto thenshow ?thesis proof (cases) case s'_is_ntz thenshow ?thesis using"1"(2-4) DirectPath NT x_la by fastforce next case null_path thenobtain n n' where"s' = NT n""NT x = NT n'"by cases auto thenshow ?thesis using"1"(2,3) IndirectPath null_path x_la NT by fastforce qed next case2 thenshow ?thesis by blast qed qed thenshow ?thesis by (simp add: Inl ‹a = (pt, s, ts, vis)›) qed (auto simp add: Inl NT ‹a = (pt, s, ts, vis)› pt_sound_def) next case (T _) thenshow ?thesis using Inl T ‹a = (pt, s, ts, vis)›by (cases ts) auto qed next case (Inr a) thenobtain pt x ss ts vis where"a = (pt, x, ss, ts, vis)"using prod_cases5 by blast have"parse_table_correct pt g ==> parseGamma pt x ss ts vis = ERROR m z ts' ==> (∃pre s. (∃suf. ss = pre @ s # suf) ∧ nullable_gamma g pre ∧ z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z))) ∨ (∃la. left_recursive g (NT z) la)" proof - assume assms: "parse_table_correct pt g""parseGamma pt x ss ts vis = ERROR m z ts'" thenobtain s ss' where"ss = s # ss'"by (auto elim: parseGamma.elims) then consider (parse_s_error) "parseSymbol pt s ts vis = ERROR m z ts'"
| (parse_ss'_error_le) str r where"parseSymbol pt s ts vis = RESULT str r" "length r < length ts""parseGamma pt x ss' r {||} = ERROR m z ts'"
| (parse_ss'_error_eq) str where"parseSymbol pt s ts vis = RESULT str ts" "parseGamma pt x ss' ts vis = ERROR m z ts'" using assms(2) parseSymbol_ts_contains_remainder by (fastforce split: return_type.splits if_splits parse_tree.splits) thenshow"(∃pre s. (∃suf. ss = pre @ s # suf) ∧ nullable_gamma g pre ∧ z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z))) ∨ (∃la. left_recursive g (NT z) la)" proof cases case parse_s_error have"parse_table_correct pt g ⟶ parseSymbol pt s ts vis = ERROR m z ts' ⟶ z |∈| vis ∧ (s = NT z ∨ nullable_path g (peek ts) s (NT z)) ∨ (∃la. left_recursive g (NT z) la)" using IH[of "Inl (pt, s, ts, vis)" m z ts'] assms unfolding mlex_triple_def parse_ind_meas_sym_def parse_ind_meas_sym_list_def by (auto simp add: Inr ‹a = (pt, x, ss, ts, vis)›) thenshow ?thesis using NullableNil ‹ss = s # ss'› assms(1) parse_s_error by blast next case parse_ss'_error_le thenhave"(parse_ind_meas_sym_list pt ss' r {||}, parse_ind_meas_sym_list pt ss ts vis) ∈ lex_triple less_than less_than less_than" unfolding parse_ind_meas_sym_def parse_ind_meas_sym_list_def using‹ss = s # ss'› parse_ss'_error_le(2) by auto thenshow ?thesis using IH[of "Inr (pt, x, ss', r, {||})" m z] assms parse_ss'_error_le(3) by (auto simp add: mlex_triple_def Inr ‹a = (pt, x, ss, ts, vis)›) next case parse_ss'_error_eq have"(parse_ind_meas_sym_list pt ss' ts vis, parse_ind_meas_sym_list pt ss ts vis) ∈ lex_triple less_than less_than less_than" unfolding parse_ind_meas_sym_def parse_ind_meas_sym_list_def using‹ss = s # ss'›by auto then consider pre s0 suf where"ss' = pre @ s0 # suf""nullable_gamma g pre""z |∈| vis" "(s0 = NT z ∨ nullable_path g (peek ts) s0 (NT z))"
| la where"left_recursive g (NT z) la" using IH[of "Inr (pt, x, ss', ts, vis)" m z ts'] assms parseSymbol_ts_contains_remainder by (auto simp add: mlex_triple_def Inr ‹a = (pt, x, ss, ts, vis)› parse_ss'_error_eq(2)) thenshow ?thesis proof cases case1 have"nullable_sym g s" using input_length_eq_nullable_sym assms(1) parse_ss'_error_eq(1) by fastforce thenhave"nullable_gamma g (s # pre)"by (simp add: "1"(2) NullableCons) thenshow ?thesis by (metis "1"(1,3,4) Cons_eq_appendI ‹ss = s # ss'›) next case2 thenshow ?thesis by auto qed qed qed thenshow ?thesis by (simp add: Inr ‹a = (pt, x, ss, ts, vis)›) qed qed
theorem parse_terminates_without_error: "parse_table_correct pt g ==> parse (PT pt) s (w @ r) ≠ ERROR m x ts'" proof assume A: "parse_table_correct pt g""parse (PT pt) s (w @ r) = ERROR m x ts'" thenhave"¬ (∃la. left_recursive g (NT x) la)"using ll1_parse_table_impl_no_left_recursion using‹parse_table_correct pt g›by fastforce thenhave"(x |∈| {||} ∧ (s = NT x ∨ nullable_path g (peek (w @ r)) s (NT x)))" using error_conditions[of g m x ts' "Inl (pt, s, (w @ r), {||})"] A by auto thenshow"False"by auto qed
theorem parse_complete: "parse_table_correct pt g ==> sym_derives_prefix g s w v r ==> parse (PT pt) s (w @ r) = RESULT v r" using parse_terminates_without_error parse_complete_or_error by fastforce
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.