Definition next_ptd (ptd:pt_dot): option pt_dot :=
  match ptd with
    | Shift_ptd term sem ptl ptlz =>
      Some (build_pt_dot ptl (Cons_ptl_ptlz (Terminal_pt term sem) ptlz))
    | Reduce_ptd ptlz =>
      let 'existT _ _ (existT _ _ (ptz, pt)) := pop_ptlz Nil_ptl ptlz in
      match ptz in pt_zipper sym _ _ return parse_tree sym _ _ -> _ with
        | Top_ptz => fun pt => None
        | Cons_ptl_ptz ptl ptlz' =>
          fun pt => Some (build_pt_dot ptl (Cons_ptl_ptlz pt ptlz'))
      end pt
  end.

(* Specifications: *)
Lemma next_ptd_cost: forall ptd, match next_ptd ptd with | None => ptd_cost ptd = 0 | Some ptd' => ptd_cost ptd = S (ptd_cost ptd') end.
Lemma step_next_ptd: forall (ptd:pt_dot) (stack:stack), ptd_stack_compat ptd stack -> match step init stack (ptd_buffer ptd) with | OK Fail_sr => False | OK (Accept_sr sem buffer) => sem = full_sem /\ buffer = buffer_end /\ next_ptd ptd = None | OK (Progress_sr stack buffer) => match next_ptd ptd with | None => False | Some ptd => ptd_stack_compat ptd stack /\ buffer = ptd_buffer ptd end | Err => True end.
Lemma parse_fix_complete: forall (ptd:pt_dot) (stack:stack) (n_steps:nat), ptd_stack_compat ptd stack -> match parse_fix init stack (ptd_buffer ptd) n_steps with | OK (Parsed_pr sem_res buffer_end_res) => sem_res = full_sem /\ buffer_end_res = buffer_end /\ S (ptd_cost ptd) <= n_steps | OK Fail_pr => False | OK Timeout_pr => n_steps < S (ptd_cost ptd) | Err => True end.