Theory Parser
section ‹QDIMACS Parser›
theory Parser
imports PCNF
begin
type_synonym 'a parser = "string ⇒ ('a × string) option"
fun trim_ws :: "string ⇒ string" where
"trim_ws Nil = Nil"
| "trim_ws (Cons x xs) = (if x = CHR '' '' then trim_ws xs else Cons x xs)"
lemma non_increasing_trim_ws [simp]: "length (trim_ws s) ≤ length s"
by (induction s) auto
lemma non_increasing_trim_ws_lemmas [intro]:
shows "length s ≤ length s' ⟹ length (trim_ws s) ≤ length s'"
and "length s < length s' ⟹ length (trim_ws s) < length s'"
and "length s ≤ length (trim_ws s') ⟹ length s ≤ length s'"
and "length s < length (trim_ws s') ⟹ length s < length s'"
apply (induction s)
apply simp_all
subgoal using trim_ws.simps(1) by blast
subgoal using non_increasing_trim_ws order_less_le_trans by blast
done
lemma whitespace_and_parse_le [intro]:
assumes "⋀s s' r. p s = Some (r, s') ⟹ length s' ≤ length s"
shows "⋀s s' r. p (trim_ws s) = Some (r, s') ⟹ length s' ≤ length s" using assms
using le_trans non_increasing_trim_ws by blast
lemma whitespace_and_parse_unit_le [intro]:
assumes "⋀s s'. p s = Some ((), s') ⟹ length s' ≤ length s"
shows "⋀s s'. p (trim_ws s) = Some ((), s') ⟹ length s' ≤ length s" using assms
using le_trans non_increasing_trim_ws by blast
lemma whitespace_and_parse_less [intro]:
assumes "⋀s s' r. p s = Some (r, s') ⟹ length s' < length s"
shows "⋀s s' r. p (trim_ws s) = Some (r, s') ⟹ length s' < length s" using assms
using non_increasing_trim_ws order_less_le_trans by blast
lemma whitespace_and_parse_unit_less [intro]:
assumes "⋀s s'. p s = Some ((), s') ⟹ length s' < length s"
shows "⋀s s'. p (trim_ws s) = Some ((), s') ⟹ length s' < length s" using assms
using non_increasing_trim_ws order_less_le_trans by blast
fun match :: "string ⇒ unit parser" where
"match Nil str = Some ((), str)"
| "match (Cons x xs) Nil = None"
| "match (Cons x xs) (Cons y ys) = (if x ≠ y then None else match xs ys)"
lemma non_increasing_match [simp]: "match xs s = Some ((), s') ⟹ length s' ≤ length s"
apply (induction xs s rule: match.induct)
apply auto[2]
by (metis le_imp_less_Suc length_Cons match.simps(3) option.simps(3) order_less_imp_le)
lemma decreasing_match [simp]:
"xs ≠ [] ⟹ match xs s = Some ((), s') ⟹ length s' < length s"
proof (induction xs s rule: match.induct)
case (3 x xs y ys)
hence "x = y" by (cases "x = y") auto
hence "match (Cons x xs) (Cons y ys) = match xs ys" by simp
hence "match xs ys = Some ((), s')" using 3 by simp
hence "length s' ≤ length ys" by simp
thus "length s' < length (Cons y ys)" by simp
qed auto
fun digit_to_nat :: "char ⇒ nat option" where
"digit_to_nat c = (
if c = CHR ''0'' then Some 0 else
if c = CHR ''1'' then Some 1 else
if c = CHR ''2'' then Some 2 else
if c = CHR ''3'' then Some 3 else
if c = CHR ''4'' then Some 4 else
if c = CHR ''5'' then Some 5 else
if c = CHR ''6'' then Some 6 else
if c = CHR ''7'' then Some 7 else
if c = CHR ''8'' then Some 8 else
if c = CHR ''9'' then Some 9 else
None)"
fun num_aux :: "nat ⇒ nat parser" where
"num_aux n Nil = Some (n, Nil)"
| "num_aux n (Cons x xs) =
(if List.member ''0123456789'' x
then num_aux (10 * n + the (digit_to_nat x)) xs
else Some (n, Cons x xs))"
lemma non_increasing_num_aux [simp]: "num_aux n s = Some (m, s') ⟹ length s' ≤ length s"
apply (induction n s rule: num_aux.induct)
apply simp
by (metis (no_types, lifting) le_imp_less_Suc length_Cons nle_le num_aux.simps(2) option.sel order_less_imp_le prod.sel(2))
fun pnum_raw :: "nat parser" where
"pnum_raw Nil = None"
| "pnum_raw (Cons x xs) = (if List.member ''0123456789'' x then num_aux 0 (Cons x xs) else None)"
lemma decreasing_pnum_raw [simp]: "pnum_raw s = Some (n, s') ⟹ length s' < length s"
apply (cases s)
apply simp
apply (metis impossible_Cons nat_less_le non_increasing_num_aux num_aux.simps(2) option.simps(3) pnum_raw.simps(2))
done
fun pnum :: "nat parser" where
"pnum str = (case pnum_raw str of
None ⇒ None |
Some (n, str') ⇒ if n = 0 then None else Some (n, str'))"
text ‹Simple tests.›
value "pnum ''123''"
value "pnum ''-123''"
value "pnum ''0123''"
value "pnum ''0''"
lemma decreasing_pnum [simp]:
assumes "pnum s = Some (n, s')"
shows "length s' < length s"
proof (cases "pnum_raw s")
case None
hence False using assms by simp
thus ?thesis by simp
next
case (Some a)
obtain n' s'' where "a = (n', s'')" by fastforce
then show ?thesis using Some assms by (cases "n' = 0") auto
qed
fun literal :: "PCNF.literal parser" where
"literal str = (case match ''-'' str of
None ⇒ (case pnum str of
None ⇒ None |
Some (n, str') ⇒ Some (P n, str')) |
Some (_, str') ⇒ (case pnum str' of
None ⇒ None |
Some (n, str'') ⇒ Some (N n, str'')))"
text ‹Simple tests.›
value "literal ''123''"
value "literal ''-123''"
value "literal ''- 123''"
value "literal ''0123''"
value "literal ''0''"
lemma decreasing_literal [simp]:
assumes "literal s = Some (l, s')"
shows "length s' < length s"
proof (cases "match ''-'' s")
case None
thus ?thesis using assms by (cases "pnum s") auto
next
case (Some a)
from this obtain s'' where s''_def: "a = ((), s'')" by (cases "match ''-'' s") auto
hence "length s'' ≤ length s" using Some by simp
moreover have "length s' < length s''" using s''_def assms Some by (cases "pnum s''") auto
ultimately show "length s' < length s" by simp
qed
fun clause :: "PCNF.clause parser" where
"clause str = (case literal (trim_ws str) of
None ⇒ None |
Some (l, str') ⇒
(case clause str' of
None ⇒
(case match ''0'' (trim_ws str') of
None ⇒ None |
Some (_, str'') ⇒
(case match ''⏎'' (trim_ws str'') of
None ⇒ None |
Some (_, str''') ⇒ Some (Cons l Nil, str'''))) |
Some (cl, str'') ⇒ Some (Cons l cl, str'')))"
text ‹Simple tests.›
value "clause ''1 2 -3 4 0 ⏎''"
value "clause ''1 2 -3 4 0 ⏎''"
value "clause ''1 2 -3 40 ⏎''"
value "clause ''1 2 -3 4 0⏎''"
value "clause ''1 2 -3 4 0''"
value "clause '' 1 2 -3 4 0 ⏎''"
lemma decreasing_clause [simp]:
assumes "clause s = Some (c, s')"
shows "length s' < length s" using assms
proof (induction s arbitrary: c rule: clause.induct)
case (1 s)
show ?case
proof (cases "literal (trim_ws s)")
case None
hence False using 1 by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain l s'' where a_def: "a = (l, s'')" by fastforce
hence less1: "length s'' < length s" using Some_a by fastforce
show ?thesis
proof (cases "clause s''")
case None': None
show ?thesis
proof (cases "match ''0'' (trim_ws s'')")
case None
hence False using 1 Some_a a_def None' by simp
thus ?thesis by simp
next
case Some_b: (Some b)
obtain u s''' where b_def: "b = (u, s''')" by (meson surj_pair)
hence le1: "length s''' ≤ length s''" using Some_b by fastforce
show ?thesis
proof (cases "match ''⏎'' (trim_ws s''')")
case None
hence False using 1 Some_a a_def None' Some_b b_def by simp
thus ?thesis by simp
next
case Some_c: (Some c)
obtain u s'''' where c_def: "c = (u, s'''')" by (meson surj_pair)
hence le2: "length s'''' ≤ length s'''" using Some_c by fastforce
have "clause s = Some (Cons l Nil, s'''')"
using Some_a a_def None' Some_b b_def Some_c c_def by simp
hence "s'''' = s'" using 1(2) by simp
thus "length s' < length s" using less1 le1 le2 by simp
qed
qed
next
case Some_b: (Some b)
obtain c' s''' where b_def: "b = (c', s''')" by fastforce
hence "clause s = Some (Cons l c', s''')" using Some_a Some_b a_def by simp
hence "s''' = s'" using 1(2) by simp
hence "clause s'' = Some (c', s')" using Some_b b_def by simp
hence "length s' < length s''" using 1(1) Some_a a_def by blast
thus "length s' < length s" using less1 by simp
qed
qed
qed
fun clause_list :: "PCNF.matrix parser" where
"clause_list str = (case clause str of
None ⇒ None |
Some (cl, str') ⇒
(case clause_list str' of
None ⇒ Some (Cons cl Nil, str') |
Some (cls, str'') ⇒ Some (Cons cl cls, str'')))"
text ‹Simple tests.›
value "clause_list ''1 2 -3 0⏎1 -2 3 0⏎-1 2 3 0⏎''"
value "clause_list ''1 2 -3 ⏎1 -2 3 0⏎-1 2 3 0⏎''"
value "clause_list ''1 2 -3 0 ⏎ 1 -2 3 0⏎-1 2 3 0⏎''"
lemma decreasing_clause_list [simp]:
assumes "clause_list s = Some (cls, s')"
shows "length s' < length s" using assms
proof (induction s arbitrary: cls rule: clause_list.induct)
case (1 s)
show ?case
proof (cases "clause s")
case None
hence False using 1 by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain cl s'' where a_def: "a = (cl, s'')" by fastforce
hence less1: "length s'' < length s" using Some_a by simp
show ?thesis
proof (cases "clause_list s''")
case None
hence "clause_list s = Some (Cons cl Nil, s'')" using Some_a a_def by simp
hence "s' = s''" using 1 by simp
thus "length s' < length s" using less1 by simp
next
case Some_b: (Some b)
obtain cls s''' where b_def: "b = (cls, s''')" by fastforce
hence "clause_list s = Some (Cons cl cls, s''')" using Some_b Some_a a_def by simp
hence "s' = s'''" using 1 by simp
hence "clause_list s'' = Some (cls, s')" using Some_b b_def by simp
hence "length s' < length s''" using 1 Some_a a_def by blast
thus ?thesis using less1 by simp
qed
qed
qed
fun matrix :: "PCNF.matrix parser" where
"matrix s = clause_list s"
text ‹Simple tests.›
value "matrix ''1 2 -3 0⏎1 -2 3 0⏎-1 2 3 0⏎''"
value "matrix ''1 2 -3 ⏎1 -2 3 0⏎-1 2 3 0⏎''"
value "matrix ''1 2 -3 0 ⏎ 1 -2 3 0⏎-1 2 3 0⏎''"
lemma decreasing_matrix [simp]: "matrix s = Some (mat, s') ⟹ length s' < length s" by simp
fun atom_set :: "(nat × nat list) parser" where
"atom_set str = (case pnum (trim_ws str) of
None ⇒ None |
Some (a, str') ⇒
(case atom_set str' of
None ⇒ Some ((a, Nil), str') |
Some ((a', as), str'') ⇒ Some ((a, Cons a' as), str'')))"
text ‹Simple tests.›
value "atom_set ''1 2 3 4''"
value "atom_set ''1 2 -3 4''"
value "atom_set ''1 2 3 4 0 ⏎''"
value "atom_set ''1 2 3 40''"
value "atom_set ''1 2 3 4 0⏎''"
value "atom_set ''1 2 3 4''"
value "atom_set '' 1 2 3 4 0 ⏎ ''"
lemma decreasing_atom_set [simp]:
assumes "atom_set s = Some (as, s')"
shows "length s' < length s" using assms
proof (induction s arbitrary: as rule: atom_set.induct)
case (1 s)
show ?case
proof (cases "pnum (trim_ws s)")
case None
hence False using 1 by simp
thus ?thesis by simp
next
case Some_b: (Some b)
obtain a s'' where b_def: "b = (a, s'')" by fastforce
hence less1: "length s'' < length s" using Some_b by fastforce
show ?thesis
proof (cases "atom_set s''")
case None
hence "atom_set s = Some ((a, Nil), s'')" using Some_b b_def by simp
hence "s' = s''" using 1 by simp
thus "length s' < length s" using less1 by simp
next
case Some_c: (Some c)
obtain a_set s''' where "c = (a_set, s''')" by fastforce
moreover obtain a' as where "a_set = (a', as)" by fastforce
ultimately have c_def: "c = ((a', as), s''')" by simp
hence "atom_set s = Some ((a, Cons a' as), s''')" using Some_c Some_b b_def by simp
hence "s' = s'''" using 1 by simp
hence "atom_set s'' = Some ((a', as), s')" using Some_c c_def by simp
hence "length s' < length s''" using 1 Some_b b_def by blast
thus "length s' < length s" using less1 by simp
qed
qed
qed
datatype quant = Universal | Existential
fun quantifier :: "quant parser" where
"quantifier str = (case match ''e'' str of
None ⇒ (case match ''a'' str of
None ⇒ None |
Some (_, str') ⇒ Some (Universal, str')) |
Some (_, str') ⇒ Some (Existential, str'))"
text ‹Simple tests.›
value "quantifier ''a 1 2 3''"
value "quantifier ''e 1 2 3''"
value "quantifier ''a 1 2 3''"
value "quantifier '' e 1 2 3''"
lemma non_increasing_quant [simp]:
assumes "quantifier s = Some (q, s')"
shows "length s' ≤ length s"
proof (cases "match ''e'' s")
case None_e: None
then show ?thesis
proof (cases "match ''a'' s")
case None
hence False using None_e assms by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain u s'' where a_def: "a = (u, s'')" by (meson surj_pair)
hence "quantifier s = Some (Universal, s'')" using None_e Some_a by simp
hence "s' = s''" using assms by simp
thus "length s' ≤ length s" using Some_a a_def by simp
qed
next
case Some_a: (Some a)
obtain u s'' where a_def: "a = (u, s'')" by (meson surj_pair)
hence "quantifier s = Some (Existential, s'')" using Some_a by simp
hence "s' = s''" using assms by simp
thus "length s' ≤ length s" using Some_a a_def by simp
qed
fun quant_set :: "(quant × (nat × nat list)) parser" where
"quant_set str = (case quantifier (trim_ws str) of
None ⇒ None |
Some (q, str') ⇒
(case atom_set (trim_ws str') of
None ⇒ None |
Some (as, str'') ⇒
(case match ''0'' (trim_ws str'') of
None ⇒ None |
Some (_, str''') ⇒
(case match ''⏎'' (trim_ws str''') of
None ⇒ None |
Some (_, str'''') ⇒ Some ((q, as), str'''')))))"
text ‹Simple tests.›
value "quant_set ''e 1 2 3 0⏎''"
value "quant_set ''a 1 2 3 0⏎''"
value "quant_set ''a 1 2 -3 0⏎''"
lemma decreasing_quant_set [simp]:
assumes "quant_set s = Some (q_set, s')"
shows "length s' < length s"
proof (cases "quantifier (trim_ws s)")
case None
hence False using assms by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain q s'' where a_def: "a = (q, s'')" by fastforce
hence le1: "length s'' ≤ length s" using Some_a by fastforce
show ?thesis
proof (cases "atom_set (trim_ws s'')")
case None
hence False using Some_a a_def assms by simp
thus ?thesis by simp
next
case Some_b: (Some b)
obtain as s''' where b_def: "b = (as, s''')" by fastforce
hence less1: "length s''' < length s''" using Some_b by fastforce
show ?thesis
proof (cases "match ''0'' (trim_ws s''')")
case None
hence False using Some_a a_def Some_b b_def assms by simp
thus ?thesis by simp
next
case Some_c: (Some c)
obtain u s'''' where c_def: "c = (u, s'''')" by (meson surj_pair)
hence le2: "length s'''' ≤ length s'''" using Some_c by fastforce
show ?thesis
proof (cases "match ''⏎'' (trim_ws s'''')")
case None
hence False using Some_a a_def Some_b b_def Some_c c_def assms by simp
thus ?thesis by simp
next
case Some_d: (Some d)
obtain u s''''' where d_def: "d = (u, s''''')" by (meson surj_pair)
hence le3: "length s''''' ≤ length s''''" using Some_d by fastforce
have "quant_set s = Some ((q, as), s''''')"
using Some_a a_def Some_b b_def Some_c c_def Some_d d_def by simp
hence "s' = s'''''" using assms by simp
thus "length s' < length s" using less1 le1 le2 le3 by simp
qed
qed
qed
qed
fun quant_sets :: "(quant × (nat × nat list)) list parser" where
"quant_sets str = (case quant_set str of
None ⇒ None |
Some (q_set, str') ⇒
(case quant_sets str' of
None ⇒ Some (Cons q_set Nil, str') |
Some (q_sets, str'') ⇒ Some (Cons q_set q_sets, str'')))"
text ‹Simple tests.›
value "quant_sets ''a 1 2 3 0⏎e 4 5 6 0⏎a 7 8 9 0 ⏎''"
value "quant_sets ''a 1 2 3 0⏎ e 4 5 6 0 ⏎e 7 8 9 0 ⏎''"
lemma decreasing_quant_sets [simp]:
assumes "quant_sets s = Some (q_sets, s')"
shows "length s' < length s" using assms
proof (induction s arbitrary: q_sets rule: quant_sets.induct)
case (1 s)
show ?case
proof (cases "quant_set s")
case None
hence False using 1 by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain q_set s'' where a_def: "a = (q_set, s'')" by fastforce
hence less1: "length s'' < length s" using Some_a by simp
show ?thesis
proof (cases "quant_sets s''")
case None
hence "quant_sets s = Some (Cons q_set Nil, s'')" using Some_a a_def by simp
hence "s' = s''" using 1 by simp
thus "length s' < length s" using less1 by simp
next
case Some_b: (Some b)
obtain q_sets s''' where b_def: "b = (q_sets, s''')" by fastforce
hence "quant_sets s = Some (Cons q_set q_sets, s''')" using Some_a a_def Some_b by simp
hence "s' = s'''" using 1 by simp
hence "quant_sets s'' = Some (q_sets, s')" using Some_b b_def by simp
hence "length s' < length s''" using 1 Some_a a_def by simp
thus "length s' < length s" using less1 by simp
qed
qed
qed
fun convert_quant_sets :: "(quant × (nat × nat list)) list ⇒ PCNF.prefix option" where
"convert_quant_sets Nil = Some Empty"
| "convert_quant_sets (Cons (Universal, as) qs) =
(case convert_quant_sets qs of
None ⇒ None |
Some Empty ⇒ Some (UniversalFirst as Nil) |
Some (ExistentialFirst as' qs') ⇒ Some (UniversalFirst as (Cons as' qs')) |
Some (UniversalFirst _ _) ⇒ None)"
| "convert_quant_sets (Cons (Existential, as) qs) =
(case convert_quant_sets qs of
None ⇒ None |
Some Empty ⇒ Some (ExistentialFirst as Nil) |
Some (ExistentialFirst _ _) ⇒ None |
Some (UniversalFirst as' qs') ⇒ Some (ExistentialFirst as (Cons as' qs')))"
fun prefix :: "PCNF.prefix parser" where
"prefix str = (case quant_sets str of
None ⇒ Some (Empty, str) |
Some (pre, str') ⇒
(case convert_quant_sets pre of
None ⇒ None |
Some converted ⇒ Some (converted, str')))"
text ‹Simple tests.›
value "prefix ''a 1 2 3 0⏎e 4 5 6 0⏎a 7 8 9 0 ⏎''"
value "prefix ''a 1 2 3 0⏎e 4 5 6 0⏎e 7 8 9 0 ⏎''"
lemma non_increasing_prefix [simp]:
assumes "prefix s = Some (pre, s')"
shows "length s' ≤ length s" using assms
proof (cases "quant_sets s")
case None
hence "prefix s = Some (Empty, s)" by simp
hence "s' = s" using assms by simp
thus "length s' ≤ length s" by simp
next
case (Some a)
obtain pre s'' where a_def: "a = (pre, s'')" by fastforce
hence "s' = s''" using Some assms by (cases "convert_quant_sets pre") auto
moreover have "length s'' < length s" using Some a_def by simp
ultimately show "length s' ≤ length s" by simp
qed
fun problem_line :: "(nat × nat) parser" where
"problem_line str = (case match ''p'' (trim_ws str) of
None ⇒ None |
Some (_, str1) ⇒
(case match ''cnf'' (trim_ws str1) of
None ⇒ None |
Some (_, str2) ⇒
(case pnum (trim_ws str2) of
None ⇒ None |
Some (lits, str3) ⇒
(case pnum (trim_ws str3) of
None ⇒ None |
Some (clauses, str4) ⇒
(case match ''⏎'' (trim_ws str4) of
None ⇒ None |
Some (_, str5) ⇒ Some ((lits, clauses), str5))))))"
text ‹Simple tests.›
value "problem_line ''p cnf 123 321⏎''"
value "problem_line ''p cnf 123 321⏎''"
value "problem_line ''p cnf 123 -321⏎''"
value "problem_line '' p cnf 123 321⏎''"
lemma decreasing_problem_line [simp]:
assumes "problem_line s = Some (res, s')"
shows "length s' < length s"
proof (cases "match ''p'' (trim_ws s)")
case None
hence False using assms by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain u s1 where a_def: "a = (u, s1)" by (meson surj_pair)
hence le1: "length s1 ≤ length s" using Some_a by fastforce
show ?thesis
proof (cases "match ''cnf'' (trim_ws s1)")
case None
hence False using Some_a a_def assms by simp
thus ?thesis by simp
next
case Some_b: (Some b)
obtain u s2 where b_def: "b = (u, s2)" by (meson surj_pair)
hence le2: "length s2 ≤ length s1" using Some_b by fastforce
show ?thesis
proof (cases "pnum (trim_ws s2)")
case None
hence False using Some_a a_def Some_b b_def assms by simp
thus ?thesis by simp
next
case Some_c: (Some c)
obtain lits s3 where c_def: "c = (lits, s3)" by fastforce
hence less1: "length s3 < length s2" using Some_c by fastforce
show ?thesis
proof (cases "pnum (trim_ws s3)")
case None
hence False using Some_a a_def Some_b b_def Some_c c_def assms by simp
thus ?thesis by simp
next
case Some_d: (Some d)
obtain clauses s4 where d_def: "d = (clauses, s4)" by fastforce
hence less2: "length s4 < length s3" using Some_d by fastforce
show ?thesis
proof (cases "match ''⏎'' (trim_ws s4)")
case None
hence False using Some_a a_def Some_b b_def Some_c c_def Some_d d_def assms by simp
thus ?thesis by simp
next
case Some_e: (Some e)
obtain u s5 where e_def: "e = (u, s5)" by (meson surj_pair)
hence "problem_line s = Some ((lits, clauses), s5)"
using Some_a a_def Some_b b_def Some_c c_def Some_d d_def Some_e by simp
hence "s' = s5" using assms by simp
hence "match ''⏎'' (trim_ws s4) = Some (u, s')" using Some_e e_def by simp
hence "length s' ≤ length s4" by fastforce
thus "length s' < length s" using le1 le2 less1 less2 by simp
qed
qed
qed
qed
qed
fun consume_text :: "unit parser" where
"consume_text Nil = Some ((), Nil)" |
"consume_text (Cons x xs) = (if x = CHR ''⏎'' then Some ((), Cons x xs) else consume_text xs)"
lemma non_increasing_consume_text [simp]: "consume_text s = Some ((), s') ⟹ length s' ≤ length s"
apply (induction s rule: consume_text.induct)
apply simp
by (metis (mono_tags, lifting) consume_text.simps(2) le_imp_less_Suc length_Cons nle_le option.sel order_less_imp_le prod.sel(2))
:: "unit parser" where
"comment_line str = (case match ''c'' (trim_ws str) of
None ⇒ None |
Some (_, str') ⇒
(case consume_text str' of
None ⇒ None |
Some (_, str'') ⇒
(case match ''⏎'' str'' of
None ⇒ None |
Some (_, str''') ⇒ Some ((), str'''))))"
text ‹Simple tests.›
value "comment_line ''c e 1 2 3⏎e 1 2 3''"
value "comment_line ''e 1 2 3⏎e 1 2 3''"
value "comment_line '' c e 1 2 3 ⏎e 1 2 3''"
lemma [simp]:
assumes "comment_line s = Some ((), s')"
shows "length s' < length s"
proof (cases "match ''c'' (trim_ws s)")
case None
hence False using assms by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain u s1 where a_def: "a = (u, s1)" by (meson surj_pair)
hence less1: "length s1 < length s"
using Some_a decreasing_match[of "''c''" "trim_ws s" s1] by fastforce
show ?thesis
proof (cases "consume_text s1")
case None
hence False using Some_a a_def assms by simp
thus ?thesis by simp
next
case Some_b: (Some b)
obtain u s2 where b_def: "b = (u, s2)" by (meson surj_pair)
hence le1: "length s2 ≤ length s1" using Some_b by simp
show ?thesis
proof (cases "match ''⏎'' s2")
case None
hence False using Some_a a_def Some_b b_def assms by simp
thus ?thesis by simp
next
case Some_c: (Some c)
obtain u s3 where c_def: "c = (u, s3)" by (meson surj_pair)
hence "comment_line s = Some (u, s3)" using Some_a a_def Some_b b_def Some_c by simp
hence "s3 = s'" using assms by simp
hence "match ''⏎'' s2 = Some (u, s')" using Some_c c_def by simp
hence "length s' ≤ length s2" by simp
thus "length s' < length s" using less1 le1 by simp
qed
qed
qed
:: "unit parser" where
"comment_lines str = (case comment_line str of
None ⇒ None |
Some (_, str') ⇒
(case comment_lines str' of
None ⇒ Some ((), str') |
Some (_, str'') ⇒ Some ((), str'')))"
text ‹Simple tests.›
value "comment_lines ''c a comment⏎c another comment⏎''"
value "comment_lines ''c a comment⏎ c another comment⏎''"
lemma [simp]:
assumes "comment_lines s = Some ((), s')"
shows "length s' < length s" using assms
proof (induction s rule: comment_lines.induct)
case (1 s)
show ?case
proof (cases "comment_line s")
case None
hence False using 1 by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain u s1 where a_def: "a = (u, s1)" by (meson surj_pair)
hence less1: "length s1 < length s" using Some_a by simp
show ?thesis
proof (cases "comment_lines s1")
case None
hence "comment_lines s = Some ((), s1)" using Some_a a_def by simp
hence "s1 = s'" using 1 by simp
thus "length s' < length s" using less1 by simp
next
case Some_b: (Some b)
obtain u s2 where b_def: "b = (u, s2)" by (meson surj_pair)
hence "comment_lines s = Some ((), s2)" using Some_a a_def Some_b by simp
hence "s2 = s'" using 1 by simp
hence "comment_lines s1 = Some ((), s')" using Some_a a_def Some_b b_def by simp
hence "length s' < length s1" using 1 Some_a a_def by blast
thus "length s' < length s" using less1 by simp
qed
qed
qed
fun preamble :: "(nat × nat) parser" where
"preamble str = (case comment_lines str of
None ⇒ problem_line str |
Some (_, str') ⇒ problem_line str')"
text ‹Simple tests.›
value "preamble ''c an example⏎p cnf 4 5⏎''"
value "preamble '' c an example⏎ p cnf 4 5⏎''"
lemma decreasing_preamble [simp]:
assumes "preamble s = Some (p, s')"
shows "length s' < length s"
proof (cases "comment_lines s")
case None
hence "preamble s = problem_line s" by simp
thus ?thesis using assms by simp
next
case (Some a)
obtain p s'' where a_def: "a = (p, s'')" by (meson surj_pair)
hence "preamble s = problem_line s''" using Some by simp
hence "length s' < length s''" using assms by simp
moreover have "length s'' < length s" using Some a_def by simp
ultimately show "length s' < length s" by simp
qed
fun eof :: "unit parser" where
"eof Nil = Some ((), Nil)"
| "eof (Cons x xs) = None"
lemma eof_nil [simp]: "eof s = Some ((), s') ⟹ s' = Nil"
by (cases s) auto
fun input :: "PCNF.pcnf parser" where
"input str = (case preamble str of
None ⇒ None |
Some ((lits, clauses), str') ⇒
(case prefix str' of
None ⇒ None |
Some (pre, str'') ⇒
(case matrix str'' of
None ⇒ None |
Some (mat, str''') ⇒
(case eof str''' of
None ⇒ None |
Some (_, str'''') ⇒ Some ((pre, mat), str'''')))))"
text ‹Simple tests.›
value "input
''c an example from the QDIMACS specification
c multiple
c lines
cwith
c comments
p cnf 4 2
e 1 2 3 4 0
-1 2 0
2 -3 -4 0
''"
value "input
''c an extension of the example from the QDIMACS specification
c multiple
c lines
cwith
c comments
p cnf 40 4
e 1 2 3 4 0
a 11 12 13 14 0
e 21 22 23 24 0
-1 2 0
2 -3 -4 0
40 -13 -24 0
12 -23 -24 0
''"
lemma input_nil [simp]:
assumes "input s = Some (p, s')"
shows "s' = Nil" using assms
proof (cases "preamble s")
case None
hence False using assms by simp
thus ?thesis by simp
next
case Some_a: (Some a)
obtain p s1 where a_def: "a = (p, s1)" by (meson surj_pair)
show ?thesis
proof (cases "prefix s1")
case None
hence False using Some_a a_def assms by simp
thus ?thesis by simp
next
case Some_b: (Some b)
obtain pre s2 where b_def: "b = (pre, s2)" by fastforce
show ?thesis
proof (cases "matrix s2")
case None
hence False using Some_a a_def Some_b b_def assms by simp
thus ?thesis by simp
next
case Some_c: (Some c)
obtain mat s3 where c_def: "c = (mat, s3)" by fastforce
show ?thesis
proof (cases "eof s3")
case None
hence False using Some_a a_def Some_b b_def Some_c c_def assms by simp
thus ?thesis by simp
next
case Some_d: (Some d)
obtain u s4 where d_def: "d = (u, s4)" by (meson surj_pair)
hence "input s = Some ((pre, mat), s4)"
using Some_a a_def Some_b b_def Some_c c_def Some_d d_def by simp
hence "s4 = s'" using assms by simp
moreover have "s4 = Nil" using Some_d d_def by simp
ultimately show "s' = Nil" by simp
qed
qed
qed
qed
fun parse :: "String.literal ⇒ pcnf option" where
"parse str = map_option fst (input (String.explode str))"
text ‹Simple tests.›
value "parse (String.implode
''c an example from the QDIMACS specification
c multiple
c lines
cwith
c comments
p cnf 4 2
e 1 2 3 4 0
-1 2 0
2 -3 -4 0
'')"
value "parse (String.implode
''c an extension of the example from the QDIMACS specification
c multiple
c lines
cwith
c comments
p cnf 40 4
e 1 2 3 4 0
a 11 12 13 14 0
e 21 22 23 24 0
-1 2 0
2 -3 -4 0
40 -13 -24 0
12 -23 -24 0
'')"
end