aboutsummaryrefslogtreecommitdiffstats
path: root/cparser/pre_parser.mly
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/pre_parser.mly
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/pre_parser.mly')
-rw-r--r--cparser/pre_parser.mly396
1 files changed, 252 insertions, 144 deletions
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)