Theory PathLemmas

theory PathLemmas
imports TheoremD14
begin

context LocalLexing begin

lemma characterize_𝒫:
  "( i < length p. u. p ! i  𝒵 (charslength (take i p)) u)  admissible p 
   u. p  𝒫 (charslength p) u"
proof (induct p rule: rev_induct)
  case Nil
    show ?case by simp
next
  case (snoc a p)
    from snoc.prems have admissible_p: "admissible p"
      by (metis append_Nil2 is_prefix_admissible is_prefix_cancel is_prefix_empty) 
    {
      fix i :: nat
      assume ilen: "i < length p"
      then have "i < length (p@[a])"
        by (simp add: Suc_leI Suc_le_lessD trans_le_add1) 
      with snoc have "u. (p @ [a]) ! i  𝒵 (charslength (take i (p @ [a]))) u"
        by blast
      then obtain u where u: "(p @ [a]) ! i  𝒵 (charslength (take i (p @ [a]))) u" by blast
      from ilen have p_at: "(p @ [a]) ! i = p ! i" by (simp add: nth_append)  
      from ilen have p_take: "take i (p @ [a]) = take i p" by (simp add: less_or_eq_imp_le) 
      from u p_at p_take have p_i: "p ! i  𝒵 (charslength (take i p)) u" by simp 
      then have " u. p ! i  𝒵 (charslength (take i p)) u" by blast
    }
    then have " i < length p. u. p ! i  𝒵 (charslength (take i p)) u" by auto
    with admissible_p snoc.hyps obtain u where u: "p  𝒫 (charslength p) u" by blast
    have "u. (p @ [a]) ! (length p)  𝒵 (charslength (take (length p) (p @ [a]))) u"
      using snoc
      by (metis (no_types, opaque_lifting) add_Suc_right append_Nil2 length_Cons length_append 
        less_Suc_eq_le less_or_eq_imp_le) 
    then obtain v where "(p @ [a]) ! (length p)  𝒵 (charslength (take (length p) (p @ [a]))) v"
      by blast
    then have v: "a  𝒵 (charslength p) v" by simp
    {
      assume v_leq_u: "v  u"
      then have "a  𝒵 (charslength p) (Suc u)" using v
        by (meson LocalLexing.subset_fSuc LocalLexing_axioms 𝒵_subset_Suc subsetCE) 
      from path_append_token[OF u this snoc.prems(2)] 
      have "p @ [a]  𝒫 (charslength p) (Suc u)" by blast
      then have ?case using in_𝒫_charslength by blast 
    }
    note case_v_leq_u = this
    {
      assume u_less_v: "u < v"
      then obtain w where w: "v = Suc w" using less_imp_Suc_add by blast 
      with u_less_v have "u  w" by arith
      with u have "p  𝒫 (charslength p) w" by (meson subsetCE subset_𝒫k) 
      from v w path_append_token[OF this _ snoc.prems(2)] 
      have "p @ [a]  𝒫 (charslength p) (Suc w)" by blast
      then have ?case using in_𝒫_charslength by blast 
    }
    note case_u_less_v = this
    
    show ?case using case_v_leq_u case_u_less_v not_le by blast 
qed

lemma drop_empty_tokens: 
  assumes p: "p  𝔓"
  assumes r: "r  length p"
  assumes empty: "charslength (take r p) = 0"
  assumes admissible: "admissible (drop r p)"
  shows "drop r p  𝔓"
proof -
  have p_𝒵: "i<length p. u. p ! i  𝒵 (charslength (take i p)) u" using p
    using tokens_nth_in_𝒵 by blast 
  obtain q where q: "q = drop r p" by blast
  {
    fix j :: nat
    assume j : "j < length q"
    have length_p_q_r: "length p = length q + r"
      using r q add.commute diff_add_inverse le_Suc_ex length_drop by simp
    have j_plus_r_bound: "j + r < length p" by (simp add: j length_p_q_r) 
    with p_𝒵 have "u. p ! (j + r)  𝒵 (charslength (take (j + r) p)) u" by blast
    then obtain u where u: "p ! (j + r)  𝒵 (charslength (take (j + r) p)) u" by blast
    have p_at_is_q_at: "p ! (j + r) = q ! j" by (simp add: add.commute q r) 
    have "take (j + r) p = (take r p) @ (take j q)" by (metis add.commute q take_add)
    with empty have "charslength (take (j + r) p) = charslength (take j q)" by auto
    with u p_at_is_q_at have "q ! j  𝒵 (charslength (take j q)) u" by simp
    then have " u. q ! j  𝒵 (charslength (take j q)) u" by auto
  }
  then have "i<length q. u. q ! i  𝒵 (charslength (take i q)) u" by blast
  from characterize_𝒫[OF this] have "u. q  𝒫 (charslength q) u" using admissible q by auto
  then show ?thesis using 𝔓_covers_𝒫 q by blast 
qed
  
end

end