aboutsummaryrefslogtreecommitdiffstats
path: root/cparser
diff options
context:
space:
mode:
authorJacques-Henri Jourdan <jacques-henri.jourdan@inria.fr>2015-11-04 03:04:21 +0100
committerJacques-Henri Jourdan <jacques-henri.jourdan@inria.fr>2015-11-04 03:04:21 +0100
commit5664fddcab15ef4482d583673c75e07bd1e96d0a (patch)
tree878b22860e69405ba5cf6fd2798731dac8ce660c /cparser
parentb960c83725d7e185ac5c6e3c0d6043c7dcd2f556 (diff)
parentfe73ed58ef80da7c53c124302a608948fb190229 (diff)
downloadcompcert-kvx-5664fddcab15ef4482d583673c75e07bd1e96d0a.tar.gz
compcert-kvx-5664fddcab15ef4482d583673c75e07bd1e96d0a.zip
Merge remote-tracking branch 'origin/master' into parser_fix
Diffstat (limited to 'cparser')
-rw-r--r--cparser/Bitfields.ml12
-rw-r--r--cparser/C.mli10
-rw-r--r--cparser/Cabs.v6
-rw-r--r--cparser/Cabshelper.ml4
-rw-r--r--cparser/Cerrors.ml12
-rw-r--r--cparser/Cerrors.mli1
-rw-r--r--cparser/Ceval.ml10
-rw-r--r--cparser/Cleanup.ml6
-rw-r--r--cparser/Cprint.ml8
-rw-r--r--cparser/Cutil.ml76
-rw-r--r--cparser/Cutil.mli8
-rw-r--r--cparser/Elab.ml32
-rw-r--r--cparser/Env.ml12
-rw-r--r--cparser/ErrorReports.ml254
-rw-r--r--cparser/ErrorReports.mli43
-rw-r--r--cparser/ExtendedAsm.ml10
-rw-r--r--cparser/GCC.ml16
-rw-r--r--cparser/GNUmakefile186
-rw-r--r--cparser/Lexer.mll91
-rw-r--r--cparser/PackedStructs.ml8
-rw-r--r--cparser/Parse.ml18
-rw-r--r--cparser/Rename.ml16
-rw-r--r--cparser/StructReturn.ml10
-rw-r--r--cparser/Transform.ml6
-rw-r--r--cparser/Transform.mli6
-rw-r--r--cparser/Unblock.ml20
-rw-r--r--cparser/deLexer.ml135
-rw-r--r--cparser/handcrafted.messages4700
-rw-r--r--cparser/pre_parser.mly396
-rw-r--r--cparser/tests/generated/Makefile50
-rw-r--r--cparser/tests/handwritten/conditional-0.c4
-rw-r--r--cparser/tests/handwritten/conditional-1.c4
-rw-r--r--cparser/tests/handwritten/dubious-enum.c7
-rw-r--r--cparser/tests/handwritten/missing-assignment.c4
-rw-r--r--cparser/tests/handwritten/missing-closing-brace-at-end-of-function.c10
-rw-r--r--cparser/tests/handwritten/missing-loop-body.c5
-rw-r--r--cparser/tests/handwritten/missing-operator.c5
-rw-r--r--cparser/tests/handwritten/missing-semicolon.c5
-rw-r--r--cparser/tests/handwritten/too-many-closing-parens.c4
-rw-r--r--cparser/tests/handwritten/unclosed-paren.c5
-rw-r--r--cparser/tests/handwritten/variable-type-confusion.c6
-rw-r--r--cparser/validator/Alphabet.v4
-rw-r--r--cparser/validator/Automaton.v4
-rw-r--r--cparser/validator/Grammar.v12
-rw-r--r--cparser/validator/Interpreter.v2
-rw-r--r--cparser/validator/Interpreter_complete.v42
-rw-r--r--cparser/validator/Interpreter_correct.v6
-rw-r--r--cparser/validator/Validator_complete.v2
-rw-r--r--cparser/validator/Validator_safe.v2
49 files changed, 5967 insertions, 328 deletions
diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml
index d064f4b1..223ee3ca 100644
--- a/cparser/Bitfields.ml
+++ b/cparser/Bitfields.ml
@@ -191,12 +191,12 @@ let transf_composite env su id attr ml =
(* Bitfield manipulation expressions *)
let left_shift_count bf =
- intconst
+ intconst
(Int64.of_int (8 * !config.sizeof_int - (bf.bf_pos + bf.bf_size)))
IInt
let right_shift_count bf =
- intconst
+ intconst
(Int64.of_int (8 * !config.sizeof_int - bf.bf_size))
IInt
@@ -303,7 +303,7 @@ let bitfield_initializer bf i =
(* Associate to the left so that it prints more nicely *)
let or_expr_list = function
- | [] -> intconst 0L IUInt
+ | [] -> intconst 0L IUInt
| [e] -> e
| e1 :: el ->
List.fold_left
@@ -409,7 +409,7 @@ let rec transf_exp env ctx e =
| Some(ex, bf) ->
transf_post env ctx (op_for_incr_decr op) ex bf e1.etyp
end
- | EUnop(op, e1) ->
+ | EUnop(op, e1) ->
{edesc = EUnop(op, transf_exp env Val e1); etyp = e.etyp}
| EBinop(Oassign, e1, e2, ty) ->
@@ -433,7 +433,7 @@ let rec transf_exp env ctx e =
transf_assignop env ctx (op_for_assignop op) ex bf e2 ty
end
| EBinop(Ocomma, e1, e2, ty) ->
- {edesc = EBinop(Ocomma, transf_exp env Effects e1,
+ {edesc = EBinop(Ocomma, transf_exp env Effects e1,
transf_exp env Val e2, ty);
etyp = e.etyp}
| EBinop(op, e1, e2, ty) ->
@@ -534,5 +534,5 @@ let program p =
Transform.program
~composite:transf_composite
~decl: transf_decl
- ~fundef:transf_fundef
+ ~fundef:transf_fundef
p
diff --git a/cparser/C.mli b/cparser/C.mli
index 72e1f787..8d8f2805 100644
--- a/cparser/C.mli
+++ b/cparser/C.mli
@@ -27,7 +27,7 @@ type ident =
(* Kinds of integers *)
-type ikind =
+type ikind =
| IBool (** [_Bool] *)
| IChar (** [char] *)
| ISChar (** [signed char] *)
@@ -39,12 +39,12 @@ type ikind =
| ILong (** [long] *)
| IULong (** [unsigned long] *)
| ILongLong (** [long long] (or [_int64] on Microsoft Visual C) *)
- | IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft
+ | IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft
Visual C) *)
(** Kinds of floating-point numbers*)
-type fkind =
+type fkind =
FFloat (** [float] *)
| FDouble (** [double] *)
| FLongDouble (** [long double] *)
@@ -73,7 +73,7 @@ type attr_arg =
| AInt of int64
| AString of string
-type attribute =
+type attribute =
| AConst
| AVolatile
| ARestrict
@@ -216,7 +216,7 @@ and stmt_desc =
| Sdecl of decl
| Sasm of attributes * string * asm_operand list * asm_operand list * string list
-and slabel =
+and slabel =
| Slabel of string
| Scase of exp
| Sdefault
diff --git a/cparser/Cabs.v b/cparser/Cabs.v
index ab53a3a8..f5cab15a 100644
--- a/cparser/Cabs.v
+++ b/cparser/Cabs.v
@@ -87,18 +87,18 @@ with parameter :=
| PARAM : list spec_elem -> option string -> decl_type -> list attribute -> cabsloc -> parameter
(* The optional expression is the bitfield *)
-with field_group :=
+with field_group :=
| Field_group : list spec_elem -> list (option name * option expression) -> cabsloc -> field_group
(* The decl_type is in the order in which they are printed. Only the name of
* the declared identifier is pulled out. *)
(* e.g: in "int *x", "*x" is the declarator; "x" will be pulled out as *)
(* the string, and decl_type will be PTR([], JUSTBASE) *)
-with name :=
+with name :=
| Name : string -> decl_type -> list attribute -> cabsloc -> name
(* A variable declarator ("name") with an initializer *)
-with init_name :=
+with init_name :=
| Init_name : name -> init_expression -> init_name
(*
diff --git a/cparser/Cabshelper.ml b/cparser/Cabshelper.ml
index b3782ba8..b4e6a082 100644
--- a/cparser/Cabshelper.ml
+++ b/cparser/Cabshelper.ml
@@ -16,8 +16,8 @@
open Cabs
-let cabslu = {lineno = -10;
- filename = "cabs loc unknown";
+let cabslu = {lineno = -10;
+ filename = "cabs loc unknown";
byteno = -10;
ident = 0}
diff --git a/cparser/Cerrors.ml b/cparser/Cerrors.ml
index 23ec1710..5c077f37 100644
--- a/cparser/Cerrors.ml
+++ b/cparser/Cerrors.ml
@@ -26,6 +26,18 @@ let reset () = num_errors := 0; num_warnings := 0
exception Abort
+(* [fatal_error_raw] is identical to [fatal_error], except it uses [Printf]
+ to print its message, as opposed to [Format], and does not automatically
+ introduce indentation and a final dot into the message. This is useful
+ for multi-line messages. *)
+
+let fatal_error_raw fmt =
+ incr num_errors;
+ Printf.kfprintf
+ (fun _ -> raise Abort)
+ stderr
+ (fmt ^^ "Fatal error; compilation aborted.\n%!")
+
let fatal_error fmt =
incr num_errors;
kfprintf
diff --git a/cparser/Cerrors.mli b/cparser/Cerrors.mli
index 6d34451b..3e315fad 100644
--- a/cparser/Cerrors.mli
+++ b/cparser/Cerrors.mli
@@ -16,6 +16,7 @@
val warn_error : bool ref
val reset : unit -> unit
exception Abort
+val fatal_error_raw : ('a, out_channel, unit, 'b) format4 -> 'a
val fatal_error : ('a, Format.formatter, unit, unit, unit, 'b) format6 -> 'a
val error : ('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a
val warning : ('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a
diff --git a/cparser/Ceval.ml b/cparser/Ceval.ml
index ba7cdabc..74b535d4 100644
--- a/cparser/Ceval.ml
+++ b/cparser/Ceval.ml
@@ -124,7 +124,7 @@ let comparison env direction ptraction tyop ty1 v1 ty2 v2 =
(* tyop = type at which the comparison is done *)
let b =
match cast env tyop ty1 v1, cast env tyop ty2 v2 with
- | I n1, I n2 ->
+ | I n1, I n2 ->
if is_signed env tyop
then direction (compare n1 n2) 0
else direction (int64_unsigned_compare n1 n2) 0 (* including pointers *)
@@ -162,7 +162,7 @@ let binop env op tyop tyres ty1 v1 ty2 v2 =
end
| Odiv ->
begin match cast env tyop ty1 v1, cast env tyop ty2 v2 with
- | I n1, I n2 ->
+ | I n1, I n2 ->
if n2 = 0L then raise Notconst else
if is_signed env tyop then I (Int64.div n1 n2)
else I (int64_unsigned_div n1 n2)
@@ -170,7 +170,7 @@ let binop env op tyop tyres ty1 v1 ty2 v2 =
end
| Omod ->
begin match v1, v2 with
- | I n1, I n2 ->
+ | I n1, I n2 ->
if n2 = 0L then raise Notconst else
if is_signed env tyop then I (Int64.rem n1 n2)
else I (int64_unsigned_mod n1 n2)
@@ -220,11 +220,11 @@ let binop env op tyop tyres ty1 v1 ty2 v2 =
| Ocomma ->
v2
| Ologand ->
- if boolean_value v1
+ if boolean_value v1
then if boolean_value v2 then I 1L else I 0L
else I 0L
| Ologor ->
- if boolean_value v1
+ if boolean_value v1
then I 1L
else if boolean_value v2 then I 1L else I 0L
| _ -> raise Notconst
diff --git a/cparser/Cleanup.ml b/cparser/Cleanup.ml
index c81fd498..c8a900d5 100644
--- a/cparser/Cleanup.ml
+++ b/cparser/Cleanup.ml
@@ -92,7 +92,7 @@ let rec add_stmt s =
| Sbreak -> ()
| Scontinue -> ()
| Sswitch(e, s1) -> add_exp e; add_stmt s1
- | Slabeled(lbl, s) ->
+ | Slabeled(lbl, s) ->
begin match lbl with Scase e -> add_exp e | _ -> () end;
add_stmt s
| Sgoto lbl -> ()
@@ -187,7 +187,7 @@ let saturate p =
let remove_unused_debug = function
| Gdecl (_,id,_,_) -> Debug.remove_unused id
| Gfundef f -> Debug.remove_unused f.fd_name
- | _ -> ()
+ | _ -> ()
let rec simpl_globdecls accu = function
| [] -> accu
@@ -212,6 +212,6 @@ let program p =
let p' = simpl_globdecls [] p in
referenced := IdentSet.empty;
p'
-
+
diff --git a/cparser/Cprint.ml b/cparser/Cprint.ml
index 1af5af1e..e80a4c8e 100644
--- a/cparser/Cprint.ml
+++ b/cparser/Cprint.ml
@@ -81,7 +81,7 @@ let const pp = function
if c >= 32L && c <= 126L && c <> 34L && c <>92L
then fprintf pp "%c" (Char.chr (Int64.to_int c))
else fprintf pp "\" \"\\x%02Lx\" \"" c)
- l;
+ l;
fprintf pp "\""
| CEnum(id, v) ->
ident pp id
@@ -216,7 +216,7 @@ let rec exp pp (prec, a) =
if assoc = LtoR
then (prec', prec' + 1)
else (prec' + 1, prec') in
- if prec' < prec
+ if prec' < prec
then fprintf pp "@[<hov 2>("
else fprintf pp "@[<hov 2>";
begin match a.edesc with
@@ -329,7 +329,7 @@ let rec exp pp (prec, a) =
begin match al with
| [] -> ()
| a1 :: al ->
- fprintf pp "%a" exp (2, a1);
+ fprintf pp "%a" exp (2, a1);
List.iter (fun a -> fprintf pp ",@ %a" exp (2, a)) al
end;
fprintf pp ")@]"
@@ -394,7 +394,7 @@ exception Not_expr
let rec exp_of_stmt s =
match s.sdesc with
| Sdo e -> e
- | Sseq(s1, s2) ->
+ | Sseq(s1, s2) ->
{edesc = EBinop(Ocomma, exp_of_stmt s1, exp_of_stmt s2, TVoid []);
etyp = TVoid []}
| Sif(e, s1, s2) ->
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index 0def347f..a86c779f 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -44,7 +44,7 @@ let rec add_attributes (al1: attributes) (al2: attributes) =
else if a1 > a2 then a2 :: add_attributes al1 al2'
else a1 :: add_attributes al1' al2'
-let rec remove_attributes (al1: attributes) (al2: attributes) =
+let rec remove_attributes (al1: attributes) (al2: attributes) =
(* viewed as sets: al1 \ al2 *)
match al1, al2 with
| [], _ -> []
@@ -91,7 +91,7 @@ let attr_is_type_related = function
| Attr(("packed" | "__packed__"), _) -> true
| _ -> false
-(* Is an attribute applicable to a whole array (true) or only to
+(* Is an attribute applicable to a whole array (true) or only to
array elements (false)? *)
let attr_array_applicable = function
@@ -114,10 +114,10 @@ let rec add_attributes_type attr t =
| TInt(ik, a) -> TInt(ik, add_attributes attr a)
| TFloat(fk, a) -> TFloat(fk, add_attributes attr a)
| TPtr(ty, a) -> TPtr(ty, add_attributes attr a)
- | TArray(ty, sz, a) ->
+ | TArray(ty, sz, a) ->
let (attr_arr, attr_elt) = List.partition attr_array_applicable attr in
TArray(add_attributes_type attr_elt ty, sz, add_attributes attr_arr a)
- | TFun(ty, params, vararg, a) -> TFun(ty, params, vararg, add_attributes attr
+ | TFun(ty, params, vararg, a) -> TFun(ty, params, vararg, add_attributes attr
a)
| TNamed(s, a) -> TNamed(s, add_attributes attr a)
| TStruct(s, a) -> TStruct(s, add_attributes attr a)
@@ -144,7 +144,7 @@ let rec attributes_of_type env t =
| TArray(ty, sz, a) -> add_attributes a (attributes_of_type env ty)
| TFun(ty, params, vararg, a) -> a
| TNamed(s, a) -> attributes_of_type env (unroll env t)
- | TStruct(s, a) ->
+ | TStruct(s, a) ->
let ci = Env.find_struct env s in add_attributes ci.ci_attr a
| TUnion(s, a) ->
let ci = Env.find_union env s in add_attributes ci.ci_attr a
@@ -177,6 +177,48 @@ let remove_attributes_type env attr t =
let erase_attributes_type env t =
change_attributes_type env (fun a -> []) t
+(* Remove all attributes from type that are not contained in attr *)
+let strip_attributes_type t attr =
+ let strip = List.filter (fun a -> List.mem a attr) in
+ match t with
+ | TVoid at -> TVoid (strip at)
+ | TInt (k,at) -> TInt (k,strip at)
+ | TFloat (k,at) -> TFloat(k,strip at)
+ | TPtr (t,at) -> TPtr(t,strip at)
+ | TArray (t,s,at) -> TArray(t,s,strip at)
+ | TFun (t,arg,v,at) -> TFun(t,arg,v,strip at)
+ | TNamed (n,at) -> TNamed(n,strip at)
+ | TStruct (n,at) -> TStruct(n,strip at)
+ | TUnion (n,at) -> TUnion(n,strip at)
+ | TEnum (n,at) -> TEnum(n,strip at)
+
+(* Remove the last attribute from the toplevel and return the changed type *)
+let strip_last_attribute typ =
+ let rec hd_opt l = match l with
+ [] -> None,[]
+ | a::rest -> Some a,rest in
+ match typ with
+ | TVoid at -> let l,r = hd_opt at in
+ l,TVoid r
+ | TInt (k,at) -> let l,r = hd_opt at in
+ l,TInt (k,r)
+ | TFloat (k,at) -> let l,r = hd_opt at in
+ l,TFloat (k,r)
+ | TPtr (t,at) -> let l,r = hd_opt at in
+ l,TPtr(t,r)
+ | TArray (t,s,at) -> let l,r = hd_opt at in
+ l,TArray(t,s,r)
+ | TFun (t,arg,v,at) -> let l,r = hd_opt at in
+ l,TFun(t,arg,v,r)
+ | TNamed (n,at) -> let l,r = hd_opt at in
+ l,TNamed(n,r)
+ | TStruct (n,at) -> let l,r = hd_opt at in
+ l,TStruct(n,r)
+ | TUnion (n,at) -> let l,r = hd_opt at in
+ l,TUnion(n,r)
+ | TEnum (n,at) -> let l,r = hd_opt at in
+ l,TEnum(n,r)
+
(* Extracting alignment value from a set of attributes. Return 0 if none. *)
let alignas_attribute al =
@@ -264,9 +306,9 @@ let combine_types mode env t1 t2 =
| _, TNamed _ -> comp m t1 (unroll env t2)
| TStruct(s1, a1), TStruct(s2, a2) ->
TStruct(comp_base s1 s2, comp_attr m a1 a2)
- | TUnion(s1, a1), TUnion(s2, a2) ->
+ | TUnion(s1, a1), TUnion(s2, a2) ->
TUnion(comp_base s1 s2, comp_attr m a1 a2)
- | TEnum(s1, a1), TEnum(s2, a2) ->
+ | TEnum(s1, a1), TEnum(s2, a2) ->
TEnum(comp_base s1 s2, comp_attr m a1 a2)
| _, _ ->
raise Incompat
@@ -334,7 +376,7 @@ let pack_bitfields ml =
in
let (nbits, ml') = pack 0 ml in
let (sz, al) =
- (* A lone bitfield of width 0 consumes no space and aligns to 1 *)
+ (* A lone bitfield of width 0 consumes no space and aligns to 1 *)
if nbits = 0 then (0, 1) else
if nbits <= 8 then (1, 1) else
if nbits <= 16 then (2, 2) else
@@ -445,7 +487,7 @@ let rec sizeof env t =
| TEnum(_, _) -> Some(sizeof_ikind enum_ikind)
(* Compute the size of a union.
- It is the size is the max of the sizes of fields.
+ It is the size is the max of the sizes of fields.
Not done here but in composite_info_decl: rounding size to alignment. *)
let sizeof_union env members =
@@ -497,7 +539,7 @@ let struct_layout env members =
end
| m :: rem ->
match alignof env m.fld_typ, sizeof env m.fld_typ with
- | Some a, Some s ->
+ | Some a, Some s ->
let offset = align ofs a in
struct_layout_rec ((m.fld_name,offset)::mem) (offset + s) rem
| _, _ -> []
@@ -538,11 +580,11 @@ let composite_info_def env su attr m =
let int_representable v nbits sgn =
if nbits >= 64 then true else
- if sgn then
+ if sgn then
let p = Int64.shift_left 1L (nbits - 1) in Int64.neg p <= v && v < p
else
0L <= v && v < Int64.shift_left 1L nbits
-
+
(* Type of a function definition *)
let fundef_typ fd =
@@ -667,9 +709,9 @@ let pointer_decay env t =
| TFun _ as ty -> TPtr(ty, [])
| t -> t
-(* The usual unary conversions (H&S 6.3.3) *)
+(* The usual unary conversions (H&S 6.3.3) *)
-let unary_conversion env t =
+let unary_conversion env t =
match unroll env t with
(* Promotion of small integer types *)
| TInt(kind, attr) ->
@@ -732,7 +774,7 @@ let binary_conversion env t1 t2 =
(* Conversion on function arguments (with protoypes) *)
-let argument_conversion env t =
+let argument_conversion env t =
(* Arrays and functions degrade automatically to pointers *)
(* Other types are not changed *)
match unroll env t with
@@ -928,7 +970,7 @@ let rec eaddrof e =
match e.edesc with
| EUnop(Oderef, e1) -> e1
| EBinop(Ocomma, e1, e2, _) -> ecomma e1 (eaddrof e2)
- | EConditional(e1, e2, e3) ->
+ | EConditional(e1, e2, e3) ->
{ edesc = EConditional(e1, eaddrof e2, eaddrof e3); etyp = TPtr(e.etyp, []) }
| _ -> { edesc = EUnop(Oaddrof, e); etyp = TPtr(e.etyp, []) }
@@ -1050,7 +1092,7 @@ let rec subst_stmt phi s =
| Sblock sl -> Sblock (List.map (subst_stmt phi) sl)
| Sdecl d -> Sdecl (subst_decl phi d)
| Sasm(attr, template, outputs, inputs, clob) ->
- let subst_asm_operand (lbl, cstr, e) =
+ let subst_asm_operand (lbl, cstr, e) =
(lbl, cstr, subst_expr phi e) in
Sasm(attr, template,
List.map subst_asm_operand outputs,
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index a322bfb1..8b6c609b 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -56,6 +56,10 @@ val attr_is_type_related: attribute -> bool
(* Is an attribute type-related (true) or variable-related (false)? *)
val attr_inherited_by_members: attribute -> bool
(* Is an attribute of a composite inherited by members of the composite? *)
+val strip_attributes_type: typ -> attribute list -> typ
+ (* Remove all attributes from the given type that are not contained in the list *)
+val strip_last_attribute: typ -> attribute option * typ
+ (* Remove the last top level attribute and return it *)
(* Type compatibility *)
@@ -65,7 +69,7 @@ type attr_handling =
| AttrIgnoreAll
val compatible_types : attr_handling -> Env.t -> typ -> typ -> bool
- (* Check that the two given types are compatible.
+ (* Check that the two given types are compatible.
The attributes in the types are compared according to the first argument:
- [AttrCompat]: the types must have the same standard attributes
([const], [volatile], [restrict]) but may differ on custom attributes.
@@ -225,7 +229,7 @@ val ecommalist : exp list -> exp -> exp
val sskip: stmt
(* The [skip] statement. No location. *)
val sseq : location -> stmt -> stmt -> stmt
- (* Return the statement [s1; s2], optimizing the cases
+ (* Return the statement [s1; s2], optimizing the cases
where [s1] or [s2] is [skip], or [s2] is a block. *)
val sassign : location -> exp -> exp -> stmt
(* Return the statement [exp1 = exp2;] *)
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index d078cdac..27b650c0 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -103,7 +103,7 @@ let elab_funbody_f : (C.typ -> Env.t -> statement -> C.stmt) ref
(** * Elaboration of constants - C99 section 6.4.4 *)
-let has_suffix s suff =
+let has_suffix s suff =
let ls = String.length s and lsuff = String.length suff in
ls >= lsuff && String.sub s (ls - lsuff) lsuff = suff
@@ -111,7 +111,7 @@ let chop_last s n =
assert (String.length s >= n);
String.sub s 0 (String.length s - n)
-let has_prefix s pref =
+let has_prefix s pref =
let ls = String.length s and lpref = String.length pref in
ls >= lpref && String.sub s 0 lpref = pref
@@ -195,7 +195,7 @@ let elab_int_constant loc s0 =
in
(* Find smallest allowable type that fits *)
let ty =
- try List.find (fun ty -> integer_representable v ty)
+ try List.find (fun ty -> integer_representable v ty)
(if base = 10 then dec_kinds else hex_kinds)
with Not_found ->
error loc "integer literal '%s' cannot be represented" s0;
@@ -224,7 +224,7 @@ let elab_char_constant loc wide chars =
let max_digit = Int64.shift_left 1L nbits in
let max_val = Int64.shift_left 1L (64 - nbits) in
let v =
- List.fold_left
+ List.fold_left
(fun acc d ->
if acc < 0L || acc >= max_val then
error loc "character constant overflows";
@@ -243,7 +243,7 @@ let elab_char_constant loc wide chars =
IInt)
let elab_string_literal loc wide chars =
- let nbits = if wide then 8 * !config.sizeof_wchar else 8 in
+ let nbits = if wide then 8 * !config.sizeof_wchar else 8 in
let char_max = Int64.shift_left 1L nbits in
List.iter
(fun c ->
@@ -390,7 +390,7 @@ let rec elab_specifier ?(only = false) loc env specifier =
let sto = ref Storage_default
and inline = ref false
and attr = ref []
- and tyspecs = ref []
+ and tyspecs = ref []
and typedef = ref false in
let do_specifier = function
@@ -404,7 +404,7 @@ let rec elab_specifier ?(only = false) loc env specifier =
| STATIC -> sto := Storage_static
| EXTERN -> sto := Storage_extern
| REGISTER -> sto := Storage_register
- | TYPEDEF ->
+ | TYPEDEF ->
if !typedef then
error loc "multiple uses of 'typedef'";
typedef := true
@@ -690,7 +690,7 @@ and elab_field_group env (Field_group (spec, fieldlist, loc)) =
error loc "bit size of '%s' is not a compile-time constant" id;
None
end in
- { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize' }
+ { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize' }
in
(List.map2 elab_bitfield fieldlist names, env')
@@ -986,7 +986,7 @@ module I = struct
if fld.fld_name = fld1.fld_name
then i
else default_init env fld1.fld_typ)
- end
+ end
| (TStruct _ | TUnion _), Init_single a ->
(* This is a previous whole-struct initialization that we
are going to overwrite. Revert to the default initializer. *)
@@ -999,7 +999,7 @@ module I = struct
let index env (z, i as zi) n =
match unroll env (typeof zi), i with
| TArray(ty, sz, _), Init_array il ->
- if n >= 0L && index_below n sz then begin
+ if n >= 0L && index_below n sz then begin
let dfl = default_init env ty in
let rec loop p before after =
if p = n then
@@ -1053,7 +1053,7 @@ end
let rec elab_designator loc env zi desig =
match desig with
- | [] ->
+ | [] ->
zi
| INFIELD_INIT name :: desig' ->
begin match I.member env zi name with
@@ -1112,7 +1112,7 @@ let rec elab_list zi il first =
and elab_item zi item il =
let ty = I.typeof zi in
match item, unroll env ty with
- (* Special case char array = "string literal"
+ (* Special case char array = "string literal"
or wchar array = L"wide string literal" *)
| (SINGLE_INIT (CONSTANT (CONST_STRING(w, s)))
| COMPOUND_INIT [_, SINGLE_INIT(CONSTANT (CONST_STRING(w, s)))]),
@@ -1782,7 +1782,7 @@ let elab_for_expr loc env = function
(* Handling of __func__ (section 6.4.2.2) *)
-let __func__type_and_init s =
+let __func__type_and_init s =
(TArray(TInt(IChar, [AConst]), Some(Int64.of_int (String.length s + 1)), []),
init_char_array_string None s)
@@ -2113,7 +2113,7 @@ let rec elab_stmt env ctx s =
if not (is_scalar_type env a'.etyp) then
error loc "the condition of 'if' does not have scalar type";
let s1' = elab_stmt env ctx s1 in
- let s2' =
+ let s2' =
match s2 with
| None -> sskip
| Some s2 -> elab_stmt env ctx s2
@@ -2146,12 +2146,12 @@ let rec elab_stmt env ctx s =
| Some (FC_DECL def) ->
let (dcl, env') = elab_definition true (Env.new_scope env) def in
let loc = elab_loc (get_definitionloc def) in
- (sskip, env',
+ (sskip, env',
Some(List.map (fun d -> {sdesc = Sdecl d; sloc = loc}) dcl)) in
let a2' =
match a2 with
| None -> intconst 1L IInt
- | Some a2 -> elab_expr loc env' a2
+ | Some a2 -> elab_expr loc env' a2
in
if not (is_scalar_type env' a2'.etyp) then
error loc "the condition of 'for' does not have scalar type";
diff --git a/cparser/Env.ml b/cparser/Env.ml
index 6610c159..65df6cb9 100644
--- a/cparser/Env.ml
+++ b/cparser/Env.ml
@@ -132,7 +132,7 @@ let lookup_struct env s =
res
with Not_found ->
raise(Error(Unbound_tag(s, "struct")))
-
+
let lookup_union env s =
try
let (id, ci as res) = IdentMap.lookup s env.env_tag in
@@ -141,7 +141,7 @@ let lookup_union env s =
res
with Not_found ->
raise(Error(Unbound_tag(s, "union")))
-
+
let lookup_composite env s =
try Some (IdentMap.lookup s env.env_tag)
with Not_found -> None
@@ -191,7 +191,7 @@ let find_union env id =
ci
with Not_found ->
raise(Error(Unbound_tag(id.name, "union")))
-
+
let find_member ci m =
List.find (fun f -> f.fld_name = m) ci
@@ -258,7 +258,7 @@ let add_typedef env id info =
let add_enum env id info =
let add_enum_item env (id, v, exp) =
{ env with env_ident = IdentMap.add id (II_enum v) env.env_ident } in
- List.fold_left add_enum_item
+ List.fold_left add_enum_item
{ env with env_enum = IdentMap.add id info env.env_enum }
info.ei_members
@@ -270,12 +270,12 @@ let composite_tag_name name =
if name = "" then "<anonymous>" else name
let error_message = function
- | Unbound_identifier name ->
+ | Unbound_identifier name ->
sprintf "Unbound identifier '%s'" name
| Unbound_tag(name, kind) ->
sprintf "Unbound %s '%s'" kind (composite_tag_name name)
| Tag_mismatch(name, expected, actual) ->
- sprintf "'%s' was declared as a %s but is used as a %s"
+ sprintf "'%s' was declared as a %s but is used as a %s"
(composite_tag_name name) actual expected
| Unbound_typedef name ->
sprintf "Unbound typedef '%s'" name
diff --git a/cparser/ErrorReports.ml b/cparser/ErrorReports.ml
new file mode 100644
index 00000000..4bbf3ded
--- /dev/null
+++ b/cparser/ErrorReports.ml
@@ -0,0 +1,254 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* François Pottier, INRIA Paris-Rocquencourt *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation, either version 2 of the License, or *)
+(* (at your option) any later version. This file is also distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+open Lexing
+open Pre_parser.MenhirInterpreter
+module S = MenhirLib.General (* Streams *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* There are places where we may hit an internal error and we would like to fail
+ abruptly because "this cannot happen". Yet, it is safer when shipping to
+ silently cover up for our internal error. Thus, we typically use an idiom of
+ the form [if debug then assert false else <some default value>]. *)
+
+let debug = false
+
+(* -------------------------------------------------------------------------- *)
+
+(* The parser keeps track of the last two tokens in a two-place buffer. *)
+
+type 'a buffer =
+| Zero
+| One of 'a
+| Two of 'a * (* most recent: *) 'a
+
+(* [push buffer x] pushes [x] into [buffer], causing the buffer to slide. *)
+
+let update buffer x : _ buffer =
+ match buffer, x with
+ | Zero, _ ->
+ One x
+ | One x1, x2
+ | Two (_, x1), x2 ->
+ Two (x1, x2)
+
+(* [show f buffer] prints the contents of the buffer. The function [f] is
+ used to print an element. *)
+
+let show f buffer : string =
+ match buffer with
+ | Zero ->
+ (* The buffer cannot be empty. If we have read no tokens, we
+ cannot have detected a syntax error. *)
+ if debug then assert false else ""
+ | One invalid ->
+ (* It is unlikely, but possible, that we have read just one token. *)
+ Printf.sprintf "before '%s'" (f invalid)
+ | Two (valid, invalid) ->
+ (* In the most likely case, we have read two tokens. *)
+ Printf.sprintf "after '%s' and before '%s'" (f valid) (f invalid)
+
+(* [last buffer] returns the last element of the buffer (that is, the
+ invalid token). *)
+
+let last buffer =
+ match buffer with
+ | Zero ->
+ (* The buffer cannot be empty. If we have read no tokens, we
+ cannot have detected a syntax error. *)
+ assert false
+ | One invalid
+ | Two (_, invalid) ->
+ invalid
+
+(* -------------------------------------------------------------------------- *)
+
+(* [extract text (pos1, pos2)] extracts the sub-string of [text] delimited
+ by the positions [pos1] and [pos2]. *)
+
+let extract text (pos1, pos2) : string =
+ let ofs1 = pos1.pos_cnum
+ and ofs2 = pos2.pos_cnum in
+ let len = ofs2 - ofs1 in
+ try
+ String.sub text ofs1 len
+ with Invalid_argument _ ->
+ (* In principle, this should not happen, but if it does, let's make this
+ a non-fatal error. *)
+ if debug then assert false else "???"
+
+(* -------------------------------------------------------------------------- *)
+
+(* [sanitize text] eliminates any special characters from the text [text].
+ They are (arbitrarily) replaced with a single dot character. *)
+
+let sanitize text =
+ String.map (fun c ->
+ if Char.code c < 32 || Char.code c >= 127 then '.' else c
+ ) text
+
+(* -------------------------------------------------------------------------- *)
+
+(* [shorten k text] limits the length of [text] to [2k+3] characters. If the
+ text is too long, a fragment in the middle is replaced with an ellipsis. *)
+
+let shorten k text =
+ let n = String.length text in
+ if n <= 2 * k + 3 then
+ text
+ else
+ String.sub text 0 k ^
+ "..." ^
+ String.sub text (n - k) k
+
+(* -------------------------------------------------------------------------- *)
+
+(* [stack checkpoint] extracts the parser's stack out of a checkpoint. *)
+
+let stack checkpoint =
+ match checkpoint with
+ | HandlingError env ->
+ stack env
+ | _ ->
+ assert false (* this cannot happen, I promise *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [state checkpoint] extracts the number of the current state out of a
+ parser checkpoint. *)
+
+let state checkpoint : int =
+ match Lazy.force (stack checkpoint) with
+ | S.Nil ->
+ (* Hmm... The parser is in its initial state. Its number is
+ usually 0. This is a BIG HACK. TEMPORARY *)
+ 0
+ | S.Cons (Element (s, _, _, _), _) ->
+ number s
+
+(* -------------------------------------------------------------------------- *)
+
+(* TEMPORARY move to MenhirLib.General *)
+
+let rec drop n (xs : 'a S.stream) : 'a S.stream =
+ match n, xs with
+ | 0, _
+ | _, lazy (S.Nil) ->
+ xs
+ | _, lazy (S.Cons (_, xs)) ->
+ drop (n - 1) xs
+
+(* -------------------------------------------------------------------------- *)
+
+(* [element checkpoint i] returns the [i]-th cell of the parser stack. The index
+ [i] is 0-based. [i] should (ideally) be within bounds; we raise [Not_found]
+ if it isn't. *)
+
+let element checkpoint i : element =
+ match Lazy.force (drop i (stack checkpoint)) with
+ | S.Nil ->
+ (* [i] is out of range. This could happen if the handwritten error
+ messages are out of sync with the grammar, or if a mistake was
+ made. We fail in a non-fatal way. *)
+ raise Not_found
+ | S.Cons (e, _) ->
+ e
+
+(* -------------------------------------------------------------------------- *)
+
+(* [range text e] converts the stack element [e] to the fragment of the source
+ text that corresponds to this stack element. The fragment is placed within
+ single quotes and shortened if it is too long. We also ensure that it does
+ not contain any special characters. *)
+
+let width = 30
+
+let range text (e : element) : string =
+ (* Extract the start and positions of this stack element. *)
+ let Element (_, _, pos1, pos2) = e in
+ (* Get the underlying source text fragment. *)
+ let fragment = extract text (pos1, pos2) in
+ (* Sanitize it and limit its length. Enclose it in single quotes. *)
+ "'" ^ shorten width (sanitize fragment) ^ "'"
+
+(* -------------------------------------------------------------------------- *)
+
+(* We allow an error message to contain the special form $i, where is a 0-based
+ index into the stack. We replace it with the fragment of the source text that
+ corresponds to this stack entry. *)
+
+let fragment text checkpoint message =
+ try
+ let i = int_of_string (Str.matched_group 1 message) in
+ range text (element checkpoint i)
+ with
+ | Failure _ ->
+ (* In principle, this should not happen, but if it does, let's cover up
+ for our internal error. *)
+ if debug then assert false else "???"
+ | Not_found ->
+ (* In principle, this should not happen, but if it does, let's cover up
+ for our internal error. *)
+ if debug then assert false else "???"
+
+let fragments text checkpoint (message : string) : string =
+ Str.global_substitute
+ (Str.regexp "\\$\\([0-9]+\\)")
+ (fragment text checkpoint)
+ message
+
+(* -------------------------------------------------------------------------- *)
+
+(* [report text buffer checkpoint] constructs an error message. The C source
+ code must be stored in the string [text]. The start and end positions of the
+ last two tokens that were read must be stored in [buffer]. The parser state
+ (i.e., the automaton's state and stack) must be recorded in the checkpoint
+ [checkpoint]. *)
+
+(* The start and end positions of the invalid token are [lexbuf.lex_start_p]
+ and [lexbuf.lex_curr_p], since this is the last token that was read. But
+ we need not care about that here. *)
+
+let report text buffer checkpoint : string =
+ (* Extract the position where the error occurred, that is, the start
+ position of the invalid token. We display it as a filename, a (1-based)
+ line number, and a (0-based) column number. *)
+ let (pos, _) = last buffer in
+ (* Construct a readable description of where the error occurred, that is,
+ after which token and before which token. *)
+ let where = show (extract text) buffer in
+ (* Find out in which state the parser failed. *)
+ let s : int = state checkpoint in
+ (* Choose an error message, based on the state number [s].
+ Then, customize it, based on dynamic information. *)
+ let message = try
+ Pre_parser_messages.message s |>
+ fragments text checkpoint
+ with Not_found ->
+ (* If the state number cannot be found -- which, in principle,
+ should not happen, since our list of erroneous states is
+ supposed to be complete! -- produce a generic message. *)
+ Printf.sprintf "This is an unknown syntax error (%d).\n\
+ Please report this problem to the compiler vendor.\n" s
+ in
+ (* Construct the full error message. *)
+ Printf.sprintf "%s:%d:%d: syntax error %s.\n%s"
+ pos.pos_fname
+ pos.pos_lnum
+ (pos.pos_cnum - pos.pos_bol)
+ where
+ message
+
diff --git a/cparser/ErrorReports.mli b/cparser/ErrorReports.mli
new file mode 100644
index 00000000..f803a08b
--- /dev/null
+++ b/cparser/ErrorReports.mli
@@ -0,0 +1,43 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* François Pottier, INRIA Paris-Rocquencourt *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation, either version 2 of the License, or *)
+(* (at your option) any later version. This file is also distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+(* This module is in charge of reporting a syntax error after the pre_parser
+ has failed. *)
+
+open Pre_parser.MenhirInterpreter
+
+(* The parser keeps track of the last two tokens in a two-place buffer. *)
+
+type 'a buffer =
+| Zero
+| One of 'a
+| Two of 'a * (* most recent: *) 'a
+
+(* [push buffer x] pushes [x] into [buffer], causing the buffer to slide. *)
+
+val update: 'a buffer -> 'a -> 'a buffer
+
+(* [report text buffer checkpoint] constructs an error message. The C source
+ code must be stored in the string [text]. The start and end positions of the
+ last two tokens that were read must be stored in [buffer]. The parser state
+ (i.e., the automaton's state and stack) must be recorded in the checkpoint
+ [checkpoint]. *)
+
+val report:
+ string ->
+ (Lexing.position * Lexing.position) buffer ->
+ _ checkpoint ->
+ string
+
diff --git a/cparser/ExtendedAsm.ml b/cparser/ExtendedAsm.ml
index 05084561..94fcda31 100644
--- a/cparser/ExtendedAsm.ml
+++ b/cparser/ExtendedAsm.ml
@@ -18,7 +18,7 @@
(* The [transf_asm] function in this module takes a full GCC-style
extended asm statement and puts it in the form supported by
CompCert, namely:
- - 0 or 1 output of kind "r"
+ - 0 or 1 output of kind "r"
- 0, 1 or several inputs of kind "r".
Inputs and outputs of kind "m" (memory location) are emulated
by taking the address of the operand and treating it as
@@ -116,7 +116,7 @@ let rec transf_inputs loc env accu pos pos' subst = function
transf_inputs loc env (e :: accu) (pos + 1) (pos' + 1)
(set_label_reg lbl pos pos' subst) inputs
end
-
+
(* Transform the output operands:
- outputs of kind "=m" become an input (equal to the address of the output)
*)
@@ -147,7 +147,7 @@ let transf_outputs loc env = function
| outputs ->
error "%aUnsupported feature: asm statement with 2 or more outputs"
formatloc loc;
- (* Bind the outputs so that we don't get another error
+ (* Bind the outputs so that we don't get another error
when substituting the text *)
let rec bind_outputs pos subst = function
| [] -> (None, [], subst, pos, pos)
@@ -165,7 +165,7 @@ let check_clobbers loc clob =
|| List.mem c' Machregsaux.scratch_register_names
|| c' = "MEMORY" || c' = "CC"
then ()
- else error "%aError: unrecognized asm register clobber '%s'"
+ else error "%aError: unrecognized asm register clobber '%s'"
formatloc loc c)
clob
@@ -174,7 +174,7 @@ let check_clobbers loc clob =
let re_asm_placeholder =
Str.regexp "\\(%[QR]?\\([0-9]+\\|\\[[a-zA-Z_][a-zA-Z_0-9]*\\]\\)\\|%%\\)"
-let rename_placeholders loc template subst =
+let rename_placeholders loc template subst =
let rename p =
if p = "%%" then p else
try
diff --git a/cparser/GCC.ml b/cparser/GCC.ml
index 030f300b..f7f64a4e 100644
--- a/cparser/GCC.ml
+++ b/cparser/GCC.ml
@@ -65,7 +65,7 @@ let builtins = {
"__builtin_acosl", (longDoubleType, [ longDoubleType ], false);
"__builtin_alloca", (voidPtrType, [ uintType ], false);
-
+
"__builtin_asin", (doubleType, [ doubleType ], false);
"__builtin_asinf", (floatType, [ floatType ], false);
"__builtin_asinl", (longDoubleType, [ longDoubleType ], false);
@@ -76,7 +76,7 @@ let builtins = {
"__builtin_atan2", (doubleType, [ doubleType; doubleType ], false);
"__builtin_atan2f", (floatType, [ floatType; floatType ], false);
- "__builtin_atan2l", (longDoubleType, [ longDoubleType;
+ "__builtin_atan2l", (longDoubleType, [ longDoubleType;
longDoubleType ], false);
"__builtin_ceil", (doubleType, [ doubleType ], false);
@@ -133,12 +133,12 @@ let builtins = {
"__builtin_frexp", (doubleType, [ doubleType; intPtrType ], false);
"__builtin_frexpf", (floatType, [ floatType; intPtrType ], false);
- "__builtin_frexpl", (longDoubleType, [ longDoubleType;
+ "__builtin_frexpl", (longDoubleType, [ longDoubleType;
intPtrType ], false);
"__builtin_ldexp", (doubleType, [ doubleType; intType ], false);
"__builtin_ldexpf", (floatType, [ floatType; intType ], false);
- "__builtin_ldexpl", (longDoubleType, [ longDoubleType;
+ "__builtin_ldexpl", (longDoubleType, [ longDoubleType;
intType ], false);
"__builtin_log", (doubleType, [ doubleType ], false);
@@ -149,10 +149,10 @@ let builtins = {
"__builtin_log10f", (floatType, [ floatType ], false);
"__builtin_log10l", (longDoubleType, [ longDoubleType ], false);
- "__builtin_modff", (floatType, [ floatType;
+ "__builtin_modff", (floatType, [ floatType;
TPtr(floatType,[]) ], false);
- "__builtin_modfl", (longDoubleType, [ longDoubleType;
- TPtr(longDoubleType, []) ],
+ "__builtin_modfl", (longDoubleType, [ longDoubleType;
+ TPtr(longDoubleType, []) ],
false);
"__builtin_nan", (doubleType, [ charConstPtrType ], false);
@@ -210,7 +210,7 @@ let builtins = {
"__builtin_tanhl", (longDoubleType, [ longDoubleType ], false);
"__builtin_va_end", (voidType, [ voidPtrType ], false);
- "__builtin_varargs_start",
+ "__builtin_varargs_start",
(voidType, [ voidPtrType ], false);
(* When we elaborate builtin_stdarg_start/builtin_va_start,
second argument is passed by address *)
diff --git a/cparser/GNUmakefile b/cparser/GNUmakefile
new file mode 100644
index 00000000..d83c49e5
--- /dev/null
+++ b/cparser/GNUmakefile
@@ -0,0 +1,186 @@
+#######################################################################
+# #
+# The Compcert verified compiler #
+# #
+# François Pottier, INRIA Paris-Rocquencourt #
+# #
+# Copyright Institut National de Recherche en Informatique et en #
+# Automatique. All rights reserved. This file is distributed #
+# under the terms of the INRIA Non-Commercial License Agreement. #
+# #
+#######################################################################
+
+# This is a development Makefile.
+# It is meant to be used by developers who wish to modify the pre_parser.
+
+# A collection of erroneous input sentences (and accompanying error messages)
+# for the pre_parser is stored in the file handcrafted.messages.
+
+# After a modification to the pre_parser, one must ensure that this collection of
+# erroneous input sentences remains correct, irredundant, and complete. By this,
+# we mean:
+# - every input sentence in the collection leads to an error (on its last token);
+# - every state where an error can occur is reached by some input sentence in the
+# collection;
+# - every state where an error can occur is reached by at most one input sentence
+# in the collection.
+
+# These properties are checked by [make correct] and [make complete] below.
+# [make correct] is cheap and is performed automatically when CompCert is
+# compiled. [make complete] is expensive and must be called explicitly.
+
+# After a modification to the pre_parser, one should also reconstruct the
+# auto-generated comments in handcrafted.messages. This is done by calling
+# [make update].
+
+# Finally, after a modification to the pre_parser, one should ensure that every
+# error message remains meaningful. Indeed, an error message should not be
+# specific of the example sentence that causes this error; it should reflect all
+# possible sentences that cause an error in this state. One must look at the
+# description of the error state (which is part of the auto-generated comments)
+# and decide, based on this description, whether the error message seems
+# appropriate.
+
+# If you wish to play with one input sentence and see how the automaton behaves,
+# use [make interpret] or [make interpret_error].
+
+# If you wish to translate the database of erroneous input sentences to concrete
+# syntax, so as to be able to run a C compiler on these sentences, use [make
+# concrete].
+
+# ------------------------------------------------------------------------------
+
+# Make sure we use the same Menhir setup as the main CompCert Makefiles.
+
+include ../Makefile.menhir
+
+# Be more verbose about the automaton.
+
+FLAGS := $(MENHIR_FLAGS) -v -la 2
+
+# So, here is our basic Menhir command.
+
+COMMAND := $(MENHIR) $(MENHIR_MODE) pre_parser.mly $(FLAGS)
+
+# And this is the database of messages.
+
+DATABASE := handcrafted.messages
+
+# We use (GNU) cut when de-lexing examples sentences.
+
+CUT := $(shell if which gcut >&/dev/null ; then echo gcut ; else echo cut ; fi)
+
+# ------------------------------------------------------------------------------
+
+# Working with the error message database.
+
+.PHONY: nothing correct complete update
+
+nothing:
+ @ echo "If you wish to compile CompCert, please run \"make\" one level up."
+ @ echo "If you wish to work on the pre-parser, please read GNUmakefile."
+
+# Checking correctness and irredundancy is done via --compile-errors.
+# This entry is also called from [Makefile.extr] to compile the message
+# database down to OCaml code.
+# This also produces a description of the automaton in pre_parser.automaton
+# and a description of the conflicts (if any) in pre_parser.conflicts.
+correct:
+ @ $(COMMAND) --compile-errors $(DATABASE) > pre_parser_messages.ml && \
+ echo "OK. The set of erroneous inputs is correct and irredundant."
+
+# Checking completeness is done by first generating a complete list of
+# erroneous sentences (in pre_parser.messages), then comparing the two
+# .messages files for inclusion.
+complete:
+# Re-generate the list of error messages. This takes time (about 25 seconds).
+ @ $(COMMAND) --list-errors >pre_parser.messages
+ @ echo "Number of error sentences that involve spurious reductions:"
+ @ grep WARNING pre_parser.messages | wc -l
+# Check $(DATABASE) for completeness.
+# We assume pre_parser.messages is up-to-date.
+ @ $(COMMAND) --compare-errors pre_parser.messages --compare-errors $(DATABASE) && \
+ echo "OK. The set of erroneous inputs is complete."
+
+update:
+# Update the auto-comments in $(DATABASE).
+ @ mv -f $(DATABASE) $(DATABASE).bak
+ @ if ! $(COMMAND) --update-errors $(DATABASE).bak > $(DATABASE) ; then \
+ cp $(DATABASE).bak $(DATABASE) ; \
+ fi
+ @ echo "The auto-generated comments in $(DATABASE) have been re-generated."
+
+# ------------------------------------------------------------------------------
+
+# Trying out an input sentence.
+
+# [make interpret] waits for you to interactively type an input sentence,
+# in symbolic syntax (e.g. ALIGNAS LPAREN TYPEDEF_NAME INT). It runs the
+# automaton on this sentence in --trace mode.
+
+# [make interpret_error] is analogous, but expects the sentence to cause
+# an error at the last token, and displays in what state the error takes
+# place.
+
+.PHONY: interpret interpret_error
+
+interpret:
+# Interpret one sentence (interactive).
+ @ $(COMMAND) --trace --interpret
+
+interpret_error:
+# Interpret one error sentence (interactive).
+ @ $(COMMAND) --interpret-error
+
+# ------------------------------------------------------------------------------
+
+# Translating the database of erroneous input sentences to concrete syntax.
+
+# [make concrete] destroys and re-creates the C files in tests/generated/.
+# Once this is done, run [make -C tests/generated] to submit these C files
+# to CompCert, clang and gcc.
+
+.PHONY: concrete
+
+# First, we translate $(DATABASE) to a text file which contains just the
+# erroneous input sentences, nothing else (no comments, no blank lines).
+%.messages.raw: %.messages
+ @ $(COMMAND) --echo-errors $< > $@
+
+# We compile deLexer.ml to native code, because running it as an ocaml script
+# is way too slow. This little utility translates symbolic tokens to their
+# concrete C syntax, e.g., EQ is translated to = and so on.
+deLexer: deLexer.ml
+ @ ocamlopt -o $@ str.cmxa $<
+
+concrete: $(DATABASE).raw deLexer
+# Destroy the C files in tests/generated.
+ @ rm -f tests/generated/*.c
+# Read $(DATABASE).raw, line by line.
+# For each sentence, create a new C file.
+# A sentence takes the form "<start symbol>: SYMBOLS...".
+# We cut the start symbol away,
+# and translate the rest to concrete C syntax using the deLexer.
+# We declare a type name "t", which the de-lexer uses as a type name.
+ @ f=0 ; \
+ while read -r line ; do \
+ filename=`printf "tests/generated/%03d.c" $$f` ; \
+ rm -f $$filename ; \
+ echo "typedef int t;" >> $$filename ; \
+ echo "$$line" \
+ | $(CUT) --fields="1" --delimiter=" " --complement \
+ | ./deLexer \
+ >> $$filename ; \
+ f=$$((f+1)) ; \
+ done < $<
+
+# ------------------------------------------------------------------------------
+
+# Cleaning up.
+
+clean:
+ rm -f pre_parser.automaton
+ rm -f pre_parser.conflicts
+ rm -f pre_parser.messages
+ rm -f $(DATABASE).raw $(DATABASE).bak
+ rm -f deLexer
diff --git a/cparser/Lexer.mll b/cparser/Lexer.mll
index 139bb5aa..58bf2fa6 100644
--- a/cparser/Lexer.mll
+++ b/cparser/Lexer.mll
@@ -268,15 +268,15 @@ rule initial = parse
currentLoc lexbuf)}
| preprocessing_number as s { error lexbuf "invalid numerical constant '%s'@ These characters form a preprocessor number, but not a constant" s;
CONSTANT (Cabs.CONST_INT "0", currentLoc lexbuf) }
- | "'" { let l = char_literal [] lexbuf in
+ | "'" { let l = char_literal lexbuf.lex_start_p [] lexbuf in
CONSTANT (Cabs.CONST_CHAR(false, l),
currentLoc lexbuf) }
- | "L'" { let l = char_literal [] lexbuf in
+ | "L'" { let l = char_literal lexbuf.lex_start_p [] lexbuf in
CONSTANT (Cabs.CONST_CHAR(true, l),
currentLoc lexbuf) }
- | "\"" { let l = string_literal [] lexbuf in
+ | "\"" { let l = string_literal lexbuf.lex_start_p [] lexbuf in
STRING_LITERAL(false, l, currentLoc lexbuf) }
- | "L\"" { let l = string_literal [] lexbuf in
+ | "L\"" { let l = string_literal lexbuf.lex_start_p [] lexbuf in
STRING_LITERAL(true, l, currentLoc lexbuf) }
| "..." { ELLIPSIS(currentLoc lexbuf) }
| "+=" { ADD_ASSIGN(currentLoc lexbuf) }
@@ -361,15 +361,17 @@ and char = parse
| _ as c
{ Int64.of_int (Char.code c) }
-and char_literal accu = parse
- | '\'' { List.rev accu }
+and char_literal startp accu = parse
+ | '\'' { lexbuf.lex_start_p <- startp;
+ List.rev accu }
| '\n' | eof { fatal_error lexbuf "missing terminating \"'\" character" }
- | "" { let c = char lexbuf in char_literal (c :: accu) lexbuf }
+ | "" { let c = char lexbuf in char_literal startp (c :: accu) lexbuf }
-and string_literal accu = parse
- | '\"' { List.rev accu }
+and string_literal startp accu = parse
+ | '\"' { lexbuf.lex_start_p <- startp;
+ List.rev accu }
| '\n' | eof { fatal_error lexbuf "missing terminating '\"' character" }
- | "" { let c = char lexbuf in string_literal (c :: accu) lexbuf }
+ | "" { let c = char lexbuf in string_literal startp (c :: accu) lexbuf }
(* We assume gcc -E syntax but try to tolerate variations. *)
and hash = parse
@@ -423,37 +425,68 @@ and singleline_comment = parse
open Parser
open Aut.GramDefs
- let tokens_stream filename channel : token coq_Stream =
- let tokens = Queue.create () in
+ (* This is the main entry point to the lexer. *)
+
+ let lexer : lexbuf -> Pre_parser.token =
+ fun lexbuf ->
+ if lexbuf.lex_curr_p.pos_cnum = lexbuf.lex_curr_p.pos_bol then
+ initial_linebegin lexbuf
+ else
+ initial lexbuf
+
+ (* [lexer tokens buffer] is a new lexer, which wraps [lexer], and also: 1-
+ records the token stream into the FIFO queue [tokens] and 2- records the
+ start and end positions of the last two tokens in the two-place buffer
+ [buffer] and 3- duplicates identifier tokens into PRE_NAME and
+ VAR/TYPE_NAME. *)
+
+ let lexer tokens buffer : lexbuf -> Pre_parser.token =
let curr_id = ref None in
- let lexer_wraper lexbuf : Pre_parser.token =
+ types_context := init_ctx;
+ fun lexbuf ->
match !curr_id with
| Some id ->
curr_id := None;
let loc = currentLoc lexbuf in
- let res =
+ let token =
if SSet.mem id !types_context then TYPEDEF_NAME (id, ref TypedefId, loc)
else VAR_NAME (id, ref VarId, loc)
in
- Queue.push res tokens;
- res
+ Queue.push token tokens;
+ token
| None ->
- let res =
- if lexbuf.lex_curr_p.pos_cnum = lexbuf.lex_curr_p.pos_bol then
- initial_linebegin lexbuf
- else
- initial lexbuf
- in
- begin match res with
+ let token = lexer lexbuf in
+ begin match token with
| PRE_NAME id -> curr_id := Some id
- | _ -> Queue.push res tokens
+ | _ -> Queue.push token tokens
end;
- res
- in
- let lexbuf = Lexing.from_channel channel in
+ let startp = lexbuf.lex_start_p
+ and endp = lexbuf.lex_curr_p in
+ buffer := ErrorReports.update !buffer (startp, endp);
+ token
+
+ (* [invoke_pre_parser] is in charge of calling the pre_parser. It uses
+ the incremental API, which allows us to do our own error handling. *)
+
+ let invoke_pre_parser filename text lexer buffer =
+ let lexbuf = Lexing.from_string text in
lexbuf.lex_curr_p <- {lexbuf.lex_curr_p with pos_fname = filename; pos_lnum = 1};
- types_context := init_ctx;
- Pre_parser.translation_unit_file lexer_wraper lexbuf;
+ let module I = Pre_parser.MenhirInterpreter in
+ let checkpoint = Pre_parser.Incremental.translation_unit_file()
+ and supplier = I.lexer_lexbuf_to_supplier lexer lexbuf
+ and succeed () = ()
+ and fail checkpoint =
+ Cerrors.fatal_error_raw "%s" (ErrorReports.report text !buffer checkpoint)
+ in
+ I.loop_handle succeed fail supplier checkpoint
+
+ (* [tokens_stream filename text] runs the pre_parser and produces a stream
+ of (appropriately classified) tokens. *)
+
+ let tokens_stream filename text : token coq_Stream =
+ let tokens = Queue.create () in
+ let buffer = ref ErrorReports.Zero in
+ invoke_pre_parser filename text (lexer tokens buffer) buffer;
let rec compute_token_stream () =
let loop t v =
Cons (Coq_existT (t, Obj.magic v), Lazy.from_fun compute_token_stream)
diff --git a/cparser/PackedStructs.ml b/cparser/PackedStructs.ml
index ca6c9da5..c163989e 100644
--- a/cparser/PackedStructs.ml
+++ b/cparser/PackedStructs.ml
@@ -190,7 +190,7 @@ let bswap_write loc env lhs rhs =
let (id, fty) =
lookup_function loc env (sprintf "__builtin_write%d_reversed" bsize) in
let fn = {edesc = EVar id; etyp = fty} in
- let args = [ecast_opt env (TPtr(aty,[])) (eaddrof lhs);
+ let args = [ecast_opt env (TPtr(aty,[])) (eaddrof lhs);
ecast_opt env aty rhs] in
{edesc = ECall(fn, args); etyp = TVoid[]}
end else begin
@@ -216,7 +216,7 @@ let transf_expr loc env ctx e =
let is_byteswapped_ptr ty fieldname =
match unroll env ty with
| TPtr(ty', _) -> is_byteswapped ty' fieldname
- | _ -> false in
+ | _ -> false in
(* Transformation of l-values. Return transformed expr plus
[true] if l-value is a byte-swapped field and [false] otherwise. *)
@@ -232,7 +232,7 @@ let transf_expr loc env ctx e =
let (e1', swap) = lvalue e1 in
({edesc = EBinop(Oindex, e1', e2, tyres); etyp = e.etyp}, swap)
| _ ->
- (texp Val e, false)
+ (texp Val e, false)
and texp ctx e =
match e.edesc with
@@ -401,7 +401,7 @@ let rec transf_globdecls env accu = function
let attr' =
match su with
| Union -> attr
- | Struct -> remove_custom_attributes ["packed";"__packed__"] attr in
+ | Struct -> remove_custom_attributes ["packed";"__packed__"] attr in
transf_globdecls
(Env.add_composite env id (composite_info_decl env su attr'))
({g with gdesc = Gcompositedecl(su, id, attr')} :: accu)
diff --git a/cparser/Parse.ml b/cparser/Parse.ml
index cfa95688..1d92d5a5 100644
--- a/cparser/Parse.ml
+++ b/cparser/Parse.ml
@@ -38,9 +38,22 @@ let parse_transformations s =
s;
!t
+let read_file sourcefile =
+ let ic = open_in sourcefile in
+ let n = in_channel_length ic in
+ let text = really_input_string ic n in
+ close_in ic;
+ text
+
let preprocessed_file transfs name sourcefile =
Cerrors.reset();
- let ic = open_in sourcefile in
+ (* Reading the whole file at once may seem costly, but seems to be
+ the simplest / most robust way of accessing the text underlying
+ a range of positions. This is used when printing an error message.
+ Plus, I note that reading the whole file into memory leads to a
+ speed increase: "make -C test" speeds up by 3 seconds out of 40
+ on my machine. *)
+ let text = read_file sourcefile in
let p =
try
let t = parse_transformations transfs in
@@ -52,7 +65,7 @@ let preprocessed_file transfs name sourcefile =
parsing of the entire file. This is non-negligeabe,
so we cannot use Timing.time2 *)
(fun () ->
- Parser.translation_unit_file inf (Lexer.tokens_stream name ic)) ()
+ Parser.translation_unit_file inf (Lexer.tokens_stream name text)) ()
with
| Parser.Parser.Inter.Fail_pr ->
(* Theoretically impossible : implies inconsistencies
@@ -65,5 +78,4 @@ let preprocessed_file transfs name sourcefile =
with
| Cerrors.Abort ->
[] in
- close_in ic;
if Cerrors.check_errors() then None else Some p
diff --git a/cparser/Rename.ml b/cparser/Rename.ml
index b0dc120f..4b387b0d 100644
--- a/cparser/Rename.ml
+++ b/cparser/Rename.ml
@@ -42,20 +42,20 @@ let enter_public env id =
{ re_id = IdentMap.add id id env.re_id;
re_public = StringMap.add id.name id env.re_public;
re_used = StringSet.add id.name env.re_used }
-
+
let enter_static env id file =
try
let id' = StringMap.find id.name env.re_public in
{ env with re_id = IdentMap.add id id' env.re_id }
with Not_found ->
let file = String.map (fun a -> match a with 'a'..'z' | 'A'..'Z' | '0'..'9' -> a | _ -> '_') file in
- let id' = {id with name = Printf.sprintf "_%s_%s" file id.name} in
+ let id' = {id with name = Printf.sprintf "_%s_%s" file id.name} in
{ re_id = IdentMap.add id id' env.re_id;
re_public = env.re_public;
re_used = StringSet.add id'.name env.re_used }
(* For static or local identifiers, we make up a new name if needed *)
-(* If the same identifier has already been declared,
+(* If the same identifier has already been declared,
don't rename a second time *)
let rename env id =
@@ -94,7 +94,7 @@ let ident env id =
try
IdentMap.find id env.re_id
with Not_found ->
- Cerrors.fatal_error "Internal error: Rename: %s__%d unbound"
+ Cerrors.fatal_error "Internal error: Rename: %s__%d unbound"
id.name id.stamp
let rec typ env = function
@@ -111,7 +111,7 @@ let rec typ env = function
| ty -> ty
and param env (id, ty) =
- if id.name = "" then
+ if id.name = "" then
((id, typ env ty), env)
else
let (id', env') = rename env id in ((id', typ env' ty), env')
@@ -216,7 +216,7 @@ let fundef env f =
fd_body = stmt env2 f.fd_body },
env0 )
-let enum env (id, v, opte) =
+let enum env (id, v, opte) =
let (id', env') = rename env id in
((id', v, optexp env' opte), env')
@@ -269,7 +269,7 @@ let rec reserve_public env file = function
begin match sto with
| Storage_default | Storage_extern -> enter_public env id
| Storage_static -> if !Clflags.option_rename_static then
- enter_static env id file
+ enter_static env id file
else
env
| _ -> assert false
@@ -292,4 +292,4 @@ let program p file =
globdecls
(reserve_public (reserve_builtins()) file p)
[] p
-
+
diff --git a/cparser/StructReturn.ml b/cparser/StructReturn.ml
index 5e5602f3..2c6fd1d2 100644
--- a/cparser/StructReturn.ml
+++ b/cparser/StructReturn.ml
@@ -71,7 +71,7 @@ let classify_param env ty =
| SP_ref_caller -> Param_ref_caller
| _ ->
match sizeof env ty, alignof env ty with
- | Some sz, Some al ->
+ | Some sz, Some al ->
Param_flattened ((sz + 3) / 4, sz, al)
| _, _ ->
Param_unchanged (* should not happen *)
@@ -306,7 +306,7 @@ let rec transf_expr env ctx e =
We used to do a copy optimization:
ctx = Effects: lv = f(...) -> f(&lv, ...)
- but it is not correct in case of overlap (see test/regression/struct12.c)
+ but it is not correct in case of overlap (see test/regression/struct12.c)
Function calls returning a composite by value:
ctx = Effects: lv = f(...) -> newtemp = f(...), lv = newtemp
@@ -521,8 +521,8 @@ let rec transf_funparams loc env params =
let tpx = TPtr(tx', []) in
let ex = { edesc = EVar x; etyp = tpx } in
let estarx = { edesc = EUnop(Oderef, ex); etyp = tx' } in
- ((x, tpx) :: params',
- actions,
+ ((x, tpx) :: params',
+ actions,
IdentMap.add x estarx subst)
| Param_flattened(n, sz, al) ->
let y = new_temp ~name:x.name (ty_buffer n) in
@@ -562,7 +562,7 @@ let transf_fundef env f =
| Ret_value(ty, sz, al) ->
(f.fd_attrib,
ty,
- params,
+ params,
transf_funbody env (subst_stmt subst f.fd_body) None) in
let temps = get_temps() in
{f with fd_attrib = attr1;
diff --git a/cparser/Transform.ml b/cparser/Transform.ml
index 6cdd8a6b..840234b8 100644
--- a/cparser/Transform.ml
+++ b/cparser/Transform.ml
@@ -81,7 +81,7 @@ let op_for_assignop = function
| Odiv_assign -> Odiv
| Omod_assign -> Omod
| Oand_assign -> Oand
- | Oor_assign -> Oor
+ | Oor_assign -> Oor
| Oxor_assign -> Oxor
| Oshl_assign -> Oshl
| Oshr_assign -> Oshr
@@ -118,7 +118,7 @@ let expand_assignop ~read ~write env ctx op l r ty =
ecomma (eassign tmp res) (ecomma (write l tmp) tmp))
let expand_preincrdecr ~read ~write env ctx op l =
- expand_assignop ~read ~write env ctx (assignop_for_incr_decr op)
+ expand_assignop ~read ~write env ctx (assignop_for_incr_decr op)
l (intconst 1L IInt) (unary_conversion env l.etyp)
let expand_postincrdecr ~read ~write env ctx op l =
@@ -147,7 +147,7 @@ let stmt ~expr ?(decl = fun env decl -> assert false) env s =
| Sskip -> s
| Sdo e ->
{s with sdesc = Sdo(expr s.sloc env Effects e)}
- | Sseq(s1, s2) ->
+ | Sseq(s1, s2) ->
{s with sdesc = Sseq(stm s1, stm s2)}
| Sif(e, s1, s2) ->
{s with sdesc = Sif(expr s.sloc env Val e, stm s1, stm s2)}
diff --git a/cparser/Transform.mli b/cparser/Transform.mli
index 57a4737b..a04896a9 100644
--- a/cparser/Transform.mli
+++ b/cparser/Transform.mli
@@ -64,11 +64,11 @@ val fundef : (Env.t -> C.stmt -> C.stmt) -> Env.t -> C.fundef -> C.fundef
val program :
?decl:(Env.t -> C.decl -> C.decl) ->
?fundef:(Env.t -> C.fundef -> C.fundef) ->
- ?composite:(Env.t -> C.struct_or_union ->
- C.ident -> C.attributes -> C.field list ->
+ ?composite:(Env.t -> C.struct_or_union ->
+ C.ident -> C.attributes -> C.field list ->
C.attributes * C.field list) ->
?typedef:(Env.t -> C.ident -> C.typ -> C.typ) ->
- ?enum:(Env.t -> C.ident -> C.attributes -> C.enumerator list ->
+ ?enum:(Env.t -> C.ident -> C.attributes -> C.enumerator list ->
C.attributes * C.enumerator list) ->
?pragma:(Env.t -> string -> string) ->
C.program ->
diff --git a/cparser/Unblock.ml b/cparser/Unblock.ml
index c6646b5c..405cf755 100644
--- a/cparser/Unblock.ml
+++ b/cparser/Unblock.ml
@@ -49,7 +49,7 @@ let rec local_initializer env path init k =
| Init_struct(id, fil) ->
let field_init (fld, i) k =
local_initializer env
- { edesc = EUnop(Odot fld.fld_name, path); etyp = fld.fld_typ }
+ { edesc = EUnop(Odot fld.fld_name, path); etyp = fld.fld_typ }
i k in
List.fold_right field_init fil k
| Init_union(id, fld, i) ->
@@ -80,7 +80,7 @@ let add_inits_expr inits e =
let local_variables = ref ([]: decl list)
let global_variables = ref ([]: decl list)
-(* Note: "const int x = y - 1;" is legal, but we turn it into
+(* Note: "const int x = y - 1;" is legal, but we turn it into
"const int x; x = y - 1;", which is not. Therefore, remove
top-level 'const' attribute. Also remove it on element type of
array type. *)
@@ -128,7 +128,7 @@ let rec expand_expr islocal env e =
let e2' =
match op with
| Ocomma | Ologand | Ologor -> expand_expr islocal env e2
- (* Make sure the initializers of [e2] are performed in
+ (* Make sure the initializers of [e2] are performed in
sequential order, i.e. just before [e2] but after [e1]. *)
| _ -> expand e2 in
{edesc = EBinop(op, e1', e2', ty); etyp = e.etyp}
@@ -148,7 +148,7 @@ let rec expand_expr islocal env e =
e'
| ECall(e1, el) ->
{edesc = ECall(expand e1, List.map expand el); etyp = e.etyp}
- in
+ in
let e' = expand e in ecommalist !inits e'
(* Elimination of compound literals within an initializer. *)
@@ -185,7 +185,7 @@ let debug_ty =
let debug_annot kind args =
{ sloc = no_loc;
- sdesc = Sdo {
+ sdesc = Sdo {
etyp = TVoid [];
edesc = ECall({edesc = EVar debug_id; etyp = debug_ty},
intconst kind IInt :: args)
@@ -276,12 +276,12 @@ let rec unblock_stmt env ctx ploc s =
| Sseq(s1, s2) ->
{s with sdesc = Sseq(unblock_stmt env ctx ploc s1,
unblock_stmt env ctx s1.sloc s2)}
- | Sif(e, s1, s2) ->
+ | Sif(e, s1, s2) ->
add_lineno ctx ploc s.sloc
{s with sdesc = Sif(expand_expr true env e,
unblock_stmt env ctx s.sloc s1,
unblock_stmt env ctx s.sloc s2)}
- | Swhile(e, s1) ->
+ | Swhile(e, s1) ->
add_lineno ctx ploc s.sloc
{s with sdesc = Swhile(expand_expr true env e,
unblock_stmt env ctx s.sloc s1)}
@@ -301,7 +301,7 @@ let rec unblock_stmt env ctx ploc s =
add_lineno ctx ploc s.sloc
{s with sdesc = Sswitch(expand_expr true env e,
unblock_stmt env ctx s.sloc s1)}
- | Slabeled(lbl, s1) ->
+ | Slabeled(lbl, s1) ->
add_lineno ctx ploc s.sloc
{s with sdesc = Slabeled(lbl, unblock_stmt env ctx s.sloc s1)}
| Sgoto lbl ->
@@ -309,7 +309,7 @@ let rec unblock_stmt env ctx ploc s =
| Sreturn None ->
add_lineno ctx ploc s.sloc s
| Sreturn (Some e) ->
- add_lineno ctx ploc s.sloc
+ add_lineno ctx ploc s.sloc
{s with sdesc = Sreturn(Some (expand_expr true env e))}
| Sblock sl ->
let ctx' =
@@ -327,7 +327,7 @@ let rec unblock_stmt env ctx ploc s =
| Sasm(attr, template, outputs, inputs, clob) ->
let expand_asm_operand (lbl, cstr, e) =
(lbl, cstr, expand_expr true env e) in
- add_lineno ctx ploc s.sloc
+ add_lineno ctx ploc s.sloc
{s with sdesc = Sasm(attr, template,
List.map expand_asm_operand outputs,
List.map expand_asm_operand inputs, clob)}
diff --git a/cparser/deLexer.ml b/cparser/deLexer.ml
new file mode 100644
index 00000000..00308e4b
--- /dev/null
+++ b/cparser/deLexer.ml
@@ -0,0 +1,135 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* François Pottier, INRIA Paris-Rocquencourt *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation, either version 2 of the License, or *)
+(* (at your option) any later version. This file is also distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+(* [delex] converts a terminal symbol (represented as a symbolic string) to a
+ concrete string, which the lexer would accept. *)
+
+(* This can be used to convert an error sentence produced by Menhir to C code. *)
+
+(* [delex] should be maintained in sync with the lexer! *)
+
+let delex (symbol : string) : string =
+ match symbol with
+ | "ALIGNAS" -> "_Alignas"
+ | "ALIGNOF" -> "__alignof__" (* use the gcc-compatible form *)
+ | "UNDERSCORE_BOOL" -> "_Bool"
+ | "ASM" -> "__asm"
+ | "ATTRIBUTE" -> "__attribute"
+ | "BUILTIN_VA_ARG" -> "__builtin_va_arg"
+ | "CONST" -> "const"
+ | "INLINE" -> "inline"
+ | "PACKED" -> "__packed__"
+ | "RESTRICT" -> "restrict"
+ | "SIGNED" -> "signed"
+ | "VOLATILE" -> "volatile"
+ | "AUTO" -> "auto"
+ | "BREAK" -> "break"
+ | "CASE" -> "case"
+ | "CHAR" -> "char"
+ | "CONTINUE" -> "continue"
+ | "DEFAULT" -> "default"
+ | "DO" -> "do"
+ | "DOUBLE" -> "double"
+ | "ELSE" -> "else"
+ | "ENUM" -> "enum"
+ | "EXTERN" -> "extern"
+ | "FLOAT" -> "float"
+ | "FOR" -> "for"
+ | "GOTO" -> "goto"
+ | "IF" -> "if"
+ | "INT" -> "int"
+ | "LONG" -> "long"
+ | "REGISTER" -> "register"
+ | "RETURN" -> "return"
+ | "SHORT" -> "short"
+ | "SIZEOF" -> "sizeof"
+ | "STATIC" -> "static"
+ | "STRUCT" -> "struct"
+ | "SWITCH" -> "switch"
+ | "TYPEDEF" -> "typedef"
+ | "UNION" -> "union"
+ | "UNSIGNED" -> "unsigned"
+ | "VOID" -> "void"
+ | "WHILE" -> "while"
+ | "TYPEDEF_NAME" -> "t" (* this should be a type name *)
+ | "VAR_NAME" -> "x" (* this should be a variable name *)
+ | "CONSTANT" -> "42"
+ | "STRING_LITERAL" -> "\"\""
+ | "ELLIPSIS" -> "..."
+ | "ADD_ASSIGN" -> "+="
+ | "SUB_ASSIGN" -> "-="
+ | "MUL_ASSIGN" -> "*="
+ | "DIV_ASSIGN" -> "/="
+ | "MOD_ASSIGN" -> "%="
+ | "OR_ASSIGN" -> "|="
+ | "AND_ASSIGN" -> "&="
+ | "XOR_ASSIGN" -> "^="
+ | "LEFT_ASSIGN" -> "<<="
+ | "RIGHT_ASSIGN" -> ">>="
+ | "LEFT" -> "<<"
+ | "RIGHT" -> ">>"
+ | "EQEQ" -> "=="
+ | "NEQ" -> "!="
+ | "LEQ" -> "<="
+ | "GEQ" -> ">="
+ | "EQ" -> "="
+ | "LT" -> "<"
+ | "GT" -> ">"
+ | "INC" -> "++"
+ | "DEC" -> "--"
+ | "PTR" -> "->"
+ | "PLUS" -> "+"
+ | "MINUS" -> "-"
+ | "STAR" -> "*"
+ | "SLASH" -> "/"
+ | "PERCENT" -> "%"
+ | "BANG" -> "!"
+ | "ANDAND" -> "&&"
+ | "BARBAR" -> "||"
+ | "AND" -> "&"
+ | "BAR" -> "|"
+ | "HAT" -> "^"
+ | "QUESTION" -> "?"
+ | "COLON" -> ":"
+ | "TILDE" -> "~"
+ | "LBRACE" -> "{"
+ | "RBRACE" -> "}"
+ | "LBRACK" -> "["
+ | "RBRACK" -> "]"
+ | "LPAREN" -> "("
+ | "RPAREN" -> ")"
+ | "SEMICOLON" -> ";"
+ | "COMMA" -> ","
+ | "DOT" -> "."
+ | "PRAGMA" -> "#pragma \n"
+ | "EOF" -> "" (* this should be ok *)
+ | _ -> raise Not_found (* this should not happen *)
+
+(* De-lexing a sentence. *)
+
+let delex sentence =
+ let symbols = Str.split (Str.regexp " ") sentence in
+ let symbols = List.map delex symbols in
+ List.iter (fun symbol ->
+ Printf.printf "%s " symbol
+ ) symbols
+
+(* This file is meant to be run as a script. We read one line from the standard
+ input channel and delex it. *)
+
+let () =
+ delex (input_line stdin);
+ print_newline()
+
diff --git a/cparser/handcrafted.messages b/cparser/handcrafted.messages
new file mode 100644
index 00000000..5a3fbd71
--- /dev/null
+++ b/cparser/handcrafted.messages
@@ -0,0 +1,4700 @@
+#######################################################################
+# #
+# The Compcert verified compiler #
+# #
+# François Pottier, INRIA Paris-Rocquencourt #
+# Jacques-Henri Jourdan, INRIA Paris-Rocquencourt #
+# #
+# Copyright Institut National de Recherche en Informatique et en #
+# Automatique. All rights reserved. This file is distributed #
+# under the terms of the INRIA Non-Commercial License Agreement. #
+# #
+#######################################################################
+
+# This file contains a complete list of sentences that cause the pre_parser to
+# detect an error.
+
+# ------------------------------------------------------------------------------
+
+# WORKFLOW:
+
+# The workflow (when and how this file should be modified; which tools exist
+# to maintain it; etc.) is documented in GNUmakefile in this directory.
+
+# ------------------------------------------------------------------------------
+
+# FILE FORMAT:
+
+# Each sentence is followed with a hand-written error message, which must be
+# preceded and followed by a blank line.
+
+# If several sentences should share a single error message, they can be grouped,
+# with no whitespace between them.
+
+# Hand-written comments, which begin with a single hash character, like this, are
+# preserved when this file is updated by Menhir. Auto-generated comments, which
+# begin with two hash characters, are re-generated by Menhir.
+
+# An error message is basically free-form text. It cannot contain a blank line.
+# Occurrences of the special form $i, where i is a number (an index into the
+# parser's stack), will be replaced by the fragment of the source text that
+# corresponds to this stack entry. It is the user's responsibility to ensure
+# that the index i is within range, i.e., falls into the known suffix of the
+# stack. Note that this index is 0-based and counts from right to left, i.e.,
+# $0 refers to the RIGHTMOST stack cell.
+
+# The replacement text for $i can be quite long (up to one line, basically)
+# so one should avoid using several $i on a single line, unless one knows
+# a smaller bound on their length.
+
+# ------------------------------------------------------------------------------
+
+# CONVENTIONS ABOUT THE FORM AND STYLE OF ERROR MESSAGES:
+
+# If possible, start with "Ill-formed foo", where "foo" is the thing that we
+# are trying to recognize, i.e., the left-hand side of our items. This is not
+# always possible, as we do not always know with certainty what we are trying
+# to rcognize.
+
+# If possible, say "Up to this point, a bar has been recognized", and show it,
+# by using $i.
+
+# If the current state was reached via spurious reductions, print a hypothesis,
+# of the form "If this bar is complete, then".
+
+# Show a list of the permitted continuations: "at this point, one of the
+# following is expected:". The list should be complete, although unlikely
+# continuations can be omitted. A continuation can be just one symbol, or
+# a sequence of symbols.
+
+# ------------------------------------------------------------------------------
+
+# NOTE ON THE CONTEXT OF AN EXPRESSION:
+
+# A C expression occurs in many contexts.
+
+# Although we could distinguish between these contexts statically, by adding a
+# phantom parameter to all of the nonterminal symbols that encode expressions,
+# that would be quite heavy: the number of states in the automaton would grow
+# quite dramatically.
+
+# Instead, we prefer to dynamically distinguish between these contexts. We do
+# so in a very simple way: we give %on_error_reduce declarations to Menhir (in
+# pre_parser.mly) so as to replace certain error actions with reduction actions.
+# Thus, when Menhir finds an error and whatever is on the stack can be reduced
+# to an expression, the automaton will reduce it to an expression. By carrying
+# out this extra (spurious) reduction, the automaton ends up in a state where
+# sufficient static context is available to tell what should follow. Thus,
+# without doing anything special beyond giving these directives, we are able
+# to sidestep the issue of the context of expressions.
+
+# Of course, we must be careful to say (in our error messages) "IF this
+# expression (or list of expressions) is complete, THEN the following
+# continuations are expected". The weakness of this approach is that if the
+# expression is NOT complete (in the user's mind), then we do not help the user
+# understand how the expression should be completed. Our error message exhibits
+# a bias towards ending expressions.
+
+# OTHER USES OF %on_error_reduce:
+
+# We apply this technique also to attribute_specifier_list and declarator. This
+# means, intuitively, that when we find an error at a position where an
+# attribute specifier list and/or a declarator could be complete, but could also
+# be continued, we implicitly assume it is complete. Again, this must be taken
+# into account in messages where an attribute_specifier_list or a declarator has
+# just been recognized.
+
+# ABOUT STRICT VERSUS LAX INTERPRETATIONS OF %on_error_reduce:
+
+# There are two ways in which Menhir could implement %on_error_reduce. In the
+# strict interpretation, an extra reduction takes place only if this is the
+# only reduction that can take place in this state. (Thus, we do not choose
+# between two interpretations of the past.) In the lax interpretation, an extra
+# reduction can take place even if some other reduction is enabled. (In a
+# situation where two extra reductions compete, neither takes place.)
+
+# Adopting the lax interpretation adds more extra reductions, causing some
+# error states to disappear. For instance, this state, where we have a read
+# a VAR_NAME which could be either the beginning of an expression or the
+# beginning of a labeled statement:
+
+# general_identifier -> PRE_NAME VAR_NAME . [ COLON ]
+# primary_expression -> PRE_NAME VAR_NAME . [ <lots of tokens> ]
+
+# In the strict interpretation, no extra reduction is permitted here, because
+# two reductions are enabled. In the lax interpretation, because we have
+# declared %on_error_reduce primary_expression, the second production is
+# reduced. Hence, we implicitly assume that this name forms an expression
+# (as opposed to a label). This is slightly inaccurate (we lose completeness)
+# but removes an error state that is rather unpleasant.
+
+# Even though it may sound "bad" to arbitrarily force one reduction among
+# several possible reductions, one should keep in mind that an arbitrary
+# choice is already made for us by the user when he "chooses" the incorrect
+# token. Indeed, depending on which incorrect token is used, we may fall
+# within or outside of a lookahead set, so we may make different reduction
+# choices, and give different error messages. So, we shouldn't feel too bad
+# about forcing a few more arbitrary choices. This is actually more regular,
+# in a sense.
+
+# In another instance of this phenomemon, there is a rather tricky state,
+# where we have read "int f" at the toplevel, and we do not know whether this
+# will be a variable definition (declarator) or a function definition
+# (direct_declarator). In the lax interpretation, because we have declared
+# %on_error_reduce declarator, we implicitly assume this must be the
+# beginning of a declarator. Again, we lose completeness (we will not suggest
+# that an opening parenthesis would have been accepted) but this makes our
+# life easier, and does not sound too bad.
+
+# Another instance is a state where we have read "enum foo". This could be a
+# complete enum_specifier, or it could be continued with an opening brace. If it
+# is complete, though, we lack static context to tell what should come after it.
+# Using lax %on_error_reduce enum_specifier allows us to force a reduction,
+# (thus forgetting that an opening brace would have been permitted) and to move
+# to another state where more contextual information is available. As noted
+# above, this reduction can already take place naturally, depending on the
+# lookahead token, so we are only adding more cases where it takes place.
+
+# The lax %on_error_reduce is used also to deal with a family of error states
+# where we have recognized a complete statement which could be continued with an
+# ELSE branch. These error states are difficult to explain: although we can
+# definitely say that ELSE is permitted, we have difficulty telling what else is
+# permitted, by lack of static context. We could recover this static information
+# by introducing a phantom parameter on statements, but that would be heavy. We
+# just cut a corner and use %on_error_reduce to view this as a complete
+# statement. Thus, we abandon the possibility that the statement could be
+# continued with ELSE: our error message will not mention it. Again, this makes
+# our life easier, and does not sound too bad.
+
+# We also apply %on_error_reduce to specifier_qualifier_list and
+# option(abstract_declarator(type_name)). This allows us to recognize
+# a valid type name, even when this type name could be continued. This
+# allows us to go back to a state where we see the opening parenthesis
+# before the type name (there is always one), which allows us to
+# explain why we request a closing parenthesis. This is a bit costly,
+# as there are quite a few similar error states to deal with here.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN INT XOR_ASSIGN
+##
+## Ends in an error in state: 299.
+##
+## attribute_specifier -> ALIGNAS LPAREN type_name . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNAS LPAREN type_name
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 152, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name)
+## In state 301, spurious reduction of production option(abstract_declarator(type_name)) ->
+## In state 307, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name))
+##
+
+# Maybe the type name was not complete, but we have reduced anyway
+# and assume it is complete. Thus, we expect a closing parenthesis.
+# This example comes in several variants, because there are several
+# places in the grammar where LPAREN type_name RPAREN appears.
+
+# gcc, clang: like us, expect a closing parenthesis.
+
+Ill-formed _Alignas qualifier.
+Up to this point, a type name has been recognized:
+ $0
+If this type name is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF LPAREN VOID XOR_ASSIGN
+##
+## Ends in an error in state: 311.
+##
+## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## unary_expression -> ALIGNOF LPAREN type_name . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNOF LPAREN type_name
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 152, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name)
+## In state 301, spurious reduction of production option(abstract_declarator(type_name)) ->
+## In state 307, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name))
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF LPAREN VOID XOR_ASSIGN
+##
+## Ends in an error in state: 378.
+##
+## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## unary_expression -> SIZEOF LPAREN type_name . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## SIZEOF LPAREN type_name
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 152, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name)
+## In state 301, spurious reduction of production option(abstract_declarator(type_name)) ->
+## In state 307, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name))
+##
+
+Ill-formed use of $2.
+Up to this point, a type name has been recognized:
+ $0
+If this type name is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME VAR_NAME COMMA VOID XOR_ASSIGN
+##
+## Ends in an error in state: 342.
+##
+## postfix_expression -> BUILTIN_VA_ARG LPAREN assignment_expression COMMA type_name . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## BUILTIN_VA_ARG LPAREN assignment_expression COMMA type_name
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 152, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name)
+## In state 301, spurious reduction of production option(abstract_declarator(type_name)) ->
+## In state 307, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name))
+##
+
+Ill-formed use of __builtin_va_arg.
+Up to this point, a type name has been recognized:
+ $0
+If this type name is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ INC LPAREN VOID XOR_ASSIGN
+##
+## Ends in an error in state: 372.
+##
+## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN type_name
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 152, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name)
+## In state 301, spurious reduction of production option(abstract_declarator(type_name)) ->
+## In state 307, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name))
+##
+
+# gcc simply says it expects a closing parenthesis,
+# but clang says it expects a closing parenthesis and an opening brace.
+
+Ill-formed compound literal.
+Up to this point, a type name has been recognized:
+ $0
+If this type name is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN VOID XOR_ASSIGN
+##
+## Ends in an error in state: 375.
+##
+## cast_expression -> LPAREN type_name . RPAREN cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN type_name
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 152, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name)
+## In state 301, spurious reduction of production option(abstract_declarator(type_name)) ->
+## In state 307, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name))
+##
+
+# gcc and clang say they expect a closing parenthesis.
+
+Up to this point, a type name has been recognized:
+ $0
+If this type name is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 309.
+##
+## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ]
+## attribute_specifier -> ALIGNAS LPAREN argument_expression_list . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNAS LPAREN argument_expression_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 133, spurious reduction of production argument_expression_list -> assignment_expression
+##
+
+# We are trying to recognize an alignas specifier.
+# We have already recognized at least one argument_expression.
+# We expect either "COMMA assignment_expression" or RPAREN.
+# But, in CompCert, only one expression is allowed as part of ALIGNAS (see Elab.ml).
+# So we say we expect RPAREN.
+
+# And we say we have recognized "an expression", instead of "a list of expressions".
+# Not sure whether this is a good idea.
+
+# gcc, clang: like us, expect a closing parenthesis.
+
+Ill-formed _Alignas qualifier.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN INT LBRACK RPAREN
+##
+## Ends in an error in state: 235.
+##
+## direct_abstract_declarator -> option(direct_abstract_declarator) LBRACK option(type_qualifier_list) . optional(assignment_expression,RBRACK) [ RPAREN LPAREN LBRACK COMMA ]
+## type_qualifier_list -> option(type_qualifier_list) . type_qualifier_noattr [ VOLATILE TILDE STRING_LITERAL STAR SIZEOF RESTRICT RBRACK PRE_NAME PLUS PACKED MINUS LPAREN INC DEC CONSTANT CONST BUILTIN_VA_ARG BANG ATTRIBUTE AND ALIGNOF ALIGNAS ]
+## type_qualifier_list -> option(type_qualifier_list) . attribute_specifier [ VOLATILE TILDE STRING_LITERAL STAR SIZEOF RESTRICT RBRACK PRE_NAME PLUS PACKED MINUS LPAREN INC DEC CONSTANT CONST BUILTIN_VA_ARG BANG ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## option(direct_abstract_declarator) LBRACK option(type_qualifier_list)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LBRACK RPAREN
+##
+## Ends in an error in state: 252.
+##
+## direct_declarator -> direct_declarator LBRACK option(type_qualifier_list) . optional(assignment_expression,RBRACK) [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+## type_qualifier_list -> option(type_qualifier_list) . type_qualifier_noattr [ VOLATILE TILDE STRING_LITERAL STAR SIZEOF RESTRICT RBRACK PRE_NAME PLUS PACKED MINUS LPAREN INC DEC CONSTANT CONST BUILTIN_VA_ARG BANG ATTRIBUTE AND ALIGNOF ALIGNAS ]
+## type_qualifier_list -> option(type_qualifier_list) . attribute_specifier [ VOLATILE TILDE STRING_LITERAL STAR SIZEOF RESTRICT RBRACK PRE_NAME PLUS PACKED MINUS LPAREN INC DEC CONSTANT CONST BUILTIN_VA_ARG BANG ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## direct_declarator LBRACK option(type_qualifier_list)
+##
+
+# We are trying to recognize an array declarator.
+# We have seen the opening bracket and (maybe) some type qualifiers.
+# We are expecting more type qualifiers, or an expression, or a closing bracket.
+
+# gcc, clang: both say they expect an expression (and nothing else).
+# Yet, they do accept a closing bracket.
+
+# If in the first sentence we replace the invalid token with a type qualifier, such as CONST,
+# gcc and clang both say:
+# error: type qualifier used in array declarator outside of function prototype
+# On the other hand, in the second sentence, they accept a qualifier.
+
+# We choose not to mention the possibility of a type qualifier (which may be
+# illegal here anyway).
+
+Ill-formed array declarator.
+At this point, one of the following is expected:
+ an expression, followed with a closing bracket ']'; or
+ a closing bracket ']'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN INT LPAREN INT COMMA ELLIPSIS XOR_ASSIGN
+##
+## Ends in an error in state: 263.
+##
+## direct_abstract_declarator -> LPAREN option(context_parameter_type_list) . RPAREN [ RPAREN LPAREN LBRACK COMMA ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN option(context_parameter_type_list)
+##
+translation_unit_file: ALIGNAS LPAREN INT LBRACK RBRACK LPAREN INT COMMA ELLIPSIS XOR_ASSIGN
+##
+## Ends in an error in state: 246.
+##
+## direct_abstract_declarator -> direct_abstract_declarator LPAREN option(context_parameter_type_list) . RPAREN [ RPAREN LPAREN LBRACK COMMA ]
+##
+## The known suffix of the stack is as follows:
+## direct_abstract_declarator LPAREN option(context_parameter_type_list)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT COMMA ELLIPSIS XOR_ASSIGN
+##
+## Ends in an error in state: 280.
+##
+## direct_declarator -> direct_declarator LPAREN context_parameter_type_list . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## direct_declarator LPAREN context_parameter_type_list
+##
+
+# Unlikely error, since only the ELLIPSIS allows us to tell that
+# the parameter list is finished.
+
+At this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN INT LPAREN LPAREN RPAREN COMMA
+##
+## Ends in an error in state: 261.
+##
+## direct_abstract_declarator -> LPAREN save_context abstract_declarator(type_name) . RPAREN [ RPAREN LPAREN LBRACK COMMA ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN save_context abstract_declarator(type_name)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 254, spurious reduction of production abstract_declarator(type_name) -> direct_abstract_declarator
+##
+#
+# The first LPAREN in this example must be the beginning of an abstract_declarator.
+# It leads us into a state where we do not yet know the meaning of the opening parenthesis:
+# direct_abstract_declarator -> LPAREN . abstract_declarator RPAREN [ RPAREN LPAREN LBRACK ]
+# direct_abstract_declarator -> LPAREN . in_context(option(parameter_type_list)) RPAREN [ RPAREN LPAREN LBRACK ]
+# i.e. (a) this could be the opening parenthesis in a pair of parentheses,
+# or (d) this could be the opening parenthesis in a function type.
+# The second LPAREN takes us again into the same state.
+# The RPAREN allows us to recognize that we have a function type of no parameters (d).
+# Hence, LPAREN RPAREN forms a direct_abstract_declarator.
+# At this point, the status of the first LPAREN is still undetermined (regular paren,
+# or beginning of a function type?) but that is not a problem for us.
+#
+# This case is simplified by giving a phantom context parameter to abstract_declarator.
+# Here, we know we are in the context of a type_name or direct_abstract_declarator,
+# so RPAREN is allowed next.
+# If we were in the context of a parameter_declaration, COMMA would be allowed next.
+#
+
+# gcc and clang simply request a closing parenthesis.
+
+Up to this point, an abstract declarator has been recognized:
+ $0
+At this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN INT LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 302.
+##
+## direct_abstract_declarator -> LPAREN . save_context abstract_declarator(type_name) RPAREN [ RPAREN LPAREN LBRACK ]
+## direct_abstract_declarator -> LPAREN . option(context_parameter_type_list) RPAREN [ RPAREN LPAREN LBRACK ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN
+##
+
+# gcc and clang both say they want a closing parenthesis.
+# This seems a bit extreme.
+
+An opening parenthesis '(' has been recognized.
+At this point, one of the following is expected:
+ an abstract declarator,
+ if this parenthesis is a delimiter; or
+ a list of parameter declarations,
+ if this parenthesis is the beginning of a function declarator.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 229.
+##
+## direct_abstract_declarator -> LPAREN . save_context abstract_declarator(type_name) RPAREN [ RPAREN LPAREN LBRACK COMMA ]
+## direct_abstract_declarator -> LPAREN . option(context_parameter_type_list) RPAREN [ RPAREN LPAREN LBRACK COMMA ]
+## direct_declarator -> LPAREN . save_context declarator RPAREN [ RPAREN PACKED LPAREN LBRACK COMMA ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN
+##
+
+# Analogous to the above, but has a third item.
+
+An opening parenthesis '(' has been recognized.
+At this point, one of the following is expected:
+ an abstract declarator or a declarator,
+ if this parenthesis is a delimiter; or
+ a list of parameter declarations,
+ if this parenthesis is the beginning of a function declarator.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN VOLATILE ADD_ASSIGN
+##
+## Ends in an error in state: 294.
+##
+## option(type_qualifier_list) -> type_qualifier_list . [ VOLATILE RESTRICT PACKED CONST ATTRIBUTE ALIGNAS ]
+## specifier_qualifier_list(type_name) -> type_qualifier_list . typedef_name option(type_qualifier_list) [ STAR RPAREN LPAREN LBRACK ]
+## specifier_qualifier_list(type_name) -> type_qualifier_list . type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) [ STAR RPAREN LPAREN LBRACK ]
+##
+## The known suffix of the stack is as follows:
+## type_qualifier_list
+##
+
+# We are trying to recognize a specifier-qualifier-list, and have not yet seen
+# a type specifier, which is why we know the list is not finished.
+
+# clang says it expects a type.
+# gcc says the missing type defaults to int, and expects a closing parenthesis.
+
+Ill-formed type name.
+At this point, one of the following is expected:
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 150.
+##
+## attribute_specifier -> ALIGNAS LPAREN . argument_expression_list RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+## attribute_specifier -> ALIGNAS LPAREN . type_name RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNAS LPAREN
+##
+
+# This one seems easy. We have recognized ALIGNAS LPAREN, and nothing that makes sense beyond that.
+
+# clang and gcc say they expect an expression.
+
+Ill-formed _Alignas qualifier.
+At this point, one of the following is expected:
+ an expression; or
+ a type name.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS XOR_ASSIGN
+##
+## Ends in an error in state: 149.
+##
+## attribute_specifier -> ALIGNAS . LPAREN argument_expression_list RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+## attribute_specifier -> ALIGNAS . LPAREN type_name RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNAS
+##
+
+# Fingers in the nose.
+
+Ill-formed _Alignas qualifier.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 354.
+##
+## gcc_attribute_list -> gcc_attribute_list COMMA . gcc_attribute [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## gcc_attribute_list COMMA
+##
+
+# We are expecting a gcc_attribute. This symbol is nullable, so
+# RPAREN and COMMA are permitted too, but we can ignore this
+# possibility in the error message (why would someone use an
+# empty attribute?).
+
+# clang and gcc say they expect a closing parenthesis.
+
+Ill-formed attribute specifier.
+At this point, a gcc attribute is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 352.
+##
+## attribute_specifier -> ATTRIBUTE LPAREN LPAREN gcc_attribute_list RPAREN . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ATTRIBUTE LPAREN LPAREN gcc_attribute_list RPAREN
+##
+
+Ill-formed attribute specifier.
+At this point, a second closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 351.
+##
+## attribute_specifier -> ATTRIBUTE LPAREN LPAREN gcc_attribute_list . RPAREN RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+## gcc_attribute_list -> gcc_attribute_list . COMMA gcc_attribute [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## ATTRIBUTE LPAREN LPAREN gcc_attribute_list
+##
+
+# We have a seen a (non-empty) attribute list, so we expect either
+# a COMMA or a closing LPAREN LPAREN.
+
+# gcc/clang say they expect a closing parenthesis.
+
+Ill-formed attribute specifier.
+At this point, one of the following is expected:
+ a comma ',', followed with a gcc attribute; or
+ two closing parentheses '))'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME COMMA PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 347.
+##
+## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ]
+## gcc_attribute -> gcc_attribute_word LPAREN typedef_name COMMA argument_expression_list . RPAREN [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## gcc_attribute_word LPAREN typedef_name COMMA argument_expression_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 133, spurious reduction of production argument_expression_list -> assignment_expression
+##
+
+# We know for sure that we are parsing a gcc attribute.
+# A (non-empty) list of expressions has been read.
+
+# gcc/clang say they want a closing parenthesis.
+
+Ill-formed gcc attribute.
+Up to this point, a list of expressions has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 346.
+##
+## gcc_attribute -> gcc_attribute_word LPAREN typedef_name COMMA . argument_expression_list RPAREN [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## gcc_attribute_word LPAREN typedef_name COMMA
+##
+
+# gcc/clang agree.
+
+Ill-formed gcc attribute.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 345.
+##
+## gcc_attribute -> gcc_attribute_word LPAREN typedef_name . COMMA argument_expression_list RPAREN [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## gcc_attribute_word LPAREN typedef_name
+##
+
+# gcc and clang complain about the TYPEDEF_NAME, not sure why.
+
+Ill-formed gcc attribute.
+At this point, a comma ',' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 45.
+##
+## gcc_attribute -> gcc_attribute_word LPAREN . option(argument_expression_list) RPAREN [ RPAREN COMMA ]
+## gcc_attribute -> gcc_attribute_word LPAREN . typedef_name COMMA argument_expression_list RPAREN [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## gcc_attribute_word LPAREN
+##
+
+# gcc and clang just say they expect an expression.
+# There is kind of hack in the pre_parser, here.
+# Without going into the details, we should just say we expect a list of attribute arguments.
+
+Ill-formed gcc attribute.
+At this point, a list of expressions is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 44.
+##
+## gcc_attribute -> gcc_attribute_word . [ RPAREN COMMA ]
+## gcc_attribute -> gcc_attribute_word . LPAREN option(argument_expression_list) RPAREN [ RPAREN COMMA ]
+## gcc_attribute -> gcc_attribute_word . LPAREN typedef_name COMMA argument_expression_list RPAREN [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## gcc_attribute_word
+##
+
+# gcc and clang say they expect a closing parenthesis (as usual).
+
+Ill-formed gcc attribute specifier.
+Up to this point, an attribute has been recognized:
+ $0
+At this point, one of the following is expected:
+ an opening parenthesis '(',
+ followed with a list of parameters for this attribute; or
+ a comma ',',
+ followed with another attribute; or
+ a closing parenthesis ')'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 37.
+##
+## attribute_specifier -> ATTRIBUTE LPAREN LPAREN . gcc_attribute_list RPAREN RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ATTRIBUTE LPAREN LPAREN
+##
+
+# A non-empty attribute list is expected.
+# Hence, an attribute is expected.
+# (The gcc documentation says a list of attributes can be empty, but
+# since an attribute can be empty too, this creates a conflict.)
+
+# clang and gcc want a closing parenthesis, as usual (sigh)...
+
+Ill-formed gcc attribute specifier.
+At this point, a gcc attribute is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 36.
+##
+## attribute_specifier -> ATTRIBUTE LPAREN . LPAREN gcc_attribute_list RPAREN RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ATTRIBUTE LPAREN
+##
+
+Ill-formed gcc attribute specifier.
+At this point, a second opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ATTRIBUTE XOR_ASSIGN
+##
+## Ends in an error in state: 35.
+##
+## attribute_specifier -> ATTRIBUTE . LPAREN LPAREN gcc_attribute_list RPAREN RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ATTRIBUTE
+##
+
+Ill-formed gcc attribute specifier.
+At this point, two opening parentheses '((' are expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 362.
+##
+## enumerator_list -> enumerator_list COMMA . declare_varname(enumerator) [ RBRACE COMMA ]
+## option(COMMA) -> COMMA . [ RBRACE ]
+##
+## The known suffix of the stack is as follows:
+## enumerator_list COMMA
+##
+
+# We omit the possibility of a closing brace.
+
+# gcc and clang say they want an identifier.
+# Indeed, an enumerator must begin with an identifier.
+
+Ill-formed enumeration specifier.
+At this point, an enumerator is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME EQ CONSTANT SEMICOLON
+##
+## Ends in an error in state: 361.
+##
+## enum_specifier -> ENUM attribute_specifier_list option(other_identifier) LBRACE enumerator_list . option(COMMA) RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+## enumerator_list -> enumerator_list . COMMA declare_varname(enumerator) [ RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## ENUM attribute_specifier_list option(other_identifier) LBRACE enumerator_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 57, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 366, spurious reduction of production enumerator -> enumeration_constant EQ conditional_expression
+## In state 363, spurious reduction of production declare_varname(enumerator) -> enumerator
+## In state 370, spurious reduction of production enumerator_list -> declare_varname(enumerator)
+##
+#
+# At first sight, it seems that the last enumerator that we have recognized
+# could be of the form either "enumeration_constant" or
+# "enumeration_constant EQ constant_expression".
+#
+# However, a moment's thought reveals that it cannot be of the first form,
+# otherwise the syntax error would have been detected in this state:
+# enumerator -> enumeration_constant . [ RBRACE COMMA ]
+# enumerator -> enumeration_constant . EQ constant_expression [ RBRACE COMMA ]
+# To see this, try the sentence ENUM LBRACE VAR_NAME XOR_ASSIGN.
+#
+# So, the last enumerator must be of the second form, which means it would be safe
+# for us to say "an expression has just been recognized".
+#
+# On the other hand, we cannot show the expression that has just been recognized;
+# we can only show the enumerator list $0.
+#
+# We omit the fact that a comma is allowed just before the closing brace.
+
+Ill-formed enumeration specifier.
+Up to this point, a list of enumerators has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing brace '}' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME EQ XOR_ASSIGN
+##
+## Ends in an error in state: 365.
+##
+## enumerator -> enumeration_constant EQ . conditional_expression [ RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## enumeration_constant EQ
+##
+
+Ill-formed enumeration specifier.
+At this point, a constant expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 364.
+##
+## enumerator -> enumeration_constant . [ RBRACE COMMA ]
+## enumerator -> enumeration_constant . EQ conditional_expression [ RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## enumeration_constant
+##
+
+# Here, both clang and gcc give an incomplete diagnostic message.
+
+Ill-formed enumeration specifier.
+At this point, one of the following is expected:
+ an equals sign '=', followed with a constant expression; or
+ a comma ',', followed with an enumerator; or
+ a closing brace '}'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ENUM LBRACE XOR_ASSIGN
+##
+## Ends in an error in state: 359.
+##
+## enum_specifier -> ENUM attribute_specifier_list option(other_identifier) LBRACE . enumerator_list option(COMMA) RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ENUM attribute_specifier_list option(other_identifier) LBRACE
+##
+
+# gcc says it expects an identifier.
+# clang says it expects a closing brace (which seems incorrect).
+
+Ill-formed enumeration specifier.
+At this point, an enumerator is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ENUM XOR_ASSIGN
+##
+## Ends in an error in state: 357.
+##
+## enum_specifier -> ENUM attribute_specifier_list . option(other_identifier) LBRACE enumerator_list option(COMMA) RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+## enum_specifier -> ENUM attribute_specifier_list . general_identifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ENUM attribute_specifier_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 34, spurious reduction of production attribute_specifier_list ->
+##
+
+# Here, both clang and gcc give an incomplete diagnostic message.
+
+Ill-formed enumeration specifier.
+At this point, one of the following is expected:
+ an attribute specifier; or
+ an identifier; or
+ an opening brace '{'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 53.
+##
+## postfix_expression -> LPAREN . type_name RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## primary_expression -> LPAREN . expression RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## unary_expression -> ALIGNOF LPAREN . type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNOF LPAREN
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 26.
+##
+## postfix_expression -> LPAREN . type_name RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## primary_expression -> LPAREN . expression RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## unary_expression -> SIZEOF LPAREN . type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## SIZEOF LPAREN
+##
+
+# Tricky because we could be looking at the beginning of a compound
+# literal, in which case we expect a type name! But that would be a
+# use of SIZEOF or ALIGNOF without parentheses, which is very unlikely.
+# So, we omit this possibility.
+
+# gcc/clang do the same.
+
+Ill-formed use of $1.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF XOR_ASSIGN
+##
+## Ends in an error in state: 52.
+##
+## unary_expression -> ALIGNOF . unary_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## unary_expression -> ALIGNOF . LPAREN type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## ALIGNOF
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF XOR_ASSIGN
+##
+## Ends in an error in state: 21.
+##
+## unary_expression -> SIZEOF . unary_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## unary_expression -> SIZEOF . LPAREN type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## SIZEOF
+##
+
+# Let's not reveal that _Alignof and sizeof can be used without parentheses.
+
+# gcc and clang say they expect an expression, which seems both surprising
+# (they don't request a parenthesis) and incomplete (they don't allow a type name).
+
+Ill-formed use of $0.
+At this point, an opening parenthesis '(' is expected,
+followed with an expression or a type name.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 340.
+##
+## postfix_expression -> BUILTIN_VA_ARG LPAREN assignment_expression . COMMA type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## BUILTIN_VA_ARG LPAREN assignment_expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+##
+
+Ill-formed use of $2.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a comma ',' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 341.
+##
+## postfix_expression -> BUILTIN_VA_ARG LPAREN assignment_expression COMMA . type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## BUILTIN_VA_ARG LPAREN assignment_expression COMMA
+##
+
+Ill-formed use of $3.
+At this point, a type name is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 49.
+##
+## postfix_expression -> BUILTIN_VA_ARG LPAREN . assignment_expression COMMA type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## BUILTIN_VA_ARG LPAREN
+##
+
+Ill-formed use of $1.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG XOR_ASSIGN
+##
+## Ends in an error in state: 48.
+##
+## postfix_expression -> BUILTIN_VA_ARG . LPAREN assignment_expression COMMA type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## BUILTIN_VA_ARG
+##
+
+Ill-formed use of $0.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ DEC XOR_ASSIGN
+##
+## Ends in an error in state: 46.
+##
+## unary_expression -> DEC . unary_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## DEC
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ INC XOR_ASSIGN
+##
+## Ends in an error in state: 31.
+##
+## unary_expression -> INC . unary_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## INC
+##
+
+Ill-formed expression.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ INC LPAREN INT RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 373.
+##
+## postfix_expression -> LPAREN type_name RPAREN . LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN type_name RPAREN
+##
+
+# Here, we seem to be certain that this must be the beginning of a
+# compound literal, so an opening brace is expected.
+# However, it is quite likely that the user does not even know about
+# compound literals, so the error took place earlier.
+# Maybe the user intended to write a cast expression, and he forgot
+# to open one more parenthesis before the one we see here.
+# Or maybe the name that we classified as a type was intended to be a variable.
+
+# gcc says an expression is expected, which seems incorrect.
+# clang says "expected '{' in compound literal".
+
+Ill-formed expression.
+Up to this point, a type name in parentheses has been recognized:
+ $2 $1 $0
+If this is the beginning of a compound literal,
+ then at this point, an opening brace '{' is expected.
+If this is intended to be the beginning of a cast expression,
+ then perhaps an opening parenthesis '(' was forgotten earlier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ INC LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 32.
+##
+## postfix_expression -> LPAREN . type_name RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## primary_expression -> LPAREN . expression RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN
+##
+
+# gcc and clang expect an expression.
+# We could choose to omit the first possibility, too.
+
+Ill-formed expression.
+At this point, one of the following is expected:
+ a type name (if this is the beginning of a compound literal); or
+ an expression.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 337.
+##
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+## primary_expression -> LPAREN expression . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+# Since we are saying "if this expression is complete",
+# there seems to be no need to say that this expression
+# can be continued with a comma and another expression.
+# So, let's just say a closing parenthesis is expected.
+
+Up to this point, a parenthesis '(' and an expression have been recognized:
+ $1 $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN LBRACE PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 334.
+##
+## initializer_list -> initializer_list . COMMA option(designation) c_initializer [ RBRACE COMMA ]
+## postfix_expression -> LPAREN type_name RPAREN LBRACE initializer_list . option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN type_name RPAREN LBRACE initializer_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 327, spurious reduction of production c_initializer -> assignment_expression
+## In state 333, spurious reduction of production initializer_list -> option(designation) c_initializer
+##
+
+# Let's ignore the fact that a comma can precede a closing brace.
+
+Ill-formed compound literal.
+Up to this point, a list of initializers has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing brace '}' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN LBRACE XOR_ASSIGN
+##
+## Ends in an error in state: 313.
+##
+## postfix_expression -> LPAREN type_name RPAREN LBRACE . initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN type_name RPAREN LBRACE
+##
+
+# gcc and clang say an expression is expected, which is incomplete.
+
+Ill-formed compound literal.
+At this point, an initializer is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 376.
+##
+## cast_expression -> LPAREN type_name RPAREN . cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## postfix_expression -> LPAREN type_name RPAREN . LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN type_name RPAREN
+##
+
+# clang and gcc expect an expression.
+
+Ill-formed expression.
+Up to this point, a type name in parentheses has been recognized:
+ $2 $1 $0
+At this point, one of the following is expected:
+ an expression, if this is a type cast; or
+ an opening brace '{', if this is a compound literal.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 28.
+##
+## cast_expression -> LPAREN . type_name RPAREN cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## postfix_expression -> LPAREN . type_name RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## primary_expression -> LPAREN . expression RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN
+##
+
+# clang and gcc expect an expression.
+
+Ill-formed expression.
+An opening parenthesis '(' has just been recognized.
+At this point, one of the following is expected:
+ a type name, if this is a type cast or a compound literal; or
+ an expression, if this is a parenthesized expression.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ TILDE XOR_ASSIGN
+##
+## Ends in an error in state: 56.
+##
+## unary_expression -> unary_operator . cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## unary_operator
+##
+
+# clang and gcc expect an expression.
+
+Ill-formed use of the unary operator $0.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME AND XOR_ASSIGN
+##
+## Ends in an error in state: 116.
+##
+## and_expression -> and_expression AND . equality_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION HAT COMMA COLON BARBAR BAR ANDAND AND ]
+##
+## The known suffix of the stack is as follows:
+## and_expression AND
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME ANDAND XOR_ASSIGN
+##
+## Ends in an error in state: 105.
+##
+## logical_and_expression -> logical_and_expression ANDAND . inclusive_or_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION COMMA COLON BARBAR ANDAND ]
+##
+## The known suffix of the stack is as follows:
+## logical_and_expression ANDAND
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME BAR XOR_ASSIGN
+##
+## Ends in an error in state: 107.
+##
+## inclusive_or_expression -> inclusive_or_expression BAR . exclusive_or_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION COMMA COLON BARBAR BAR ANDAND ]
+##
+## The known suffix of the stack is as follows:
+## inclusive_or_expression BAR
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME BARBAR XOR_ASSIGN
+##
+## Ends in an error in state: 128.
+##
+## logical_or_expression -> logical_or_expression BARBAR . logical_and_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION COMMA COLON BARBAR ]
+##
+## The known suffix of the stack is as follows:
+## logical_or_expression BARBAR
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME HAT XOR_ASSIGN
+##
+## Ends in an error in state: 109.
+##
+## exclusive_or_expression -> exclusive_or_expression HAT . and_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION HAT COMMA COLON BARBAR BAR ANDAND ]
+##
+## The known suffix of the stack is as follows:
+## exclusive_or_expression HAT
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LT XOR_ASSIGN
+##
+## Ends in an error in state: 99.
+##
+## relational_expression -> relational_expression relational_operator . shift_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION NEQ LT LEQ HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ]
+##
+## The known suffix of the stack is as follows:
+## relational_expression relational_operator
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME NEQ XOR_ASSIGN
+##
+## Ends in an error in state: 113.
+##
+## equality_expression -> equality_expression equality_operator . relational_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION NEQ HAT EQEQ COMMA COLON BARBAR BAR ANDAND AND ]
+##
+## The known suffix of the stack is as follows:
+## equality_expression equality_operator
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME PLUS XOR_ASSIGN
+##
+## Ends in an error in state: 92.
+##
+## additive_expression -> additive_expression additive_operator . multiplicative_expression [ SEMICOLON RPAREN RIGHT RBRACK RBRACE QUESTION PLUS NEQ MINUS LT LEQ LEFT HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ]
+##
+## The known suffix of the stack is as follows:
+## additive_expression additive_operator
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME RIGHT XOR_ASSIGN
+##
+## Ends in an error in state: 81.
+##
+## shift_expression -> shift_expression shift_operator . additive_expression [ SEMICOLON RPAREN RIGHT RBRACK RBRACE QUESTION NEQ LT LEQ LEFT HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ]
+##
+## The known suffix of the stack is as follows:
+## shift_expression shift_operator
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME STAR XOR_ASSIGN
+##
+## Ends in an error in state: 86.
+##
+## multiplicative_expression -> multiplicative_expression multiplicative_operator . cast_expression [ STAR SLASH SEMICOLON RPAREN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT NEQ MINUS LT LEQ LEFT HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ]
+##
+## The known suffix of the stack is as follows:
+## multiplicative_expression multiplicative_operator
+##
+
+# clang and gcc expect an expression.
+
+Ill-formed use of the binary operator $0.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME XOR_ASSIGN XOR_ASSIGN
+##
+## Ends in an error in state: 77.
+##
+## assignment_expression -> unary_expression assignment_operator . assignment_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## unary_expression assignment_operator
+##
+
+# clang and gcc expect an expression.
+
+Ill-formed use of the assignment operator $0.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 135.
+##
+## argument_expression_list -> argument_expression_list COMMA . assignment_expression [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## argument_expression_list COMMA
+##
+
+# Here, we could say more about the context if we parameterized
+# argument_expression_list with a context. For the moment, let
+# us just say that an expression is expected at this point.
+
+# clang and gcc expect an expression.
+
+Ill-formed list of expressions.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME DOT XOR_ASSIGN
+##
+## Ends in an error in state: 141.
+##
+## postfix_expression -> postfix_expression DOT . general_identifier [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## postfix_expression DOT
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME PTR XOR_ASSIGN
+##
+## Ends in an error in state: 62.
+##
+## postfix_expression -> postfix_expression PTR . general_identifier [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## postfix_expression PTR
+##
+
+# clang and gcc expect an identifier.
+
+Ill-formed use of the dereferencing operator $0.
+At this point, the name of a struct or union member is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LBRACK PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 138.
+##
+## expression -> expression . COMMA assignment_expression [ RBRACK COMMA ]
+## postfix_expression -> postfix_expression LBRACK expression . RBRACK [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## postfix_expression LBRACK expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+# We know for sure that an array subscript expression has begun, and
+# a closing bracket is expected (if the expression is complete).
+# The expression could also be completed with a COMMA, but there is
+# no reason to mention that -- it can be viewed as part of the
+# hypothesis "if the expression is complete".
+
+Ill-formed expression.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing bracket ']' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LBRACK XOR_ASSIGN
+##
+## Ends in an error in state: 137.
+##
+## postfix_expression -> postfix_expression LBRACK . expression RBRACK [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## postfix_expression LBRACK
+##
+
+Ill-formed expression.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 134.
+##
+## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ]
+## option(argument_expression_list) -> argument_expression_list . [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## argument_expression_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 133, spurious reduction of production argument_expression_list -> assignment_expression
+##
+
+Up to this point, a list of expressions has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 64.
+##
+## postfix_expression -> postfix_expression LPAREN . option(argument_expression_list) RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## postfix_expression LPAREN
+##
+
+# gcc and clang expect an expression: this is incomplete.
+
+Ill-formed expression.
+At this point, a list of expressions,
+followed with a closing parenthesis ')', is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION PRE_NAME VAR_NAME COLON XOR_ASSIGN
+##
+## Ends in an error in state: 125.
+##
+## conditional_expression -> logical_or_expression QUESTION expression COLON . conditional_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## logical_or_expression QUESTION expression COLON
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION XOR_ASSIGN
+##
+## Ends in an error in state: 103.
+##
+## conditional_expression -> logical_or_expression QUESTION . expression COLON conditional_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## logical_or_expression QUESTION
+##
+
+Ill-formed conditional expression.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 121.
+##
+## conditional_expression -> logical_or_expression QUESTION expression . COLON conditional_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ]
+## expression -> expression . COMMA assignment_expression [ COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## logical_or_expression QUESTION expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+# gcc and clang simply expect a colon.
+
+Ill-formed conditional expression.
+Up to this point, an expression, '?', and an expression have been recognized:
+ $2
+ $1
+ $0
+If the last expression is complete,
+then at this point, a colon ':' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: PACKED LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 381.
+##
+## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ]
+## attribute_specifier -> PACKED LPAREN argument_expression_list . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PACKED LPAREN argument_expression_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 133, spurious reduction of production argument_expression_list -> assignment_expression
+##
+
+Ill-formed $2 attribute.
+Up to this point, a list of expressions has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: PACKED LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 17.
+##
+## attribute_specifier -> PACKED LPAREN . argument_expression_list RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PACKED LPAREN
+##
+
+# clang expects a "parameter declarator" (?).
+# gcc expects "declaration specifiers or ‘...’".
+# Which is incorrect, since an ellipsis is rejected here.
+
+Ill-formed $1 attribute.
+At this point, a list of expressions is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 22.
+##
+## primary_expression -> PRE_NAME . VAR_NAME [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+
+Ill-formed expression.
+The following identifier is used as a variable, but has been defined as a type:
+ $0
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: PACKED XOR_ASSIGN
+##
+## Ends in an error in state: 16.
+##
+## attribute_specifier -> PACKED . LPAREN argument_expression_list RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PACKED
+##
+
+# This one seems important, since CompCert currently does not support __packed__
+# without an argument.
+
+Ill-formed $0 attribute.
+At this point, an opening parenthesis '(',
+followed with a possibly empty list of expressions,
+is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: SEMICOLON XOR_ASSIGN
+##
+## Ends in an error in state: 399.
+##
+## translation_unit -> translation_unit . external_declaration [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PRAGMA PACKED LONG INT INLINE FLOAT EXTERN EOF ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## translation_unit -> translation_unit . SEMICOLON [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PRAGMA PACKED LONG INT INLINE FLOAT EXTERN EOF ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## translation_unit_file -> translation_unit . EOF [ # ]
+##
+## The known suffix of the stack is as follows:
+## translation_unit
+##
+translation_unit_file: XOR_ASSIGN
+##
+## Ends in an error in state: 0.
+##
+## translation_unit_file' -> . translation_unit_file [ # ]
+##
+## The known suffix of the stack is as follows:
+##
+##
+# The king of all syntax errors: an error in the initial state.
+
+# Anyway, we are at the toplevel.
+
+# clang and gcc want an identifier or an opening parenthesis, which is way incomplete.
+
+At this point, one of the following is expected:
+ a function definition; or
+ a declaration; or
+ a pragma; or
+ the end of the file.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: TYPEDEF PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 384.
+##
+## declaration_specifiers_typedef -> TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: PRE_NAME TYPEDEF_NAME TYPEDEF XOR_ASSIGN
+##
+## Ends in an error in state: 393.
+##
+## declaration_specifiers_typedef -> typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type)
+##
+translation_unit_file: VOLATILE TYPEDEF PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 406.
+##
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: VOLATILE PRE_NAME TYPEDEF_NAME TYPEDEF XOR_ASSIGN
+##
+## Ends in an error in state: 412.
+##
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type)
+##
+translation_unit_file: TYPEDEF INT XOR_ASSIGN
+##
+## Ends in an error in state: 386.
+##
+## declaration_specifiers_typedef -> TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: INT TYPEDEF XOR_ASSIGN
+##
+## Ends in an error in state: 397.
+##
+## declaration_specifiers_typedef -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: VOLATILE TYPEDEF INT XOR_ASSIGN
+##
+## Ends in an error in state: 408.
+##
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: VOLATILE INT TYPEDEF XOR_ASSIGN
+##
+## Ends in an error in state: 416.
+##
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name)
+##
+
+# We have begun a type definition (a.k.a. declaration_specifiers_typedef).
+# To complete this type definition,
+# we expect a possibly-empty list declaration_specifiers_no_type?,
+# or declaration_specifiers_no_typedef_name?,
+# (depending on which example sentence one looks at)
+# which (in all cases) means a list of:
+# storage class specifiers,
+# type qualifiers,
+# function specifiers (i.e., INLINE, but I suspect this is illegal here).
+# and (in the second case) also includes:
+# type_specifier_no_typedef_name (e.g., INT, etc.).
+# After this type definition,
+# we expect typedef_declarator_list? SEMICOLON.
+
+# We omit the possibility of giving another type specifier, such as INT.
+
+# We could omit the possibility of a storage class specifier and a type qualifier.
+
+# gcc and clang expect identifier or '(', which is correct but incomplete (and too low-level).
+
+Ill-formed type definition.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a list of declarators, followed with a semicolon ';'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: TYPEDEF XOR_ASSIGN
+##
+## Ends in an error in state: 7.
+##
+## declaration_specifiers_typedef -> TYPEDEF list(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> TYPEDEF list(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## TYPEDEF list(declaration_specifier_no_type)
+##
+translation_unit_file: VOLATILE TYPEDEF XOR_ASSIGN
+##
+## Ends in an error in state: 404.
+##
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type)
+##
+
+# We have seen the TYPEDEF keyword, and possibly some declaration_specifiers_no_type.
+# We expect:
+# possibly more declaration_specifiers_no_type?,
+# which means a list of:
+# storage class specifiers,
+# type qualifiers,
+# function specifiers (i.e., INLINE, but I suspect this is illegal here).
+# followed with a type specifier.
+
+# gcc and clang expect identifier or '('.
+
+Ill-formed type definition.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE XOR_ASSIGN
+##
+## Ends in an error in state: 217.
+##
+## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ]
+## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 209, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr
+##
+
+# Analogous to the above, except we are in the context of a parameter declaration,
+# and (obviously) have not seen a TYPEDEF keyword.
+# We expect possibly more declaration_specifiers_no_type?
+# followed with a type specifier.
+# I think it is OK to forbid INLINE here.
+
+# (At this point, our declaration_specifiers will be complete, and the
+# continuation would be declarator, abstract_declarator, or nothing,
+# which implies COMMA or RPAREN. Let's not mention that, and describe
+# things only up to the (required) type specifier.)
+
+Ill-formed parameter declaration.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 391.
+##
+## declaration_specifiers(declaration(external_declaration)) -> typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 410.
+##
+## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: INT XOR_ASSIGN
+##
+## Ends in an error in state: 395.
+##
+## declaration_specifiers(declaration(external_declaration)) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: VOLATILE INT XOR_ASSIGN
+##
+## Ends in an error in state: 414.
+##
+## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+
+# We have seen a TYPEDEF_NAME or a primitive type specifier,
+# and possibly some declaration_specifiers_no_type.
+# We expect:
+# possibly more declaration_specifier_no_type or declaration_specifier_no_typedef_name,
+# which means a list of:
+# storage class specifiers,
+# type qualifiers,
+# function specifiers,
+# possibly type specifiers,
+# possibly followed with a TYPEDEF keyword.
+
+# Note that we can get here via spurious reductions (e.g. "enum foo" can
+# be considered a complete enum_specifier, hence a complete type_specifier).
+# Thus, the list of permitted continuations below can be slightly incomplete:
+# an opening brace could be used to continue "enum foo".
+
+# Let's NOT mention the possibility of placing TYPEDEF somewhere in the middle.
+# This means we pretend to be definitely in a declaration_specifiers(declaration).
+# In other words, we are in the beginning of a declaration of function definition
+# (we do not know which, yet).
+
+# Let's also ignore the possibility of writing INLINE *after* the result type,
+# which sounds awkward.
+
+# If this declaration_specifiers is complete,
+# then we expect:
+# init_declarator_list? SEMICOLON if this is a declaration;
+# declarator if this is a function definition.
+# (followed with a function body)
+
+# gcc and clang expect identifier or '(', which is very low-level.
+
+# We simplify "a list of init declarators" to "an init declarator".
+
+# Our message is probably too elaborate; we could omit certain elements,
+# or try to simplify our description in the case of a function definition.
+
+Ill-formed declaration or function definition.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ an init declarator,
+ if this is a declaration; or
+ a declarator,
+ followed with a function body,
+ if this is a function definition.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 196.
+##
+## declaration_specifiers(parameter_declaration) -> typedef_name list(declaration_specifier_no_type) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 219.
+##
+## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT XOR_ASSIGN
+##
+## Ends in an error in state: 202.
+##
+## declaration_specifiers(parameter_declaration) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE INT XOR_ASSIGN
+##
+## Ends in an error in state: 221.
+##
+## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+
+# Analogous to the above situation, except this time, we are in the
+# context of a parameter declaration (as opposed to a declaration or
+# function definition). This rules out 'typedef' and 'inline', for real,
+# I think. Also, this changes the continuation.
+
+# We have seen a type specifier,
+# and possibly some declaration_specifiers_no_type.
+# We expect:
+# possibly more declaration_specifier_no_type or declaration_specifier_no_typedef_name,
+# which means a list of:
+# storage class specifiers,
+# type qualifiers.
+# (omitting the possibility of another type specifier)
+
+# If this declaration_specifiers(parameter_declaration) is complete,
+# then we expect:
+# declarator
+# abstract_declarator
+# or neither, which means that the parameter_declaration is over,
+# which means we expect COMMA or RPAREN.
+
+# We could say that $1 has been interpreted as a type specifier,
+# although I don't know if that would help.
+
+# clang expects ')'.
+# gcc expects ‘;’, ‘,’ or ‘)’. The semicolon seems incorrect.
+
+Ill-formed parameter declaration.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a declarator; or
+ an abstract declarator; or
+ a comma ',', followed with a parameter declaration; or
+ a closing parenthesis ')'.
+
+# # ------------------------------------------------------------------------------
+
+translation_unit_file: VOLATILE XOR_ASSIGN
+##
+## Ends in an error in state: 402.
+##
+## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 209, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr
+##
+
+# We have seen some specifiers or qualifiers. We have probably seen at least
+# one of them, otherwise we would be at the top level of the file, and the
+# error would be signaled in another state, I think.
+
+# This could be the beginning of a declaration or function definition.
+
+# It could in theory be the beginning of a type definition, but only
+# if the TYPEDEF keyword is not in front, which sounds awkward, so
+# let's ignore that.
+
+# Again, we ignore the possibility of INLINE when not in front, as it
+# is awkward.
+
+# We have not yet seen a type specifier, so we must see it, regardless
+# of whether this is a declaration or function definition.
+
+Ill-formed declaration or function definition.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE VOLATILE XOR_ASSIGN
+##
+## Ends in an error in state: 512.
+##
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 209, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr
+##
+# Identical to the previous one, except we are not at the top level,
+# so we know this cannot be the beginning of a function definition.
+
+Ill-formed declaration.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME TYPEDEF_NAME VOLATILE XOR_ASSIGN
+##
+## Ends in an error in state: 509.
+##
+## declaration_specifiers(declaration(block_item)) -> typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 514.
+##
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE INT XOR_ASSIGN
+##
+## Ends in an error in state: 511.
+##
+## declaration_specifiers(declaration(block_item)) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE VOLATILE INT XOR_ASSIGN
+##
+## Ends in an error in state: 516.
+##
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+
+# This is analogous to the error sentence TYPEDEF_NAME VOLATILE XOR_ASSIGN,
+# except we are inside a block, instead of at the top level, so we
+# know that this cannot be the beginning of a function definition.
+
+# This is an interesting situation where, by using phantom parameters,
+# we have forced a distinction between two states that would NOT be
+# distinguished in a canonical automaton. Indeed, the lookahead sets
+# are the same: the states would be the same if the phantom parameters
+# were erased.
+
+# Assuming that the list of init declarators is nonempty, we say that
+# we expect an init declarator, instead of saying that we expect a
+# possibly empty, comma-separated list of init declarators, followed
+# with a semicolon.
+
+# We do not distinguish the case where we have seen a primitive type
+# specifier, so another primitive type specifier would be OK.
+
+# gcc and clang expect identifier or '(', which is incomplete and low-level.
+
+Ill-formed declaration.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ an init declarator.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 177.
+##
+## struct_declaration -> specifier_qualifier_list(struct_declaration) . option(struct_declarator_list) SEMICOLON [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT RESTRICT RBRACE PRE_NAME PACKED LONG INT FLOAT ENUM DOUBLE CONST CHAR ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## specifier_qualifier_list(struct_declaration)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 163, spurious reduction of production specifier_qualifier_list(struct_declaration) -> typedef_name option(type_qualifier_list)
+##
+
+# We have (spuriously) recognized a specifier_qualifier_list,
+# part of a struct_declaration.
+# Thus, we expect:
+# more type qualifiers or specifiers (part of the specifier_qualifier_list), or
+# a struct declarator, or
+# a semicolon.
+
+# The nonterminal symbol is officially called struct-declaration.
+# But this means struct *or union*,
+# and it is a declaration of a struct or union *member*.
+
+# It seems good to show the type specifier that we have just read (if
+# there is one), as it could be a variable name that has been
+# mis-classified as a type name, I suppose.
+
+# clang's message is analogous to ours.
+# gcc expects identifier or '('.
+
+Ill-formed struct declaration.
+Up to this point,
+a list of type qualifiers and type specifiers has been recognized:
+ $0
+If this list is complete, then
+at this point, one of the following is expected:
+ a struct declarator; or
+ a semicolon ';'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE LONG COLON CONSTANT RPAREN
+##
+## Ends in an error in state: 282.
+##
+## option(struct_declarator_list) -> struct_declarator_list . [ SEMICOLON ]
+## struct_declarator_list -> struct_declarator_list . COMMA struct_declarator [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## struct_declarator_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 57, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 287, spurious reduction of production struct_declarator -> option(declarator) COLON conditional_expression
+## In state 289, spurious reduction of production struct_declarator_list -> struct_declarator
+##
+
+# We have seen a non-empty struct_declarator_list.
+
+# clang expects a semicolon, like us.
+# gcc expects too many things (incorrect).
+
+Ill-formed struct declaration.
+Up to this point, a list of struct declarators has been recognized:
+ $0
+If this list is complete,
+then at this point, a semicolon ';' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE INT COLON XOR_ASSIGN
+##
+## Ends in an error in state: 286.
+##
+## struct_declarator -> option(declarator) COLON . conditional_expression [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## option(declarator) COLON
+##
+
+Ill-formed struct declarator.
+At this point, a constant expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE INT PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 283.
+##
+## struct_declarator_list -> struct_declarator_list COMMA . struct_declarator [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## struct_declarator_list COMMA
+##
+
+Ill-formed struct declaration.
+At this point, a struct declarator is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE INT PRE_NAME VAR_NAME RPAREN
+##
+## Ends in an error in state: 288.
+##
+## option(declarator) -> declarator . [ COLON ]
+## struct_declarator -> declarator . [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## declarator
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 250, spurious reduction of production declarator_noattrend -> direct_declarator
+## In state 255, spurious reduction of production attribute_specifier_list ->
+## In state 256, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list
+##
+
+# Assuming the declarator so far is complete, we expect
+# either COLON constant_expression (part of this struct_declarator)
+# or something that follows this struct_declarator.
+
+# clang expects ';'.
+# gcc expects many things, including '}', which seems incorrect.
+
+Ill-formed struct declaration.
+Up to this point, a declarator has been recognized:
+ $0
+If this declarator is complete,
+then at this point, one of the following is expected:
+ a colon ':', followed with a constant expression; or
+ a comma ',', followed with a struct declarator; or
+ a semicolon ';'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE VOLATILE ADD_ASSIGN
+##
+## Ends in an error in state: 171.
+##
+## option(type_qualifier_list) -> type_qualifier_list . [ VOLATILE RESTRICT PACKED CONST ATTRIBUTE ALIGNAS ]
+## specifier_qualifier_list(struct_declaration) -> type_qualifier_list . typedef_name option(type_qualifier_list) [ STAR SEMICOLON PRE_NAME LPAREN COLON ]
+## specifier_qualifier_list(struct_declaration) -> type_qualifier_list . type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN COLON ]
+##
+## The known suffix of the stack is as follows:
+## type_qualifier_list
+##
+
+# A list of qualifiers has been read.
+# (Probably a nonempty list, otherwise we would be in a different state.)
+# We expect a type specifier, or one more qualifier.
+
+Ill-formed struct declaration.
+At this point, one of the following is expected:
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION LBRACE XOR_ASSIGN
+##
+## Ends in an error in state: 160.
+##
+## struct_declaration_list -> struct_declaration_list . struct_declaration [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT RESTRICT RBRACE PRE_NAME PACKED LONG INT FLOAT ENUM DOUBLE CONST CHAR ATTRIBUTE ALIGNAS ]
+## struct_or_union_specifier -> struct_or_union attribute_specifier_list option(other_identifier) LBRACE struct_declaration_list . RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## struct_or_union attribute_specifier_list option(other_identifier) LBRACE struct_declaration_list
+##
+
+# gcc and clang do not seem prepared to accept a struct or union with
+# zero members, so they request a type specifier or qualifier.
+
+At this point, one of the following is expected:
+ a struct declaration; or
+ a closing brace '}'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: UNION XOR_ASSIGN
+##
+## Ends in an error in state: 157.
+##
+## struct_or_union_specifier -> struct_or_union attribute_specifier_list . option(other_identifier) LBRACE struct_declaration_list RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+## struct_or_union_specifier -> struct_or_union attribute_specifier_list . general_identifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## struct_or_union attribute_specifier_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 156, spurious reduction of production attribute_specifier_list ->
+##
+
+# gcc expects '{'.
+# clang gives a mysterious message: "declaration of anonymous union must be a definition".
+# Adding TYPEDEF in front does not help.
+
+Ill-formed struct or union specifier.
+At this point, one of the following is expected:
+ an attribute specifier; or
+ an identifier; or
+ an opening brace '{', followed with a list of members.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 259.
+##
+## direct_declarator -> LPAREN save_context declarator . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN save_context declarator
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 250, spurious reduction of production declarator_noattrend -> direct_declarator
+## In state 255, spurious reduction of production attribute_specifier_list ->
+## In state 256, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list
+##
+
+Up to this point, an opening parenthesis and a declarator have been recognized:
+ $1 $0
+If this declarator is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 183.
+##
+## direct_declarator -> LPAREN save_context . declarator RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## LPAREN save_context
+##
+
+# clang and gcc expect identifier or '(', as usual.
+
+Ill-formed direct declarator.
+At this point, a declarator is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 276.
+##
+## identifier_list -> identifier_list . COMMA PRE_NAME VAR_NAME [ RPAREN COMMA ]
+## option(identifier_list) -> identifier_list . [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## identifier_list
+##
+
+Ill-formed K&R function definition.
+Up to this point, a list of identifiers has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 189.
+##
+## context_parameter_type_list -> save_context . parameter_type_list save_context [ RPAREN ]
+## direct_declarator -> direct_declarator LPAREN save_context . option(identifier_list) RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## direct_declarator LPAREN save_context
+##
+
+# Ignore K&R syntax, just request ANSI syntax.
+
+# Ignore the distinction between parameter-type-list and parameter-list.
+
+# clang expects a parameter declarator (which is incomplete).
+# gcc expects declaration specifiers or ‘...’ (which is incorrect).
+
+Ill-formed function definition.
+At this point, a list of parameter declarations,
+followed with a closing parenthesis ')', is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT STAR RPAREN
+##
+## Ends in an error in state: 186.
+##
+## declarator_noattrend -> list(pointer1) STAR option(type_qualifier_list) . direct_declarator [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LONG LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+## list(pointer1) -> list(pointer1) STAR option(type_qualifier_list) . [ STAR ]
+## type_qualifier_list -> option(type_qualifier_list) . type_qualifier_noattr [ VOLATILE STAR RESTRICT PRE_NAME PACKED LPAREN CONST ATTRIBUTE ALIGNAS ]
+## type_qualifier_list -> option(type_qualifier_list) . attribute_specifier [ VOLATILE STAR RESTRICT PRE_NAME PACKED LPAREN CONST ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## list(pointer1) STAR option(type_qualifier_list)
+##
+
+# If the pointer isn't finished, we expect
+# one more type qualifier; or
+# one more '*', possibly followed with type qualifiers.
+# If the pointer is finished, then we expect a direct declarator.
+
+# If may seem tempting to declare %on_error_reduce "list(pointer1)", but
+# that would clash with %on_error_reduce "abstract_declarator(type_name)".
+# There are states where both reductions are enabled, and Menhir currently
+# refuses to choose between them.
+
+# clang and gcc expect identifier or '(', as usual.
+
+Ill-formed declarator.
+At this point, one of the following is expected:
+ a type qualifier; or
+ a star '*', possibly followed with type qualifiers; or
+ a direct declarator.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: TYPEDEF INT PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 528.
+##
+## option(typedef_declarator_list) -> typedef_declarator_list . [ SEMICOLON ]
+## typedef_declarator_list -> typedef_declarator_list . COMMA typedef_declarator [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## typedef_declarator_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 250, spurious reduction of production declarator_noattrend -> direct_declarator
+## In state 255, spurious reduction of production attribute_specifier_list ->
+## In state 256, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list
+## In state 532, spurious reduction of production declare_typename(declarator) -> declarator
+## In state 531, spurious reduction of production typedef_declarator -> declare_typename(declarator)
+## In state 533, spurious reduction of production typedef_declarator_list -> typedef_declarator
+##
+
+# Because attribute_specifier_list, declarator and declarator_noattrend have been marked
+# %on_error_reduce, we perform several spurious reductions and end up here.
+# Which is good, because the context is clear.
+
+# If the attribute_specifier_list or declarator was not finished, then we could have accepted:
+# an attribute specifier.
+# a opening bracket '['.
+# an opening parenthesis '('.
+
+# As far as the C grammar is concerned, typedef_declarator is just declarator.
+
+# clang says "invalid token after top level declarator", which seems vague.
+# gcc expects a list of many things...
+
+Up to this point, a list of declarators has been recognized:
+ $0
+If this list is complete,
+then at this point, a semicolon ';' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: TYPEDEF INT PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 529.
+##
+## typedef_declarator_list -> typedef_declarator_list COMMA . typedef_declarator [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## typedef_declarator_list COMMA
+##
+
+At this point, a declarator is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN INT LPAREN RPAREN LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 244.
+##
+## direct_abstract_declarator -> direct_abstract_declarator LPAREN . option(context_parameter_type_list) RPAREN [ RPAREN LPAREN LBRACK COMMA ]
+##
+## The known suffix of the stack is as follows:
+## direct_abstract_declarator LPAREN
+##
+
+At this point, a list of parameter declarations,
+followed with a closing parenthesis ')', is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM CONST XOR_ASSIGN
+##
+## Ends in an error in state: 444.
+##
+## asm_attributes -> CONST . asm_attributes [ LPAREN ]
+##
+## The known suffix of the stack is as follows:
+## CONST
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM VOLATILE XOR_ASSIGN
+##
+## Ends in an error in state: 443.
+##
+## asm_attributes -> VOLATILE . asm_attributes [ LPAREN ]
+##
+## The known suffix of the stack is as follows:
+## VOLATILE
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM XOR_ASSIGN
+##
+## Ends in an error in state: 442.
+##
+## asm_statement -> ASM . asm_attributes LPAREN string_literals_list asm_arguments RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ASM
+##
+
+Ill-formed assembly statement.
+At this point, one of the following is expected:
+ an assembly attribute, such as 'volatile'; or
+ an opening parenthesis '('.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON COLON STRING_LITERAL COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 468.
+##
+## asm_flags -> asm_flags COMMA . string_literals_list [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## asm_flags COMMA
+##
+# We are in the clobber list.
+# We have seen a comma, so we expect a string literal.
+# first(asm_flags) = STRING_LITERAL
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON COLON XOR_ASSIGN
+##
+## Ends in an error in state: 465.
+##
+## asm_arguments -> COLON asm_operands COLON asm_operands COLON . asm_flags [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## COLON asm_operands COLON asm_operands COLON
+##
+# We are at the beginning of the clobber list.
+# first(asm_flags) = STRING_LITERAL
+
+Ill-formed assembly statement.
+At this point, a clobbered resource is expected.
+Examples of clobbered resources:
+ "memory"
+ "eax"
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON COLON STRING_LITERAL XOR_ASSIGN
+##
+## Ends in an error in state: 467.
+##
+## asm_arguments -> COLON asm_operands COLON asm_operands COLON asm_flags . [ RPAREN ]
+## asm_flags -> asm_flags . COMMA string_literals_list [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## COLON asm_operands COLON asm_operands COLON asm_flags
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 466, spurious reduction of production asm_flags -> string_literals_list
+##
+
+# Let's ignore the possibility of concatenating string literals.
+# We are in the clobber list (asm_flags).
+# Either we extend it, or we terminate it with RPAREN.
+
+Ill-formed assembly statement.
+Up to this point, a list of clobbered resources has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN CONSTANT RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 462.
+##
+## asm_arguments -> COLON asm_operands . [ RPAREN ]
+## asm_arguments -> COLON asm_operands . COLON asm_operands [ RPAREN ]
+## asm_arguments -> COLON asm_operands . COLON asm_operands COLON asm_flags [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## COLON asm_operands
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 454, spurious reduction of production asm_operands -> asm_operands_ne
+##
+
+# We have seen one COLON, hence the outputs. (The list of outputs may be empty.)
+
+Ill-formed assembly statement.
+Up to this point, a list of outputs has been recognized:
+ $0
+If this list is complete,
+then at this point, one of the following is expected:
+ a colon ':', followed with a list of inputs; or
+ a closing parenthesis ')'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON XOR_ASSIGN
+##
+## Ends in an error in state: 464.
+##
+## asm_arguments -> COLON asm_operands COLON asm_operands . [ RPAREN ]
+## asm_arguments -> COLON asm_operands COLON asm_operands . COLON asm_flags [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## COLON asm_operands COLON asm_operands
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 463, spurious reduction of production asm_operands ->
+##
+
+# We have seen two COLONs, hence the outputs and inputs. (The list of inputs may be empty.)
+
+# clang requests a closing parenthesis. gcc requests a string literal.
+
+Ill-formed assembly statement.
+Up to this point, a list of outputs and a list of inputs have been recognized:
+ $2
+ $0
+If the latter list is complete,
+then at this point, one of the following is expected:
+ a colon ':', followed with a list of clobbered resources; or
+ a closing parenthesis ')'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON LBRACK PRE_NAME VAR_NAME RBRACK XOR_ASSIGN
+##
+## Ends in an error in state: 457.
+##
+## asm_operand -> asm_op_name . string_literals_list LPAREN expression RPAREN [ RPAREN COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## asm_op_name
+##
+
+# Example of asm_operand: [oldval]"=r"(res)
+# We have seen an asm_op_name, we now expect a string literal list.
+# "=r" is an example of a constraint.
+
+Ill-formed assembly operand.
+At this point, a string literal, representing a constraint, is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON LBRACK PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 452.
+##
+## asm_op_name -> LBRACK general_identifier . RBRACK [ STRING_LITERAL ]
+##
+## The known suffix of the stack is as follows:
+## LBRACK general_identifier
+##
+
+Ill-formed assembly operand.
+At this point, a closing bracket ']' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON LBRACK XOR_ASSIGN
+##
+## Ends in an error in state: 451.
+##
+## asm_op_name -> LBRACK . general_identifier RBRACK [ STRING_LITERAL ]
+##
+## The known suffix of the stack is as follows:
+## LBRACK
+##
+
+Ill-formed assembly operand.
+At this point, an identifier is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN CONSTANT RPAREN COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 455.
+##
+## asm_operands_ne -> asm_operands_ne COMMA . asm_operand [ RPAREN COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## asm_operands_ne COMMA
+##
+
+# clang and gcc request a string literal (which is incomplete).
+
+Ill-formed assembly statement.
+At this point, an assembly operand is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 460.
+##
+## asm_operand -> asm_op_name string_literals_list LPAREN expression . RPAREN [ RPAREN COMMA COLON ]
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## asm_op_name string_literals_list LPAREN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+Ill-formed assembly operand.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 459.
+##
+## asm_operand -> asm_op_name string_literals_list LPAREN . expression RPAREN [ RPAREN COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## asm_op_name string_literals_list LPAREN
+##
+
+Ill-formed assembly operand.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL XOR_ASSIGN
+##
+## Ends in an error in state: 458.
+##
+## asm_operand -> asm_op_name string_literals_list . LPAREN expression RPAREN [ RPAREN COMMA COLON ]
+## string_literals_list -> string_literals_list . STRING_LITERAL [ STRING_LITERAL LPAREN ]
+##
+## The known suffix of the stack is as follows:
+## asm_op_name string_literals_list
+##
+
+# If we disregard the concatenation of string literals, then
+# at this point, we expect LPAREN.
+
+Ill-formed assembly operand.
+At this point, an opening parenthesis '(',
+followed with an expression and a closing parenthesis ')', is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL XOR_ASSIGN
+##
+## Ends in an error in state: 449.
+##
+## asm_statement -> ASM asm_attributes LPAREN string_literals_list . asm_arguments RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+## string_literals_list -> string_literals_list . STRING_LITERAL [ STRING_LITERAL RPAREN COLON ]
+##
+## The known suffix of the stack is as follows:
+## ASM asm_attributes LPAREN string_literals_list
+##
+# Expecting either one more string literal, or COLON, or RPAREN.
+
+# clang requests ')'. gcc requests ':' or ')'.
+
+Ill-formed assembly statement.
+At this point, one of the following is expected:
+ a string literal, representing one more instruction; or
+ a colon ':', followed with a list of outputs; or
+ a closing parenthesis ')'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 448.
+##
+## asm_statement -> ASM asm_attributes LPAREN . string_literals_list asm_arguments RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ASM asm_attributes LPAREN
+##
+
+Ill-formed assembly statement.
+At this point, a string literal, representing an instruction, is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE BREAK XOR_ASSIGN
+##
+## Ends in an error in state: 440.
+##
+## jump_statement -> BREAK . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## BREAK
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CONTINUE XOR_ASSIGN
+##
+## Ends in an error in state: 435.
+##
+## jump_statement -> CONTINUE . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## CONTINUE
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 559.
+##
+## iteration_statement -> save_context do_statement1 WHILE LPAREN expression RPAREN . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context do_statement1 WHILE LPAREN expression RPAREN
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE GOTO PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 431.
+##
+## jump_statement -> GOTO general_identifier . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## GOTO general_identifier
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 472.
+##
+## asm_statement -> ASM asm_attributes LPAREN string_literals_list asm_arguments RPAREN . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## ASM asm_attributes LPAREN string_literals_list asm_arguments RPAREN
+##
+
+Ill-formed statement.
+At this point, a semicolon ';' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CASE CONSTANT COLON XOR_ASSIGN
+##
+## Ends in an error in state: 439.
+##
+## labeled_statement -> CASE conditional_expression COLON . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## CASE conditional_expression COLON
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DEFAULT COLON XOR_ASSIGN
+##
+## Ends in an error in state: 434.
+##
+## labeled_statement -> DEFAULT COLON . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## DEFAULT COLON
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME VAR_NAME COLON XOR_ASSIGN
+##
+## Ends in an error in state: 486.
+##
+## labeled_statement -> general_identifier COLON . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## general_identifier COLON
+##
+
+# gcc and clang request an expression, which seems misleading (incomplete).
+
+Ill-formed labeled statement.
+At this point, a statement is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CASE CONSTANT SEMICOLON
+##
+## Ends in an error in state: 438.
+##
+## labeled_statement -> CASE conditional_expression . COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## CASE conditional_expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 57, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+##
+
+Ill-formed labeled statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a colon ':' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CASE XOR_ASSIGN
+##
+## Ends in an error in state: 437.
+##
+## labeled_statement -> CASE . conditional_expression COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## CASE
+##
+
+Ill-formed labeled statement.
+At this point, a constant expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DEFAULT XOR_ASSIGN
+##
+## Ends in an error in state: 433.
+##
+## labeled_statement -> DEFAULT . COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## DEFAULT
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 485.
+##
+## labeled_statement -> general_identifier . COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## general_identifier
+##
+
+# gcc and clang apparently do not allow a TYPEDEF_NAME to be reclassified as a label.
+
+Ill-formed labeled statement.
+At this point, a colon ':' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 558.
+##
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+## iteration_statement -> save_context do_statement1 WHILE LPAREN expression . RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context do_statement1 WHILE LPAREN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+Ill-formed 'do' ... 'while' statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' and a semicolon ';' are expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 557.
+##
+## iteration_statement -> save_context do_statement1 WHILE LPAREN . expression RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context do_statement1 WHILE LPAREN
+##
+
+Ill-formed 'do' ... 'while' statement.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE XOR_ASSIGN
+##
+## Ends in an error in state: 556.
+##
+## iteration_statement -> save_context do_statement1 WHILE . LPAREN expression RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context do_statement1 WHILE
+##
+
+Ill-formed 'do' ... 'while' statement.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON XOR_ASSIGN
+##
+## Ends in an error in state: 555.
+##
+## iteration_statement -> save_context do_statement1 . WHILE LPAREN expression RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context do_statement1
+##
+
+# Quite nicely, in this case, there is no doubt that the statement is
+# finished. This is not true in general, I think (the statement could
+# be an if/then, and we don't know whether it should have an ELSE
+# branch) but is true sometimes (e.g. it is not a conditional
+# statement, or it is one and we just saw the ELSE branch).
+
+Ill-formed 'do' ... 'while' statement.
+At this point, a 'while' keyword is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO XOR_ASSIGN
+##
+## Ends in an error in state: 551.
+##
+## do_statement1 -> save_context DO . statement [ WHILE ]
+##
+## The known suffix of the stack is as follows:
+## save_context DO
+##
+
+# gcc and clang expect an expression.
+
+Ill-formed 'do' ... 'while' statement.
+At this point, a statement (the loop body) is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON SEMICOLON RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 521.
+##
+## iteration_statement -> save_context FOR LPAREN for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN) . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context FOR LPAREN for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN)
+##
+
+Ill-formed 'for' statement.
+At this point, a statement (the loop body) is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON SEMICOLON PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 523.
+##
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+## optional(expression,RPAREN) -> expression . RPAREN [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BREAK BANG ASM AND ALIGNOF ]
+##
+## The known suffix of the stack is as follows:
+## expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+# The use of optional(expression,RPAREN) tells us that we are in a FOR statement.
+# Relying on this is a bit fragile, though.
+
+Ill-formed 'for' statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON SEMICOLON XOR_ASSIGN
+##
+## Ends in an error in state: 519.
+##
+## iteration_statement -> save_context FOR LPAREN for_statement_header optional(expression,SEMICOLON) . optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context FOR LPAREN for_statement_header optional(expression,SEMICOLON)
+##
+
+# Expecting the third part of the loop header -- the expression
+# that tells what happens after each iteration.
+
+Ill-formed 'for' statement.
+At this point, an optional expression
+ (evaluated after each execution of the loop body),
+followed with a closing parenthesis ')', is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON XOR_ASSIGN
+##
+## Ends in an error in state: 518.
+##
+## iteration_statement -> save_context FOR LPAREN for_statement_header . optional(expression,SEMICOLON) optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context FOR LPAREN for_statement_header
+##
+
+# Expecting the second part of the loop header -- the controlling expression.
+
+Ill-formed 'for' statement.
+At this point, an optional expression
+ (evaluated before each execution of the loop body),
+followed with a semicolon ';', is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN PRE_NAME VAR_NAME RPAREN
+##
+## Ends in an error in state: 525.
+##
+## expression -> expression . COMMA assignment_expression [ SEMICOLON COMMA ]
+## optional(expression,SEMICOLON) -> expression . SEMICOLON [ TILDE STRING_LITERAL STAR SIZEOF SEMICOLON RPAREN PRE_NAME PLUS MINUS LPAREN INC DEC CONSTANT BUILTIN_VA_ARG BANG AND ALIGNOF ]
+##
+## The known suffix of the stack is as follows:
+## expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+# At the time of writing, optional(expression,SEMICOLON) is used only in FOR
+# loops, but it could be used elsewhere in the future. This is a bit fragile.
+
+Ill-formed 'for' statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a semicolon ';' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 506.
+##
+## iteration_statement -> save_context FOR LPAREN . for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context FOR LPAREN
+##
+
+# gcc and clang say they expect an expression, which is incomplete.
+
+Ill-formed 'for' statement.
+At this point, one of the following is expected:
+ an optional expression
+ (evaluated once at the beginning),
+ followed with a semicolon ';'; or
+ a declaration.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR XOR_ASSIGN
+##
+## Ends in an error in state: 505.
+##
+## iteration_statement -> save_context FOR . LPAREN for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context FOR
+##
+
+Ill-formed 'for' statement.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE GOTO XOR_ASSIGN
+##
+## Ends in an error in state: 430.
+##
+## jump_statement -> GOTO . general_identifier SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## GOTO
+##
+
+Ill-formed 'goto' statement.
+At this point, an identifier (a 'goto' label) is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO IF LPAREN CONSTANT RPAREN SEMICOLON ELSE XOR_ASSIGN
+##
+## Ends in an error in state: 553.
+##
+## selection_statement -> save_context ifelse_statement1 . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context ifelse_statement1
+##
+
+Ill-formed 'if' ... 'else' statement.
+At this point, a statement is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 502.
+##
+## ifelse_statement1 -> IF LPAREN expression RPAREN save_context . statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BREAK BANG ASM AND ALIGNOF ]
+## selection_statement -> save_context IF LPAREN expression RPAREN save_context . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context IF LPAREN expression RPAREN save_context
+##
+
+Ill-formed 'if' statement.
+At this point, a statement is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 500.
+##
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+## ifelse_statement1 -> IF LPAREN expression . RPAREN save_context statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BREAK BANG ASM AND ALIGNOF ]
+## selection_statement -> save_context IF LPAREN expression . RPAREN save_context statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context IF LPAREN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+Ill-formed 'if' statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 499.
+##
+## ifelse_statement1 -> IF LPAREN . expression RPAREN save_context statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BREAK BANG ASM AND ALIGNOF ]
+## selection_statement -> save_context IF LPAREN . expression RPAREN save_context statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context IF LPAREN
+##
+
+Ill-formed 'if' statement.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF XOR_ASSIGN
+##
+## Ends in an error in state: 498.
+##
+## ifelse_statement1 -> IF . LPAREN expression RPAREN save_context statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BREAK BANG ASM AND ALIGNOF ]
+## selection_statement -> save_context IF . LPAREN expression RPAREN save_context statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context IF
+##
+
+Ill-formed 'if' statement.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 496.
+##
+## selection_statement -> save_context SWITCH LPAREN expression RPAREN . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context SWITCH LPAREN expression RPAREN
+##
+
+
+# Technically, the body of a 'switch' statement is just a statement,
+# but in practice, it should be a list of labeled statements,
+# enclosed in braces. (Unless someone is writing a Duff loop...)
+
+# gcc and clang again request an expression...
+
+Ill-formed 'switch' statement.
+At this point, a statement is expected.
+It usually takes the form of a series of labeled statements,
+enclosed within braces '{' and '}'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 495.
+##
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+## selection_statement -> save_context SWITCH LPAREN expression . RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context SWITCH LPAREN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+Ill-formed 'switch' statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 494.
+##
+## selection_statement -> save_context SWITCH LPAREN . expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context SWITCH LPAREN
+##
+
+Ill-formed 'switch' statement.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH XOR_ASSIGN
+##
+## Ends in an error in state: 493.
+##
+## selection_statement -> save_context SWITCH . LPAREN expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context SWITCH
+##
+
+Ill-formed 'switch' statement.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 480.
+##
+## iteration_statement -> save_context WHILE LPAREN expression RPAREN . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context WHILE LPAREN expression RPAREN
+##
+
+Ill-formed 'while' statement.
+At this point, a statement (the loop body) is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE LPAREN PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 479.
+##
+## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ]
+## iteration_statement -> save_context WHILE LPAREN expression . RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context WHILE LPAREN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+Ill-formed 'while' statement.
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE LPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 478.
+##
+## iteration_statement -> save_context WHILE LPAREN . expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context WHILE LPAREN
+##
+
+Ill-formed 'while' statement.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE XOR_ASSIGN
+##
+## Ends in an error in state: 477.
+##
+## iteration_statement -> save_context WHILE . LPAREN expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context WHILE
+##
+
+Ill-formed 'while' statement.
+At this point, an opening parenthesis '(' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE XOR_ASSIGN
+##
+## Ends in an error in state: 420.
+##
+## block_item_list -> option(block_item_list) . block_item [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+## compound_statement -> save_context LBRACE option(block_item_list) . RBRACE [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN EOF ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## save_context LBRACE option(block_item_list)
+##
+# We are possibly at the end of a block.
+#
+# Note that, because we have used %on_error_reduce to consider some statements
+# as complete even when they could be continued ELSE, we may end up here even
+# though ELSE is permitted. There is nothing we can do about it. We just omit
+# this permitted continuation in our message.
+
+# clang and gcc say an expression is expected.
+
+At this point, one of the following is expected:
+ a declaration; or
+ a statement; or
+ a pragma; or
+ a closing brace '}'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE RETURN XOR_ASSIGN
+##
+## Ends in an error in state: 422.
+##
+## jump_statement -> RETURN . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+## jump_statement -> RETURN . expression SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## RETURN
+##
+
+# clang and gcc expect an expression.
+
+Ill-formed 'return' statement.
+At this point, one of the following is expected:
+ an expression; or
+ a semicolon ';'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE STRING_LITERAL RPAREN
+##
+## Ends in an error in state: 489.
+##
+## expression -> expression . COMMA assignment_expression [ SEMICOLON COMMA ]
+## expression_statement -> expression . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 58, spurious reduction of production primary_expression -> string_literals_list
+## In state 60, spurious reduction of production postfix_expression -> primary_expression
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LBRACE RETURN STRING_LITERAL WHILE
+##
+## Ends in an error in state: 424.
+##
+## expression -> expression . COMMA assignment_expression [ SEMICOLON COMMA ]
+## jump_statement -> RETURN expression . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## RETURN expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 58, spurious reduction of production primary_expression -> string_literals_list
+## In state 60, spurious reduction of production postfix_expression -> primary_expression
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 127, spurious reduction of production expression -> assignment_expression
+##
+
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a semicolon ';' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 562.
+##
+## declaration_specifiers(declaration(block_item)) -> typedef_name . list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers_typedef -> typedef_name . list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## general_identifier -> typedef_name . [ COLON ]
+##
+## The known suffix of the stack is as follows:
+## typedef_name
+##
+
+# We see a type name "foo" at the beginning of a block_item, it seems.
+# This could be the beginning of a declaration, "foo x".
+# In that case, we expect a possibly-empty list declaration_specifiers_no_type?,
+# which means a list of:
+# storage class specifiers,
+# type qualifiers,
+# function specifiers (i.e., INLINE, but I suspect this is illegal here).
+# After this list, we expect init_declarator_list? SEMICOLON.
+# The second form, where this could be a typedef, is very exotic; ignore it.
+# This could also be a labeled statement, in which case we expect a colon.
+# This case sounds rather unlikely. Let's omit it.
+
+# We simplify "a list of init declarators" to "an init declarator".
+
+A type identifier has been recognized.
+Assuming this is the beginning of a declaration,
+at this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ an init declarator, followed with a semicolon ';'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 122.
+##
+## expression -> expression COMMA . assignment_expression [ SEMICOLON RPAREN RBRACK COMMA COLON ]
+##
+## The known suffix of the stack is as follows:
+## expression COMMA
+##
+
+Ill-formed use of the sequencing operator ','.
+At this point, an expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME COMMA PRE_NAME VAR_NAME RPAREN
+##
+## Ends in an error in state: 539.
+##
+## init_declarator_list -> init_declarator_list . COMMA init_declarator [ SEMICOLON COMMA ]
+## option(init_declarator_list) -> init_declarator_list . [ SEMICOLON ]
+##
+## The known suffix of the stack is as follows:
+## init_declarator_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 250, spurious reduction of production declarator_noattrend -> direct_declarator
+## In state 547, spurious reduction of production declare_varname(declarator_noattrend) -> declarator_noattrend
+## In state 542, spurious reduction of production save_context ->
+## In state 543, spurious reduction of production attribute_specifier_list ->
+## In state 544, spurious reduction of production init_declarator -> declare_varname(declarator_noattrend) save_context attribute_specifier_list
+## In state 541, spurious reduction of production init_declarator_list -> init_declarator_list COMMA init_declarator
+##
+
+Up to this point, a list of declarators has been recognized:
+ $0
+If this list is complete,
+then at this point, a semicolon ';' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 540.
+##
+## init_declarator_list -> init_declarator_list COMMA . init_declarator [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## init_declarator_list COMMA
+##
+
+Ill-formed declaration.
+At this point, an init declarator is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT PRE_NAME VAR_NAME EQ ALIGNAS
+##
+## Ends in an error in state: 321.
+##
+## initializer_list -> option(designation) . c_initializer [ RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## option(designation)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE PRE_NAME VAR_NAME COMMA DOT PRE_NAME VAR_NAME EQ ALIGNAS
+##
+## Ends in an error in state: 325.
+##
+## initializer_list -> initializer_list COMMA option(designation) . c_initializer [ RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## initializer_list COMMA option(designation)
+##
+
+Ill-formed initializer list.
+At this point, an initializer is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT PRE_NAME VAR_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 328.
+##
+## designation -> designator_list . EQ [ TILDE STRING_LITERAL STAR SIZEOF PRE_NAME PLUS MINUS LPAREN LBRACE INC DEC CONSTANT BUILTIN_VA_ARG BANG AND ALIGNOF ]
+## option(designator_list) -> designator_list . [ LBRACK DOT ]
+##
+## The known suffix of the stack is as follows:
+## designator_list
+##
+
+# We are expecting either one more designator,
+# or an EQ sign (which marks the end of the designation).
+
+Ill-formed designation.
+Up to this point, a list of designators has been recognized:
+ $0
+If this list is complete,
+then at this point, an equals sign '=' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT XOR_ASSIGN
+##
+## Ends in an error in state: 318.
+##
+## designator -> DOT . general_identifier [ LBRACK EQ DOT ]
+##
+## The known suffix of the stack is as follows:
+## DOT
+##
+
+# clang gives examples of designators.
+
+Ill-formed designator.
+At this point, the name of a struct or union member is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE LBRACK PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 316.
+##
+## designator -> LBRACK conditional_expression . RBRACK [ LBRACK EQ DOT ]
+##
+## The known suffix of the stack is as follows:
+## LBRACK conditional_expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 57, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+##
+
+Ill-formed designator.
+Up to this point, an opening bracket and an expression have been recognized:
+ $1 $0
+If this expression is complete,
+then at this point, a closing bracket ']' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE LBRACK XOR_ASSIGN
+##
+## Ends in an error in state: 315.
+##
+## designator -> LBRACK . conditional_expression RBRACK [ LBRACK EQ DOT ]
+##
+## The known suffix of the stack is as follows:
+## LBRACK
+##
+
+Ill-formed designator.
+At this point, a constant expression is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 324.
+##
+## initializer_list -> initializer_list COMMA . option(designation) c_initializer [ RBRACE COMMA ]
+## option(COMMA) -> COMMA . [ RBRACE ]
+##
+## The known suffix of the stack is as follows:
+## initializer_list COMMA
+##
+
+# This could be a trailing comma, in which case a closing brace is legal.
+# Or, this comma could announce a new option(designation) c_initializer.
+
+Ill-formed initializer list.
+At this point, one of the following is expected:
+ an optional designation, followed with an initializer; or
+ a closing brace '}'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE CONSTANT SEMICOLON
+##
+## Ends in an error in state: 323.
+##
+## c_initializer -> LBRACE initializer_list . option(COMMA) RBRACE [ SEMICOLON RBRACE COMMA ]
+## initializer_list -> initializer_list . COMMA option(designation) c_initializer [ RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## LBRACE initializer_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+## In state 327, spurious reduction of production c_initializer -> assignment_expression
+## In state 333, spurious reduction of production initializer_list -> option(designation) c_initializer
+##
+
+# Omitting the fact that the closing brace can be preceded with a comma.
+
+Ill-formed initializer.
+Up to this point, a list of initializers has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing brace '}' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE XOR_ASSIGN
+##
+## Ends in an error in state: 322.
+##
+## c_initializer -> LBRACE . initializer_list option(COMMA) RBRACE [ SEMICOLON RBRACE COMMA ]
+##
+## The known suffix of the stack is as follows:
+## LBRACE
+##
+
+# An initializer list is expected.
+# Hence, an initializer is expected.
+
+# clang and gcc expect an expression (incomplete).
+
+Ill-formed initializer.
+At this point, an optional designation,
+followed with an initializer, is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME EQ XOR_ASSIGN
+##
+## Ends in an error in state: 545.
+##
+## init_declarator -> declare_varname(declarator_noattrend) save_context attribute_specifier_list EQ . c_initializer [ SEMICOLON COMMA ]
+##
+## The known suffix of the stack is as follows:
+## declare_varname(declarator_noattrend) save_context attribute_specifier_list EQ
+##
+
+# clang and gcc expect an expression (incomplete).
+
+Ill-formed init declarator.
+At this point, an initializer is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LBRACK CONSTANT SEMICOLON
+##
+## Ends in an error in state: 238.
+##
+## optional(assignment_expression,RBRACK) -> assignment_expression . RBRACK [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## assignment_expression
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 61, spurious reduction of production unary_expression -> postfix_expression
+## In state 65, spurious reduction of production cast_expression -> unary_expression
+## In state 88, spurious reduction of production multiplicative_expression -> cast_expression
+## In state 82, spurious reduction of production additive_expression -> multiplicative_expression
+## In state 101, spurious reduction of production shift_expression -> additive_expression
+## In state 78, spurious reduction of production relational_expression -> shift_expression
+## In state 94, spurious reduction of production equality_expression -> relational_expression
+## In state 110, spurious reduction of production and_expression -> equality_expression
+## In state 118, spurious reduction of production exclusive_or_expression -> and_expression
+## In state 119, spurious reduction of production inclusive_or_expression -> exclusive_or_expression
+## In state 120, spurious reduction of production logical_and_expression -> inclusive_or_expression
+## In state 104, spurious reduction of production logical_or_expression -> logical_and_expression
+## In state 102, spurious reduction of production conditional_expression -> logical_or_expression
+## In state 123, spurious reduction of production assignment_expression -> conditional_expression
+##
+
+# At the time of writing, optional(expression,RBRACK) is used only in direct
+# (possibly abstract) declarators, but it could be used elsewhere in the future.
+# This is a bit fragile.
+
+# Ill-formed direct declarator or direct abstract declarator.
+
+Up to this point, an expression has been recognized:
+ $0
+If this expression is complete,
+then at this point, a closing bracket ']' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 277.
+##
+## identifier_list -> identifier_list COMMA . PRE_NAME VAR_NAME [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## identifier_list COMMA
+##
+
+# Strangely, gcc requests ')'.
+
+Ill-formed K&R function definition.
+At this point, an identifier is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME COMMA PRE_NAME TYPEDEF_NAME
+##
+## Ends in an error in state: 278.
+##
+## identifier_list -> identifier_list COMMA PRE_NAME . VAR_NAME [ RPAREN COMMA ]
+##
+## The known suffix of the stack is as follows:
+## identifier_list COMMA PRE_NAME
+##
+
+Ill-formed K&R function definition.
+The following type name is used as a K&R parameter name:
+ $0
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN INT XOR_ASSIGN
+##
+## Ends in an error in state: 581.
+##
+## declaration_specifiers(declaration(block_item)) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOLATILE INT XOR_ASSIGN
+##
+## Ends in an error in state: 586.
+##
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 579.
+##
+## declaration_specifiers(declaration(block_item)) -> typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## typedef_name list(declaration_specifier_no_type)
+##
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 584.
+##
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . type_qualifier_noattr [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . function_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . attribute_specifier [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type)
+##
+
+# We omit the case of the empty list of declarators
+# We omit the case of successive primitive type specifiers
+
+Ill-formed K&R parameter declaration.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a list of declarator.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOLATILE XOR_ASSIGN
+##
+## Ends in an error in state: 582.
+##
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ]
+## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ]
+##
+## The known suffix of the stack is as follows:
+## rlist(declaration_specifier_no_type)
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 209, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr
+##
+
+Ill-formed K&R parameter declaration.
+At this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: VOID PRE_NAME TYPEDEF_NAME PACKED LPAREN CONSTANT RPAREN XOR_ASSIGN
+##
+## Ends in an error in state: 595.
+##
+## attribute_specifier_list -> attribute_specifier . attribute_specifier_list [ SEMICOLON LBRACE EQ COMMA ]
+## rlist(declaration_specifier_no_type) -> attribute_specifier . [ VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT PRE_NAME LONG INT FLOAT ENUM DOUBLE CHAR ]
+## rlist(declaration_specifier_no_type) -> attribute_specifier . rlist(declaration_specifier_no_type) [ VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT PRE_NAME LONG INT FLOAT ENUM DOUBLE CHAR ]
+##
+## The known suffix of the stack is as follows:
+## attribute_specifier
+##
+
+# We have just parsed a list of attribute specifiers, but we cannot
+# print it because it is not available. We do not know wether it is
+# part of the declaration or whether it is part of the first K&R parameter
+# declaration.
+
+# We omit the possibility of one more attribute specifier
+
+Ill-formed declaration or function definition.
+Up to this point, a list of attribute specifiers has been recognized.
+If this is a declaration,
+ then at this point, a semicolon ';' is expected.
+If this is a function definition,
+ then at this point, an opening brace '{' is expected (for the function body).
+If this is the parameter declaration of a K&R function definition,
+ then at this point, one of the following is expected:
+ a storage class specifier; or
+ a type qualifier; or
+ a type specifier.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT COMMA XOR_ASSIGN
+##
+## Ends in an error in state: 225.
+##
+## parameter_list -> parameter_list COMMA . parameter_declaration [ RPAREN COMMA ]
+## parameter_type_list -> parameter_list COMMA . ELLIPSIS [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## parameter_list COMMA
+##
+
+At this point, one of the following is expected:
+ a parameter declaration; or
+ an ellipsis '...'.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME SEMICOLON
+##
+## Ends in an error in state: 224.
+##
+## parameter_list -> parameter_list . COMMA parameter_declaration [ RPAREN COMMA ]
+## parameter_type_list -> parameter_list . [ RPAREN ]
+## parameter_type_list -> parameter_list . COMMA ELLIPSIS [ RPAREN ]
+##
+## The known suffix of the stack is as follows:
+## parameter_list
+##
+## WARNING: This example involves spurious reductions.
+## This implies that, although the LR(1) items shown above provide an
+## accurate view of the past (what has been recognized so far), they
+## may provide an INCOMPLETE view of the future (what was expected next).
+## In state 250, spurious reduction of production declarator_noattrend -> direct_declarator
+## In state 255, spurious reduction of production attribute_specifier_list ->
+## In state 256, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list
+## In state 272, spurious reduction of production declare_varname(declarator) -> declarator
+## In state 271, spurious reduction of production parameter_declaration -> declaration_specifiers(parameter_declaration) declare_varname(declarator)
+## In state 232, spurious reduction of production parameter_list -> parameter_declaration
+##
+
+# We omit the possibility of an ellipsis.
+# It can be understood as part of the "if this list is complete..." hypothesis.
+
+# Strangely, gcc is not bothered by the last SEMICOLON,
+# but complains that this is a "forward declaration" of the parameter.
+
+Up to this point, a list of parameter declarations has been recognized:
+ $0
+If this list is complete,
+then at this point, a closing parenthesis ')' is expected.
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: PRE_NAME VAR_NAME
+##
+## Ends in an error in state: 14.
+##
+## typedef_name -> PRE_NAME . TYPEDEF_NAME [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA COLON AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+
+# This can only happen in a declaration
+
+Ill-formed declaration.
+The following identifier is not a type name, but a type specifier was expected:
+$0
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN INT SEMICOLON XOR_ASSIGN
+##
+## Ends in an error in state: 591.
+##
+## declaration_list -> declaration_list . kr_param_declaration [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED LONG LBRACE INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ]
+## function_definition1 -> declaration_specifiers(declaration(external_declaration)) declare_varname(declarator_noattrend) save_context declaration_list . [ LBRACE ]
+##
+## The known suffix of the stack is as follows:
+## declaration_specifiers(declaration(external_declaration)) declare_varname(declarator_noattrend) save_context declaration_list
+##
+# clang requests the function body; gcc requests a declaration :-)
+
+Ill-formed K&R function definition.
+At this point, one of the following is expected:
+ a declaration; or
+ an opening brace '{' (for the function body).
+
+# ------------------------------------------------------------------------------
+
+translation_unit_file: ALIGNAS LPAREN PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 27.
+##
+## primary_expression -> PRE_NAME . VAR_NAME [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## typedef_name -> PRE_NAME . TYPEDEF_NAME [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+translation_unit_file: ALIGNAS LPAREN VOID LPAREN VOID LPAREN PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 231.
+##
+## declarator_identifier -> PRE_NAME . low_prec TYPEDEF_NAME [ RPAREN PACKED LPAREN LBRACK ATTRIBUTE ALIGNAS ]
+## declarator_identifier -> PRE_NAME . VAR_NAME [ RPAREN PACKED LPAREN LBRACK ATTRIBUTE ALIGNAS ]
+## typedef_name -> PRE_NAME . TYPEDEF_NAME [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+translation_unit_file: UNION PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 38.
+##
+## general_identifier -> PRE_NAME . VAR_NAME [ XOR_ASSIGN VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF SUB_ASSIGN STRUCT STATIC STAR SLASH SIGNED SHORT SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RESTRICT REGISTER RBRACK RBRACE QUESTION PTR PRE_NAME PLUS PERCENT PACKED OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LONG LEQ LEFT_ASSIGN LEFT LBRACK LBRACE INT INLINE INC HAT GT GEQ FLOAT EXTERN EQEQ EQ ENUM DOUBLE DOT DIV_ASSIGN DEC CONST COMMA COLON CHAR BARBAR BAR AUTO ATTRIBUTE AND_ASSIGN ANDAND AND ALIGNAS ADD_ASSIGN ]
+## typedef_name -> PRE_NAME . TYPEDEF_NAME [ XOR_ASSIGN VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF SUB_ASSIGN STRUCT STATIC STAR SLASH SIGNED SHORT SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RESTRICT REGISTER RBRACK RBRACE QUESTION PTR PRE_NAME PLUS PERCENT PACKED OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LONG LEQ LEFT_ASSIGN LEFT LBRACK LBRACE INT INLINE INC HAT GT GEQ FLOAT EXTERN EQEQ EQ ENUM DOUBLE DOT DIV_ASSIGN DEC CONST COMMA COLON CHAR BARBAR BAR AUTO ATTRIBUTE AND_ASSIGN ANDAND AND ALIGNAS ADD_ASSIGN ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LBRACE PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 427.
+##
+## general_identifier -> PRE_NAME . VAR_NAME [ COLON ]
+## primary_expression -> PRE_NAME . VAR_NAME [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RIGHT_ASSIGN RIGHT QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ]
+## typedef_name -> PRE_NAME . TYPEDEF_NAME [ VOLATILE TYPEDEF STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED LPAREN INLINE EXTERN CONST COLON AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LPAREN PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 190.
+##
+## identifier_list -> PRE_NAME . VAR_NAME [ RPAREN COMMA ]
+## typedef_name -> PRE_NAME . TYPEDEF_NAME [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+translation_unit_file: VOID PRE_NAME XOR_ASSIGN
+##
+## Ends in an error in state: 178.
+##
+## declarator_identifier -> PRE_NAME . low_prec TYPEDEF_NAME [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+## declarator_identifier -> PRE_NAME . VAR_NAME [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ]
+##
+## The known suffix of the stack is as follows:
+## PRE_NAME
+##
+
+# This is not supposed to be possible, since the Lexer can only emit a
+# VAR_NAME or a TYPEDEF_NAME after a PRE_NAME
+
+Internal error when printing a syntax error message. Please report.
+
+# ------------------------------------------------------------------------------
+
+
+
+# Local Variables:
+# mode: shell-script
+# End:
diff --git a/cparser/pre_parser.mly b/cparser/pre_parser.mly
index 41b068de..4d7ad40a 100644
--- a/cparser/pre_parser.mly
+++ b/cparser/pre_parser.mly
@@ -3,6 +3,7 @@
/* The Compcert verified compiler */
/* */
/* Jacques-Henri Jourdan, INRIA Paris-Rocquencourt */
+/* François Pottier, INRIA Paris-Rocquencourt */
/* */
/* Copyright Institut National de Recherche en Informatique et en */
/* Automatique. All rights reserved. This file is distributed */
@@ -17,7 +18,7 @@
WARNING: The precedence declarations tend to silently solve
conflicts. So, if you change the grammar (especially for
statements), you should check that without these declarations, it
- has ONLY 3 CONFLICTS in 3 STATES.
+ has ONLY 2 CONFLICTS in 2 STATES.
*)
%{
@@ -32,16 +33,6 @@
let declare_typename (i,_,_) =
!declare_typename i
- let syntax_error pos =
- Cerrors.fatal_error "%s:%d: syntax error"
- pos.Lexing.pos_fname pos.Lexing.pos_lnum
-
- let unclosed opening closing pos1 pos2 =
- Cerrors.info "%s:%d: syntax error: expecting '%s'"
- pos2.Lexing.pos_fname pos2.Lexing.pos_lnum closing;
- Cerrors.fatal_error "%s:%d: this is the location of the unclosed '%s'"
- pos1.Lexing.pos_fname pos1.Lexing.pos_lnum opening
-
type 'id fun_declarator_ctx =
| Decl_ident
| Decl_other
@@ -85,16 +76,106 @@
%nonassoc ELSE
%start<unit> translation_unit_file
+
+(* The following declarations cause certain nonterminal symbols to be
+ reduced when an error is detected. This replaces error actions in
+ the automaton with reduction actions. So, if the input is correct,
+ this makes no difference, and if the input is incorrect, this only
+ forces a few more reductions to take place before the error is
+ detected and reported. If used properly, this facilitates error
+ reports. *)
+
+%on_error_reduce
+ primary_expression
+ postfix_expression
+ unary_expression
+ cast_expression
+ multiplicative_expression
+ additive_expression
+ shift_expression
+ relational_expression
+ equality_expression
+ and_expression
+ exclusive_or_expression
+ inclusive_or_expression
+ logical_and_expression
+ logical_or_expression
+ conditional_expression
+ assignment_expression
+ expression
+ attribute_specifier_list
+ declarator
+ declarator_noattrend
+ selection_statement
+ enum_specifier
+ struct_or_union_specifier
+ specifier_qualifier_list(struct_declaration)
+ specifier_qualifier_list(type_name)
+ option(abstract_declarator(type_name))
+ abstract_declarator(type_name)
+ abstract_declarator(parameter_declaration)
+ asm_flags
+ asm_operands
+ init_declarator
+ rlist(declaration_specifier_no_type)
+
%%
(* Helpers *)
-%inline option(X):
+(* Note that, by convention, [X?] is syntactic sugar for [option(X)],
+ so this definition of [option] is actually used, even though the
+ word [option] does not appear in the rest of this file. *)
+
+(* [ioption(X)] is equivalent to [option(X)], but is marked [%inline],
+ so its definition is expanded. In the absence of conflicts, the two
+ are equivalent. Using [ioption] instead of [option] in well-chosen
+ places can help avoid conflicts. Conversely, using [option] instead
+ of [ioption] in well-chosen places can help reduce the number of
+ states of the automaton. *)
+
+(* Defining the non-%inline version in terms of the %inline version is
+ a standard idiom. It obviates the need to duplicate the definition.
+ The same idiom is used elsewhere below. *)
+
+%inline ioption(X):
| /* nothing */
{ None }
| x = X
{ Some x }
+option(X):
+ o = ioption(X)
+ { o }
+
+(* [optional(X, Y)] is equivalent to [X? Y]. However, by inlining
+ the two possibilies -- either [X Y] or just [Y] -- we are able
+ to give more meaningful syntax error messages. [optional(X, Y)]
+ itself is usually NOT inlined, as that would cause a useless
+ explosion of cases. *)
+optional(X, Y):
+ ioption(X) Y {}
+
+(* This is a standard left-recursive, possibly empty list, without
+ separators. Note that, by convention, [X*] is syntactic sugar for
+ [list(X)]. *)
+
+(* [ilist(X)] is equivalent to [list(X)], but is marked [%inline],
+ so its definition is expanded (only one level deep, of course). *)
+
+%inline ilist(X):
+| (* empty *) {}
+| list(X) X {}
+
+list(X):
+| ilist(X) {}
+
+(* [rlist(X)] is right-recursive non-empty list. *)
+
+rlist(X):
+| X {}
+| X rlist(X) {}
+
(* The kind of an identifier should not be determined when looking
ahead, because the context may not be up to date. For this reason,
when reading an identifier, the lexer emits two tokens: the first
@@ -106,7 +187,7 @@ typedef_name:
| PRE_NAME i = TYPEDEF_NAME
{ i }
-var_name:
+%inline var_name:
| PRE_NAME i = VAR_NAME
{ i }
@@ -115,8 +196,18 @@ general_identifier:
| i = var_name
{ i }
+(* [other_identifier] is equivalent to [general_identifier], but adds
+ an instruction that re-classifies this identifier as an [OtherId].
+ Because this definition is marked %inline, the function call takes
+ place when the host production is reduced. *)
+
+%inline other_identifier:
+ i = general_identifier
+ { set_id_type i OtherId }
+
string_literals_list:
-| string_literals_list? STRING_LITERAL
+| STRING_LITERAL
+| string_literals_list STRING_LITERAL
{}
save_context:
@@ -127,40 +218,42 @@ declare_varname(nt):
declare_typename(nt):
i = nt { declare_typename (fst i); i }
+(* A note about phantom parameters. The definition of a non-terminal symbol
+ [nt] is sometimes parameterized with a parameter that is unused in the
+ right-hand side. This parameter disappears when macro-expansion takes
+ place. Thus, the presence of this parameter does not influence the language
+ that is accepted by the parser. Yet, it carries information about the
+ context, since different call sites can supply different values of this
+ parameter. This forces the creation of two (or more) identical copies of
+ the definition of [nt], which leads to a larger automaton, where some
+ states have been duplicated. In these states, more information about the
+ context is available, which allows better syntax error messages to be
+ given.
+
+ By convention, a formal phantom parameter is named [phantom], so as to be
+ easily recognizable. For clarity, we usually explicitly document which
+ actual values it can take. *)
+
(* Actual grammar *)
primary_expression:
-| i = var_name
- { set_id_type i VarId }
+| var_name
| CONSTANT
| string_literals_list
| LPAREN expression RPAREN
{}
-| LPAREN expression error
- { unclosed "(" ")" $startpos($1) $endpos }
postfix_expression:
| primary_expression
| postfix_expression LBRACK expression RBRACK
| postfix_expression LPAREN argument_expression_list? RPAREN
- {}
-| postfix_expression LPAREN argument_expression_list? error
- { unclosed "(" ")" $startpos($2) $endpos }
| BUILTIN_VA_ARG LPAREN assignment_expression COMMA type_name RPAREN
- {}
-| BUILTIN_VA_ARG LPAREN assignment_expression COMMA type_name error
- { unclosed "(" ")" $startpos($2) $endpos }
-| postfix_expression DOT i = general_identifier
-| postfix_expression PTR i = general_identifier
- { set_id_type i OtherId }
+| postfix_expression DOT other_identifier
+| postfix_expression PTR other_identifier
| postfix_expression INC
| postfix_expression DEC
| LPAREN type_name RPAREN LBRACE initializer_list COMMA? RBRACE
{}
-| LPAREN type_name error
- { unclosed "(" ")" $startpos($1) $endpos }
-| LPAREN type_name RPAREN LBRACE initializer_list COMMA? error
- { unclosed "{" "}" $startpos($4) $endpos }
argument_expression_list:
| assignment_expression
@@ -192,37 +285,44 @@ cast_expression:
| LPAREN type_name RPAREN cast_expression
{}
+multiplicative_operator:
+ STAR | SLASH | PERCENT {}
+
multiplicative_expression:
| cast_expression
-| multiplicative_expression STAR cast_expression
-| multiplicative_expression SLASH cast_expression
-| multiplicative_expression PERCENT cast_expression
+| multiplicative_expression multiplicative_operator cast_expression
{}
+additive_operator:
+ PLUS | MINUS {}
+
additive_expression:
| multiplicative_expression
-| additive_expression PLUS multiplicative_expression
-| additive_expression MINUS multiplicative_expression
+| additive_expression additive_operator multiplicative_expression
{}
+shift_operator:
+ LEFT | RIGHT {}
+
shift_expression:
| additive_expression
-| shift_expression LEFT additive_expression
-| shift_expression RIGHT additive_expression
+| shift_expression shift_operator additive_expression
{}
+relational_operator:
+ LT | GT | LEQ | GEQ {}
+
relational_expression:
| shift_expression
-| relational_expression LT shift_expression
-| relational_expression GT shift_expression
-| relational_expression LEQ shift_expression
-| relational_expression GEQ shift_expression
+| relational_expression relational_operator shift_expression
{}
+equality_operator:
+ EQEQ | NEQ {}
+
equality_expression:
| relational_expression
-| equality_expression EQEQ relational_expression
-| equality_expression NEQ relational_expression
+| equality_expression equality_operator relational_expression
{}
and_expression:
@@ -279,7 +379,7 @@ expression:
| expression COMMA assignment_expression
{}
-constant_expression:
+%inline constant_expression:
| conditional_expression
{}
@@ -291,9 +391,12 @@ constant_expression:
cannot contain an initialization (this is an error to initialize a
typedef). *)
-declaration:
-| declaration_specifiers init_declarator_list? SEMICOLON
-| declaration_specifiers_typedef typedef_declarator_list? SEMICOLON
+(* The phantom parameter is either [block_item], which means we are
+ definitely reading a declaration, or [external_declaration], which
+ means we could also be reading the beginning of a function definition. *)
+declaration(phantom):
+| declaration_specifiers(declaration(phantom)) init_declarator_list? SEMICOLON
+| declaration_specifiers_typedef typedef_declarator_list? SEMICOLON
{}
init_declarator_list:
@@ -322,23 +425,24 @@ storage_class_specifier_no_typedef:
| REGISTER
{}
-(* [declaration_specifiers_no_type] matches declaration specifiers
+(* [declaration_specifier_no_type] matches declaration specifiers
that do not contain either "typedef" nor type specifiers. *)
-declaration_specifiers_no_type:
-| storage_class_specifier_no_typedef declaration_specifiers_no_type?
-| type_qualifier declaration_specifiers_no_type?
-| function_specifier declaration_specifiers_no_type?
+%inline declaration_specifier_no_type:
+| storage_class_specifier_no_typedef
+| type_qualifier_noattr
+| function_specifier
+| attribute_specifier
{}
-(* [declaration_specifiers_no_typedef_name] matches declaration
+(* [declaration_specifier_no_typedef_name] matches declaration
specifiers that contain neither "typedef" nor a typedef name
(i.e. type specifier declared using a previous "typedef
keyword"). *)
-declaration_specifiers_no_typedef_name:
-| declaration_specifiers_no_typedef_name? storage_class_specifier_no_typedef
-| declaration_specifiers_no_typedef_name? type_qualifier
-| declaration_specifiers_no_typedef_name? function_specifier
-| declaration_specifiers_no_typedef_name? type_specifier_no_typedef_name
+declaration_specifier_no_typedef_name:
+| storage_class_specifier_no_typedef
+| type_qualifier
+| function_specifier
+| type_specifier_no_typedef_name
{}
(* [declaration_specifiers] makes sure one type specifier is given, and,
@@ -355,29 +459,23 @@ declaration_specifiers_no_typedef_name:
The first field is a named t, while the second is unnamed of type t.
*)
-declaration_specifiers:
-| declaration_specifiers_no_type? i = typedef_name declaration_specifiers_no_type?
- { set_id_type i TypedefId }
-| declaration_specifiers_no_type? type_specifier_no_typedef_name declaration_specifiers_no_typedef_name?
+(* The phantom parameter is either [declaration(_)], which means that
+ this is the beginning of a declaration or a function definition, or
+ [parameter_declaration], which means that this is the beginning of a
+ parameter declaration. *)
+declaration_specifiers(phantom):
+| ioption(rlist(declaration_specifier_no_type)) typedef_name declaration_specifier_no_type*
+| ioption(rlist(declaration_specifier_no_type)) type_specifier_no_typedef_name declaration_specifier_no_typedef_name*
{}
(* This matches declaration_specifiers that do contains once the
"typedef" keyword. To avoid conflicts, we also encode the
constraint described in the comment for [declaration_specifiers]. *)
declaration_specifiers_typedef:
-| declaration_specifiers_no_type?
- TYPEDEF declaration_specifiers_no_type?
- i = typedef_name declaration_specifiers_no_type?
-| declaration_specifiers_no_type?
- i = typedef_name declaration_specifiers_no_type?
- TYPEDEF declaration_specifiers_no_type?
- { set_id_type i TypedefId }
-| declaration_specifiers_no_type?
- TYPEDEF declaration_specifiers_no_type?
- type_specifier_no_typedef_name declaration_specifiers_no_typedef_name?
-| declaration_specifiers_no_type?
- type_specifier_no_typedef_name declaration_specifiers_no_typedef_name?
- TYPEDEF declaration_specifiers_no_typedef_name?
+| ioption(rlist(declaration_specifier_no_type)) TYPEDEF declaration_specifier_no_type* typedef_name declaration_specifier_no_type*
+| ioption(rlist(declaration_specifier_no_type)) typedef_name declaration_specifier_no_type* TYPEDEF declaration_specifier_no_type*
+| ioption(rlist(declaration_specifier_no_type)) TYPEDEF declaration_specifier_no_type* type_specifier_no_typedef_name declaration_specifier_no_typedef_name*
+| ioption(rlist(declaration_specifier_no_type)) type_specifier_no_typedef_name declaration_specifier_no_typedef_name* TYPEDEF declaration_specifier_no_typedef_name*
{}
(* A type specifier which is not a typedef name. *)
@@ -397,15 +495,9 @@ type_specifier_no_typedef_name:
{}
struct_or_union_specifier:
-| struct_or_union attribute_specifier_list LBRACE struct_declaration_list RBRACE
+| struct_or_union attribute_specifier_list other_identifier? LBRACE struct_declaration_list RBRACE
+| struct_or_union attribute_specifier_list other_identifier
{}
-| struct_or_union attribute_specifier_list i = general_identifier LBRACE struct_declaration_list RBRACE
-| struct_or_union attribute_specifier_list i = general_identifier
- { set_id_type i OtherId }
-| struct_or_union attribute_specifier_list LBRACE struct_declaration_list error
- { unclosed "{" "}" $startpos($3) $endpos }
-| struct_or_union attribute_specifier_list general_identifier LBRACE struct_declaration_list error
- { unclosed "{" "}" $startpos($4) $endpos }
struct_or_union:
| STRUCT
@@ -418,20 +510,20 @@ struct_declaration_list:
{}
struct_declaration:
-| specifier_qualifier_list struct_declarator_list? SEMICOLON
+| specifier_qualifier_list(struct_declaration) struct_declarator_list? SEMICOLON
{}
(* As in the standard, except it also encodes the constraint described
in the comment above [declaration_specifiers]. *)
-specifier_qualifier_list:
-| type_qualifier_list? i = typedef_name type_qualifier_list?
- { set_id_type i TypedefId }
-| type_qualifier_list? type_specifier_no_typedef_name specifier_qualifier_list_no_typedef_name?
+(* The phantom parameter can be [struct_declaration] or [type_name]. *)
+specifier_qualifier_list(phantom):
+| ioption(type_qualifier_list) typedef_name type_qualifier_list?
+| ioption(type_qualifier_list) type_specifier_no_typedef_name specifier_qualifier_no_typedef_name*
{}
-specifier_qualifier_list_no_typedef_name:
-| type_specifier_no_typedef_name specifier_qualifier_list_no_typedef_name?
-| type_qualifier specifier_qualifier_list_no_typedef_name?
+specifier_qualifier_no_typedef_name:
+| type_specifier_no_typedef_name
+| type_qualifier
{}
struct_declarator_list:
@@ -445,15 +537,9 @@ struct_declarator:
{}
enum_specifier:
-| ENUM attribute_specifier_list LBRACE enumerator_list COMMA? RBRACE
+| ENUM attribute_specifier_list other_identifier? LBRACE enumerator_list COMMA? RBRACE
+| ENUM attribute_specifier_list other_identifier
{}
-| ENUM attribute_specifier_list i = general_identifier LBRACE enumerator_list COMMA? RBRACE
-| ENUM attribute_specifier_list i = general_identifier
- { set_id_type i OtherId }
-| ENUM attribute_specifier_list LBRACE enumerator_list COMMA? error
- { unclosed "{" "}" $startpos($3) $endpos }
-| ENUM attribute_specifier_list general_identifier LBRACE enumerator_list COMMA? error
- { unclosed "{" "}" $startpos($4) $endpos }
enumerator_list:
| declare_varname(enumerator)
@@ -469,10 +555,14 @@ enumeration_constant:
| i = general_identifier
{ set_id_type i VarId; i }
-%inline type_qualifier:
+type_qualifier_noattr:
| CONST
| RESTRICT
| VOLATILE
+ {}
+
+%inline type_qualifier:
+| type_qualifier_noattr
| attribute_specifier
{}
@@ -484,8 +574,6 @@ attribute_specifier_list:
attribute_specifier:
| ATTRIBUTE LPAREN LPAREN gcc_attribute_list RPAREN RPAREN
| PACKED LPAREN argument_expression_list RPAREN
-(* TODO: slove conflict *)
-(* | PACKED *)
| ALIGNAS LPAREN argument_expression_list RPAREN
| ALIGNAS LPAREN type_name RPAREN
{}
@@ -507,8 +595,7 @@ gcc_attribute:
{ set_id_type i VarId }
gcc_attribute_word:
-| i = general_identifier
- { set_id_type i OtherId }
+| other_identifier
| CONST
| PACKED
{}
@@ -524,7 +611,7 @@ function_specifier:
low_prec : %prec lowPrec1 {}
declarator_identifier:
| PRE_NAME low_prec i = TYPEDEF_NAME
-| PRE_NAME i = VAR_NAME
+| i = var_name
{ i }
(* The semantic action returned by [declarator] is a pair of the
@@ -547,8 +634,7 @@ direct_declarator:
| i = declarator_identifier
{ set_id_type i VarId; (i, Decl_ident) }
| LPAREN save_context x = declarator RPAREN
- { x }
-| x = direct_declarator LBRACK type_qualifier_list? assignment_expression? RBRACK
+| x = direct_declarator LBRACK type_qualifier_list? optional(assignment_expression, RBRACK)
{ match snd x with
| Decl_ident -> (fst x, Decl_other)
| _ -> x }
@@ -562,9 +648,25 @@ direct_declarator:
| Decl_ident, None -> (fst x, Decl_krfun [])
| _ -> x }
-pointer:
-| STAR type_qualifier_list?
-| STAR type_qualifier_list? pointer
+(* The C standard defines [pointer] as a right-recursive list. We prefer to
+ define it as a left-recursive list, because this provides better static
+ context (that is, this changes the automaton in such a way that it is
+ easier to give good error messages, in at least 2 states).
+
+ The non-terminal symbol [pointer1] represents one list element.
+
+ [pointer], which represents a non-empty list of [pointer1]'s, is defined
+ as [pointer1* pointer1].
+
+ When the C standard writes [pointer?], which represents a possibly empty
+ list of [pointer1]'s, we write [pointer1*]. *)
+
+%inline pointer1:
+ STAR type_qualifier_list?
+ {}
+
+%inline pointer:
+ pointer1* pointer1
{}
type_qualifier_list:
@@ -586,31 +688,33 @@ parameter_list:
{}
parameter_declaration:
-| declaration_specifiers declare_varname(declarator)
-| declaration_specifiers abstract_declarator?
+| declaration_specifiers(parameter_declaration) declare_varname(declarator)
+| declaration_specifiers(parameter_declaration) abstract_declarator(parameter_declaration)?
{}
type_name:
-| specifier_qualifier_list abstract_declarator?
+| specifier_qualifier_list(type_name) abstract_declarator(type_name)?
{}
-abstract_declarator:
+(* The phantom parameter can be [parameter_declaration] or [type_name].
+ We take the latter to mean [type_or_name] or [direct_abstract_declarator].
+ We need not distinguish these two cases: in both cases, a closing parenthesis
+ is permitted (and we do not wish to keep track of why it is permitted). *)
+abstract_declarator(phantom):
| pointer
-| pointer? direct_abstract_declarator
+| ioption(pointer) direct_abstract_declarator
{}
direct_abstract_declarator:
-| LPAREN save_context abstract_declarator RPAREN
-| direct_abstract_declarator? LBRACK type_qualifier_list? assignment_expression? RBRACK
-| direct_abstract_declarator? LPAREN context_parameter_type_list RPAREN
+| LPAREN save_context abstract_declarator(type_name) RPAREN
+| direct_abstract_declarator? LBRACK type_qualifier_list? optional(assignment_expression, RBRACK)
+| ioption(direct_abstract_declarator) LPAREN context_parameter_type_list? RPAREN
{}
c_initializer:
| assignment_expression
| LBRACE initializer_list COMMA? RBRACE
{}
-| LBRACE initializer_list COMMA? error
- { unclosed "{" "}" $startpos($1) $endpos }
initializer_list:
| designation? c_initializer
@@ -627,9 +731,8 @@ designator_list:
designator:
| LBRACK constant_expression RBRACK
+| DOT other_identifier
{}
-| DOT i = general_identifier
- { set_id_type i OtherId }
statement:
| labeled_statement
@@ -642,8 +745,7 @@ statement:
{}
labeled_statement:
-| i = general_identifier COLON statement
- { set_id_type i OtherId }
+| other_identifier COLON statement
| CASE constant_expression COLON statement
| DEFAULT COLON statement
{}
@@ -651,29 +753,26 @@ labeled_statement:
compound_statement:
| ctx = save_context LBRACE block_item_list? RBRACE
{ ctx() }
-| ctx = save_context LBRACE block_item_list? error
- { ctx(); unclosed "{" "}" $startpos($2) $endpos }
block_item_list:
| block_item_list? block_item
{}
block_item:
-| declaration
+| declaration(block_item)
| statement
| PRAGMA
{}
expression_statement:
-| expression? SEMICOLON
+| ioption(expression) SEMICOLON
{}
jump_statement:
-| GOTO i = general_identifier SEMICOLON
- { set_id_type i OtherId }
+| GOTO other_identifier SEMICOLON
| CONTINUE SEMICOLON
| BREAK SEMICOLON
-| RETURN expression? SEMICOLON
+| RETURN ioption(expression) SEMICOLON
{}
asm_statement:
@@ -696,11 +795,15 @@ do_statement1:
iteration_statement:
| ctx = save_context WHILE LPAREN expression RPAREN statement
-| ctx = save_context FOR LPAREN expression? SEMICOLON expression? SEMICOLON expression? RPAREN statement
-| ctx = save_context FOR LPAREN declaration expression? SEMICOLON expression? RPAREN statement
| ctx = save_context do_statement1 WHILE LPAREN expression RPAREN SEMICOLON
+| ctx = save_context FOR LPAREN for_statement_header optional(expression, SEMICOLON) optional(expression, RPAREN) statement
{ ctx() }
+for_statement_header:
+| optional(expression, SEMICOLON)
+| declaration(block_item)
+ {}
+
asm_attributes:
| /* empty */
| CONST asm_attributes
@@ -729,20 +832,19 @@ asm_operand:
{}
asm_op_name:
-| /*empty*/ {}
-| LBRACK i = general_identifier RBRACK { set_id_type i OtherId }
+| /*empty*/
+| LBRACK other_identifier RBRACK
+ {}
asm_flags:
| string_literals_list
-| string_literals_list COMMA asm_flags
+| asm_flags COMMA string_literals_list
{}
translation_unit_file:
| translation_unit EOF
| EOF
{}
-| error
- { syntax_error $endpos }
translation_unit:
| external_declaration
@@ -753,7 +855,7 @@ translation_unit:
external_declaration:
| function_definition
-| declaration
+| declaration(external_declaration)
| PRAGMA
{}
@@ -763,15 +865,21 @@ identifier_list:
| l = identifier_list COMMA x = var_name
{ x::l }
+kr_param_declaration:
+| declaration_specifiers(declaration(block_item)) init_declarator_list? SEMICOLON
+ {}
+
declaration_list:
-| declaration
-| declaration_list declaration
+| kr_param_declaration
+| declaration_list kr_param_declaration
{}
function_definition1:
-| declaration_specifiers func = declare_varname(declarator_noattrend)
+| declaration_specifiers(declaration(external_declaration))
+ func = declare_varname(declarator_noattrend)
save_context attribute_specifier_list ctx = save_context
-| declaration_specifiers func = declare_varname(declarator_noattrend)
+| declaration_specifiers(declaration(external_declaration))
+ func = declare_varname(declarator_noattrend)
ctx = save_context declaration_list
{ begin match snd func with
| Decl_fun ctx -> ctx (); declare_varname (fst func)
diff --git a/cparser/tests/generated/Makefile b/cparser/tests/generated/Makefile
new file mode 100644
index 00000000..fb6e7610
--- /dev/null
+++ b/cparser/tests/generated/Makefile
@@ -0,0 +1,50 @@
+#######################################################################
+# #
+# The Compcert verified compiler #
+# #
+# François Pottier, INRIA Paris-Rocquencourt #
+# #
+# Copyright Institut National de Recherche en Informatique et en #
+# Automatique. All rights reserved. This file is distributed #
+# under the terms of the INRIA Non-Commercial License Agreement. #
+# #
+#######################################################################
+
+.PHONY: all clean
+
+SOURCES := $(wildcard *.c)
+TARGETS := \
+ $(patsubst %.c,%.ccomp.err,$(SOURCES)) \
+ $(patsubst %.c,%.gcc.err,$(SOURCES)) \
+ $(patsubst %.c,%.clang.err,$(SOURCES))
+
+CCOMP := ../../../ccomp
+GCC := gcc
+CLANG := clang
+
+all: $(TARGETS)
+
+clean:
+ @ rm -f *.err *~
+
+%.ccomp.err: %.c $(CCOMP)
+ @ echo $(CCOMP) -c $<
+ @ if $(CCOMP) -c $< 2>$@ ; then \
+ echo "UNEXPECTED SUCCESS: $(CCOMP) -c $< SUCCEEDED!" ; \
+ fi
+ @ if grep "unknown syntax error" $@ ; then \
+ echo "UNKNOWN SYNTAX ERROR!" ; \
+ fi
+
+%.gcc.err: %.c
+ @ echo $(GCC) -c $<
+ @ if $(GCC) -c $< 2>$@ ; then \
+ echo "UNEXPECTED SUCCESS: $(GCC) -c $< SUCCEEDED!" ; \
+ fi
+
+%.clang.err: %.c
+ @ echo $(CLANG) -c $<
+ @ if $(CLANG) -c $< 2>$@ ; then \
+ echo "UNEXPECTED SUCCESS: $(CLANG) -c $< SUCCEEDED!" ; \
+ fi
+
diff --git a/cparser/tests/handwritten/conditional-0.c b/cparser/tests/handwritten/conditional-0.c
new file mode 100644
index 00000000..4aeb4659
--- /dev/null
+++ b/cparser/tests/handwritten/conditional-0.c
@@ -0,0 +1,4 @@
+int main (int x, int y)
+{
+ return x == 0 ? x : y == 0 : y;
+}
diff --git a/cparser/tests/handwritten/conditional-1.c b/cparser/tests/handwritten/conditional-1.c
new file mode 100644
index 00000000..c6a5210a
--- /dev/null
+++ b/cparser/tests/handwritten/conditional-1.c
@@ -0,0 +1,4 @@
+int main (int x, int y)
+{
+ return x == 0 ? x : y == 0 ? y;
+}
diff --git a/cparser/tests/handwritten/dubious-enum.c b/cparser/tests/handwritten/dubious-enum.c
new file mode 100644
index 00000000..12ee6683
--- /dev/null
+++ b/cparser/tests/handwritten/dubious-enum.c
@@ -0,0 +1,7 @@
+int f (void)
+{
+ int x = sizeof(enum e;
+ /* Maybe a closing parenthesis is missing,
+ maybe also "enum e" could be continued with an opening brace.
+ Our message ignores the latter possibility. */
+}
diff --git a/cparser/tests/handwritten/missing-assignment.c b/cparser/tests/handwritten/missing-assignment.c
new file mode 100644
index 00000000..2fce2cbf
--- /dev/null
+++ b/cparser/tests/handwritten/missing-assignment.c
@@ -0,0 +1,4 @@
+int main (void)
+{
+ int x = 10, y 8;
+}
diff --git a/cparser/tests/handwritten/missing-closing-brace-at-end-of-function.c b/cparser/tests/handwritten/missing-closing-brace-at-end-of-function.c
new file mode 100644
index 00000000..dfb3691d
--- /dev/null
+++ b/cparser/tests/handwritten/missing-closing-brace-at-end-of-function.c
@@ -0,0 +1,10 @@
+int main (void)
+{
+ int x = 0;
+ x++;
+ /* missing closing brace, here */
+ /* unfortunately, the error is detected only after the declaration of f */
+
+void f (void)
+{
+}
diff --git a/cparser/tests/handwritten/missing-loop-body.c b/cparser/tests/handwritten/missing-loop-body.c
new file mode 100644
index 00000000..44781564
--- /dev/null
+++ b/cparser/tests/handwritten/missing-loop-body.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+ int x = 10;
+ while (x--) /* missing loop body */
+}
diff --git a/cparser/tests/handwritten/missing-operator.c b/cparser/tests/handwritten/missing-operator.c
new file mode 100644
index 00000000..d93e91f4
--- /dev/null
+++ b/cparser/tests/handwritten/missing-operator.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+ int y = 7, z = 8;
+ int x = (3 * (2 x) - y * y);
+}
diff --git a/cparser/tests/handwritten/missing-semicolon.c b/cparser/tests/handwritten/missing-semicolon.c
new file mode 100644
index 00000000..a655ca3b
--- /dev/null
+++ b/cparser/tests/handwritten/missing-semicolon.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+ int y = 7, z = 8
+ int x = (3 * (2 + x) - y * y);
+}
diff --git a/cparser/tests/handwritten/too-many-closing-parens.c b/cparser/tests/handwritten/too-many-closing-parens.c
new file mode 100644
index 00000000..68fe0b62
--- /dev/null
+++ b/cparser/tests/handwritten/too-many-closing-parens.c
@@ -0,0 +1,4 @@
+int main (void)
+{
+ int x = main());
+}
diff --git a/cparser/tests/handwritten/unclosed-paren.c b/cparser/tests/handwritten/unclosed-paren.c
new file mode 100644
index 00000000..b0ef6747
--- /dev/null
+++ b/cparser/tests/handwritten/unclosed-paren.c
@@ -0,0 +1,5 @@
+int main (void)
+{
+ int y = 7;
+ int x = (3 * (2 + x) - y * y;
+}
diff --git a/cparser/tests/handwritten/variable-type-confusion.c b/cparser/tests/handwritten/variable-type-confusion.c
new file mode 100644
index 00000000..0957ca9d
--- /dev/null
+++ b/cparser/tests/handwritten/variable-type-confusion.c
@@ -0,0 +1,6 @@
+typedef int t;
+typedef int u;
+int f (void) {
+ t = 3;
+}
+
diff --git a/cparser/validator/Alphabet.v b/cparser/validator/Alphabet.v
index 85a1689d..13718cd5 100644
--- a/cparser/validator/Alphabet.v
+++ b/cparser/validator/Alphabet.v
@@ -193,7 +193,7 @@ Program Instance NumberedAlphabet {A:Type} (N:Numbered A) : Alphabet A :=
{ AlphabetComparable :=
{| compare := fun x y => compare31 (inj x) (inj y) |};
AlphabetFinite :=
- {| all_list := fst (iter_int31 inj_bound _
+ {| all_list := fst (iter_int31 inj_bound _
(fun p => (cons (surj (snd p)) (fst p), incr (snd p))) ([], 0%int31)) |} }.
Next Obligation. apply Zcompare_antisym. Qed.
Next Obligation.
@@ -229,7 +229,7 @@ rewrite <- surj_inj_compat, <- phi_inv_phi with (inj x0), H0, phi_inv_phi; refle
replace (Zsucc (phi i)) with (2 ^ Z_of_nat size)%Z in H0 by omega.
rewrite Z_mod_same_full in H0.
exfalso; omega.
-exfalso; inversion Heqp; subst;
+exfalso; inversion Heqp; subst;
pose proof (phi_bounded (inj x)); change (phi 0) with 0%Z in H; omega.
clear H.
rewrite <- phi_inv_phi with i, <- phi_inv_phi with inj_bound; f_equal.
diff --git a/cparser/validator/Automaton.v b/cparser/validator/Automaton.v
index b15f87d2..98ab1246 100644
--- a/cparser/validator/Automaton.v
+++ b/cparser/validator/Automaton.v
@@ -113,7 +113,7 @@ Module Types(Import Init:AutInit).
(** Types used for the annotations of the automaton. **)
(** An item is a part of the annotations given to the validator.
- It is acually a set of LR(1) items sharing the same core. It is needed
+ It is acually a set of LR(1) items sharing the same core. It is needed
to validate completeness. **)
Record item := {
(** The pseudo-production of the item. **)
@@ -136,7 +136,7 @@ Module Type T.
Parameter start_nt: initstate -> nonterminal.
(** The action table maps a state to either a map terminal -> action. **)
- Parameter action_table:
+ Parameter action_table:
state -> action.
(** The goto table of an LR(1) automaton. **)
Parameter goto_table: state -> forall nt:nonterminal,
diff --git a/cparser/validator/Grammar.v b/cparser/validator/Grammar.v
index d162892d..0768d647 100644
--- a/cparser/validator/Grammar.v
+++ b/cparser/validator/Grammar.v
@@ -96,8 +96,8 @@ Module Defs(Import G:T).
Definition token := {t:terminal & symbol_semantic_type (T t)}.
(** A grammar creates a relation between word of tokens and semantic values.
- This relation is parametrized by the head symbol. It defines the
- "semantics" of the grammar. This relation is defined by a notion of
+ This relation is parametrized by the head symbol. It defines the
+ "semantics" of the grammar. This relation is defined by a notion of
parse tree. **)
Inductive parse_tree:
forall (head_symbol:symbol) (word:list token)
@@ -110,9 +110,9 @@ Module Defs(Import G:T).
parse_tree (T t)
[existT (fun t => symbol_semantic_type (T t)) t sem] sem
- (** Given a production, if a word has a list of semantic values for the
- right hand side as head symbols, then this word has the semantic value
- given by the semantic action of the production for the left hand side
+ (** Given a production, if a word has a list of semantic values for the
+ right hand side as head symbols, then this word has the semantic value
+ given by the semantic action of the production for the left hand side
as head symbol.**)
| Non_terminal_pt:
forall {p:production} {word:list token}
@@ -152,7 +152,7 @@ Module Defs(Import G:T).
Fixpoint pt_size {head_symbol word sem} (tree:parse_tree head_symbol word sem) :=
- match tree with
+ match tree with
| Terminal_pt _ _ => 1
| Non_terminal_pt _ _ _ l => S (ptl_size l)
end
diff --git a/cparser/validator/Interpreter.v b/cparser/validator/Interpreter.v
index 16be3859..2242065c 100644
--- a/cparser/validator/Interpreter.v
+++ b/cparser/validator/Interpreter.v
@@ -98,7 +98,7 @@ Fixpoint pop (symbols_to_pop:list symbol) (stack_cur:stack):
result (stack * A) :=
match symbols_to_pop return forall {A:Type} (action:arrows_right A (map _ symbols_to_pop)), _ with
| [] => fun A action => OK (stack_cur, action)
- | t::q => fun A action =>
+ | t::q => fun A action =>
match stack_cur with
| existT state_cur sem::stack_rec =>
match compare_eqdec (last_symb_of_non_init_state state_cur) t with
diff --git a/cparser/validator/Interpreter_complete.v b/cparser/validator/Interpreter_complete.v
index 3b922f7d..3d564c11 100644
--- a/cparser/validator/Interpreter_complete.v
+++ b/cparser/validator/Interpreter_complete.v
@@ -102,7 +102,7 @@ Variable buffer_end: Stream token.
Variable full_sem: symbol_semantic_type (NT (start_nt init)).
Inductive pt_zipper:
- forall (hole_symb:symbol) (hole_word:list token)
+ forall (hole_symb:symbol) (hole_word:list token)
(hole_sem:symbol_semantic_type hole_symb), Type :=
| Top_ptz:
pt_zipper (NT (start_nt init)) (full_word) (full_sem)
@@ -115,7 +115,7 @@ Inductive pt_zipper:
{wordq:list token}
{semantic_valuesq:tuple (map symbol_semantic_type head_symbolsq)},
parse_tree_list head_symbolsq wordq semantic_valuesq ->
-
+
ptl_zipper (head_symbolt::head_symbolsq) (wordt++wordq)
(semantic_valuet,semantic_valuesq) ->
@@ -134,11 +134,11 @@ with ptl_zipper:
{wordt:list token}
{semantic_valuet:symbol_semantic_type head_symbolt},
parse_tree head_symbolt wordt semantic_valuet ->
-
+
forall {head_symbolsq:list symbol}
{wordq:list token}
{semantic_valuesq:tuple (map symbol_semantic_type head_symbolsq)},
-
+
ptl_zipper (head_symbolt::head_symbolsq) (wordt++wordq)
(semantic_valuet,semantic_valuesq) ->
@@ -275,7 +275,7 @@ Fixpoint build_pt_dot {hole_symbs hole_word hole_sems}
(ptlz:ptl_zipper hole_symbs hole_word hole_sems)
:pt_dot :=
match ptl in parse_tree_list hole_symbs hole_word hole_sems
- return ptl_zipper hole_symbs hole_word hole_sems -> _
+ return ptl_zipper hole_symbs hole_word hole_sems -> _
with
| Nil_ptl => fun ptlz =>
Reduce_ptd ptlz
@@ -292,7 +292,7 @@ Fixpoint build_pt_dot {hole_symbs hole_word hole_sems}
end ptlz.
Lemma build_pt_dot_cost:
- forall hole_symbs hole_word hole_sems
+ forall hole_symbs hole_word hole_sems
(ptl:parse_tree_list hole_symbs hole_word hole_sems)
(ptlz:ptl_zipper hole_symbs hole_word hole_sems),
ptd_cost (build_pt_dot ptl ptlz) = ptl_size ptl + ptlz_cost ptlz.
@@ -307,7 +307,7 @@ simpl; rewrite <- plus_n_Sm, plus_assoc; reflexivity.
Qed.
Lemma build_pt_dot_buffer:
- forall hole_symbs hole_word hole_sems
+ forall hole_symbs hole_word hole_sems
(ptl:parse_tree_list hole_symbs hole_word hole_sems)
(ptlz:ptl_zipper hole_symbs hole_word hole_sems),
ptd_buffer (build_pt_dot ptl ptlz) = hole_word ++ ptlz_buffer ptlz.
@@ -321,7 +321,7 @@ simpl; rewrite build_pt_dot_buffer.
apply app_str_app_assoc.
Qed.
-Lemma ptd_stack_compat_build_pt_dot:
+Lemma ptd_stack_compat_build_pt_dot:
forall hole_symbs hole_word hole_sems
(ptl:parse_tree_list hole_symbs hole_word hole_sems)
(ptlz:ptl_zipper hole_symbs hole_word hole_sems)
@@ -354,8 +354,8 @@ Program Fixpoint pop_ptlz {hole_symbs hole_word hole_sems}
{ word:_ & { sem:_ &
(pt_zipper (NT (prod_lhs (ptlz_prod ptlz))) word sem *
parse_tree (NT (prod_lhs (ptlz_prod ptlz))) word sem)%type } } :=
- match ptlz in ptl_zipper hole_symbs hole_word hole_sems
- return parse_tree_list hole_symbs hole_word hole_sems ->
+ match ptlz in ptl_zipper hole_symbs hole_word hole_sems
+ return parse_tree_list hole_symbs hole_word hole_sems ->
{ word:_ & { sem:_ &
(pt_zipper (NT (prod_lhs (ptlz_prod ptlz))) word sem *
parse_tree (NT (prod_lhs (ptlz_prod ptlz))) word sem)%type } }
@@ -368,7 +368,7 @@ Program Fixpoint pop_ptlz {hole_symbs hole_word hole_sems}
end ptl.
Lemma pop_ptlz_cost:
- forall hole_symbs hole_word hole_sems
+ forall hole_symbs hole_word hole_sems
(ptl:parse_tree_list hole_symbs hole_word hole_sems)
(ptlz:ptl_zipper hole_symbs hole_word hole_sems),
let 'existT word (existT sem (ptz, pt)) := pop_ptlz ptl ptlz in
@@ -381,7 +381,7 @@ simpl; apply pop_ptlz_cost.
Qed.
Lemma pop_ptlz_buffer:
- forall hole_symbs hole_word hole_sems
+ forall hole_symbs hole_word hole_sems
(ptl:parse_tree_list hole_symbs hole_word hole_sems)
(ptlz:ptl_zipper hole_symbs hole_word hole_sems),
let 'existT word (existT sem (ptz, pt)) := pop_ptlz ptl ptlz in
@@ -414,14 +414,14 @@ Lemma pop_ptlz_pop_stack_compat:
(stack:stack),
ptlz_stack_compat ptlz stack ->
-
- let action' :=
- eq_rect _ (fun x=>x) (prod_action (ptlz_prod ptlz)) _
+
+ let action' :=
+ eq_rect _ (fun x=>x) (prod_action (ptlz_prod ptlz)) _
(pop_ptlz_pop_stack_compat_converter _ _ _ _ _)
in
let 'existT word (existT sem (ptz, pt)) := pop_ptlz ptl ptlz in
match pop (ptlz_past ptlz) stack (uncurry action' hole_sems) with
- | OK (stack', sem') =>
+ | OK (stack', sem') =>
ptz_stack_compat ptz stack' /\ sem = sem'
| Err => True
end.
@@ -503,8 +503,8 @@ pose proof (pop_ptlz_buffer _ _ _ Nil_ptl ptlz).
destruct (pop_ptlz Nil_ptl ptlz) as [word [sem [ptz pt]]].
rewrite H0; clear H0.
revert H.
-match goal with
- |- match ?p1 with Err => _ | OK _ => _ end -> match bind2 ?p2 _ with Err => _ | OK _ => _ end =>
+match goal with
+ |- match ?p1 with Err => _ | OK _ => _ end -> match bind2 ?p2 _ with Err => _ | OK _ => _ end =>
replace p1 with p2; [destruct p2 as [|[]]; intros|]
end.
assumption.
@@ -610,8 +610,8 @@ Qed.
Variable full_pt: parse_tree (NT (start_nt init)) full_word full_sem.
Definition init_ptd :=
- match full_pt in parse_tree head full_word full_sem return
- pt_zipper head full_word full_sem ->
+ match full_pt in parse_tree head full_word full_sem return
+ pt_zipper head full_word full_sem ->
match head return Type with | T _ => unit | NT _ => pt_dot end
with
| Terminal_pt _ _ => fun _ => ()
@@ -668,7 +668,7 @@ Qed.
Theorem parse_complete n_steps:
match parse init (full_word ++ buffer_end) n_steps with
| OK (Parsed_pr sem_res buffer_end_res) =>
- sem_res = full_sem /\ buffer_end_res = buffer_end /\
+ sem_res = full_sem /\ buffer_end_res = buffer_end /\
pt_size full_pt <= n_steps
| OK Fail_pr => False
| OK Timeout_pr => n_steps < pt_size full_pt
diff --git a/cparser/validator/Interpreter_correct.v b/cparser/validator/Interpreter_correct.v
index 095b26ca..3a285158 100644
--- a/cparser/validator/Interpreter_correct.v
+++ b/cparser/validator/Interpreter_correct.v
@@ -68,7 +68,7 @@ Qed.
Lemma pop_invariant:
forall (symbols_to_pop symbols_popped:list symbol)
(stack_cur:stack)
- (A:Type)
+ (A:Type)
(action:arrows_left (map symbol_semantic_type (rev_append symbols_to_pop symbols_popped)) A),
forall word_stack word_popped,
forall sem_popped,
@@ -96,12 +96,12 @@ destruct e; simpl.
dependent destruction H.
destruct H0, H1. apply (Cons_ptl X), inhabits in X0.
specialize (IHsymbols_to_pop _ _ _ action0 _ _ _ H X0).
-match goal with
+match goal with
IHsymbols_to_pop:match ?p1 with Err => _ | OK _ => _ end |- match ?p2 with Err => _ | OK _ => _ end =>
replace p2 with p1; [destruct p1 as [|[]]|]; intuition
end.
destruct IHsymbols_to_pop as [word1res [word2res [sem_full []]]]; intuition; subst.
-exists word1res.
+exists word1res.
eexists.
exists sem_full.
intuition.
diff --git a/cparser/validator/Validator_complete.v b/cparser/validator/Validator_complete.v
index 98559305..90ab1b0c 100644
--- a/cparser/validator/Validator_complete.v
+++ b/cparser/validator/Validator_complete.v
@@ -497,7 +497,7 @@ Qed.
(** The automaton is complete **)
Definition complete :=
- nullable_stable /\ first_stable /\ start_future /\ terminal_shift
+ nullable_stable /\ first_stable /\ start_future /\ terminal_shift
/\ end_reduce /\ non_terminal_goto /\ start_goto /\ non_terminal_closed.
Definition is_complete (_:unit) :=
diff --git a/cparser/validator/Validator_safe.v b/cparser/validator/Validator_safe.v
index 119f7337..c5229ac9 100644
--- a/cparser/validator/Validator_safe.v
+++ b/cparser/validator/Validator_safe.v
@@ -121,7 +121,7 @@ Qed.
Definition goto_head_symbs :=
forall s nt,
match goto_table s nt with
- | Some (exist s2 _) =>
+ | Some (exist s2 _) =>
prefix (past_symb_of_non_init_state s2) (head_symbs_of_state s)
| None => True
end.