Proof with eauto.
intros.
destruct H, H.
unfold step.
destruct (action_table (state_of_stack init stack)).
pose proof (reduce_step_invariant stack p x buffer_tmp).
destruct (reduce_step init stack p buffer_tmp) as [|[]]; intuition; subst...
destruct buffer_tmp.
unfold Streams.hd.
destruct t.
destruct (l x0); intuition.
exists (x ++ [existT (fun t => symbol_semantic_type (T t)) x0 s])%list.
split.
now rewrite <- app_str_app_assoc; intuition.
apply Cons_stack_whss; intuition.
destruct e; simpl.
now exact (inhabits (Terminal_pt _ _)).
match goal with |- (match reduce_step init stack p ?buff with Err => _ | OK _ => _ end) =>
pose proof (reduce_step_invariant stack p x buff);
destruct (reduce_step init stack p buff) as [|[]]; intuition; subst
end...
Qed.

(** The interpreter is correct : if it returns a semantic value, then the input word has this semantic value. **)
Theorem parse_correct buffer n_steps:
match parse init buffer n_steps with
| OK (Parsed_pr sem buffer_new) =>
exists word_new,
buffer = word_new ++ buffer_new /\
inhabited (parse_tree (NT (start_nt init)) word_new sem)
| _ => True
end.