Library grammar
Grammars
Definition tsym := nat.
Definition nsym := nat.
Inductive sym := T : tsym -> sym | NT : nsym -> sym.
Definition grammar : Set := list (nsym * list sym).
Derivations
Inductive deriv (g:grammar) : list sym -> list sym -> Prop :=
| deriv_nil : deriv g nil nil
| deriv_refl : forall l w s, deriv g l w -> deriv g (s::l) (s::w)
| deriv_NT :
forall exp l w u,
In (u,exp) g ->
deriv g (exp ++ l) w ->
deriv g (NT u :: l) w.
Parsing and LL(1) grammars
All definitions in this section will be parameterized by G.
A list of symbols is nullable if it can derive the empty word.
First a e means that a word in the language of e
starts with the terminal a.
A list of symbols is reachable if it is the suffix of a list
that can be derived from the initial non-terminal.
Definition Reachable u := exists w, deriv G (NT 0 :: nil) (w ++ u).
Definition Follow a U := exists v, Reachable (NT U :: v) /\ First a v.
Definition End U := exists v, Reachable (NT U :: v) /\ Nullable v.
Definition Follow a U := exists v, Reachable (NT U :: v) /\ First a v.
Definition End U := exists v, Reachable (NT U :: v) /\ Nullable v.
The high-level idea behind LL(1) grammars is that, when attempting to
determine whether w belongs to the language of NT U :: l, we want
to be able to determine a unique production U ~> e which can make
this work. When two productions could work, we say that there is a
conflict.
Conflicts can happen in several cases, for instance when w = a::_
and there are productions U ~> e and U ~> e' such that First a e
and First a e'. It also happens when First a e, Nullable e' and
Follow a U: intuitively, we could obtain a from e, but we could
also get rid of e' and then obtain a from l because it may follow
U.
A grammar is strongly LL(1) when there is no distinct productions
U ~> e and U ~> e' that are in conflict, in the following sense:
instead of definition a conjunction of conditions, we use a record,
so that conjuncts get names. When r : no_conflict u e e',
nullable_nullable r : Nullable e -> Nullable e' -> e = e'.
Record no_conflict u e e' : Prop := {
first_first : forall a, First a e -> First a e' -> e = e' ;
first_follow : forall a, First a e -> Nullable e' -> Follow a u -> e = e' ;
nullable_nullable : Nullable e -> Nullable e' -> e = e'
}.
Definition LL_1 :=
forall u e e', In (u,e) G -> In (u,e') G -> no_conflict u e e'.
End LL.