📄 cpp5.y
字号:
foo : sizeof(foo + 1);
*/
bit_field_identifier_declarator:
':' constant_expression
| identifier_declarator {} ':' constant_expression
;
enum_name_elaboration:
global_opt_scope_opt_enum_key '{' enumerator_list '}'
| enum_name '{' enumerator_list '}'
;
/* As with structures, the distinction between "elaborating" and
"non-elaborating" enum types is maintained. In actuality, it
probably does not cause much in the way of conflicts, since a ':'
is not allowed. For symmetry, we maintain the distinction. The
{} actions are intended to allow the symbol table to be updated.
These updates are significant to code such as:
enum A { first=sizeof(A)};
*/
enum_name:
global_opt_scope_opt_enum_key tag_name
;
global_opt_scope_opt_enum_key:
ENUM
| global_or_scope ENUM
;
enumerator_list:
enumerator_list_no_trailing_comma
| enumerator_list_no_trailing_comma ',' /* C++, not ANSI C */
;
/* Note that we do not need to rush to add an enumerator to the
symbol table until *AFTER* the enumerator_value_opt is parsed.
The enumerated value is only in scope AFTER its definition is
complete. Hence the following is legal: "enum {a, b=a+10};" but
the following is (assuming no external matching of names) is not
legal: "enum {c, d=sizeof(d)};" ("d" not defined when sizeof was
applied.) This is notably contrasted with declarators, which
enter scope as soon as the declarator is complete. */
enumerator_list_no_trailing_comma:
enumerator_name enumerator_value_opt
| enumerator_list_no_trailing_comma ',' enumerator_name enumerator_value_opt
;
enumerator_name:
IDENTIFIER
| TYPEDEFname
;
enumerator_value_opt:
/* Nothing */
| '=' constant_expression
;
/* We special case the lone type_name which has no storage class
(even though it should be an example of a parameter_type_list).
This helped to disambiguate type-names in parenthetical casts.*/
parameter_type_list:
'(' ')' type_qualifier_list_opt
| '(' type_name ')' type_qualifier_list_opt
| '(' type_name initializer ')' type_qualifier_list_opt /* C++, not ANSI C */
| '(' named_parameter_type_list ')' type_qualifier_list_opt
;
/* The following are used in old style function definitions, when
a complex return type includes the "function returning" modifier.
Note the subtle distinction from parameter_type_list. These
parameters are NOT the parameters for the function being defined,
but are simply part of the type definition. An example would be:
int(*f( a ))(float) long a; {...}
which is equivalent to the full new style definition:
int(*f(long a))(float) {...}
The type list `(float)' is an example of an
old_parameter_type_list. The bizarre point here is that an old
function definition declarator can be followed by a type list,
which can start with a qualifier `const'. This conflicts with
the new syntactic construct for const member functions!?! As a
result, an old style function definition cannot be used in all
cases for a member function. */
old_parameter_type_list:
'(' ')'
| '(' type_name ')'
| '(' type_name initializer ')' /* C++, not ANSI C */
| '(' named_parameter_type_list ')'
;
named_parameter_type_list: /* WARNING: excludes lone type_name*/
parameter_list
| parameter_list comma_opt_ellipsis
| type_name comma_opt_ellipsis
| type_name initializer comma_opt_ellipsis /* C++, not ANSI C */
| ELLIPSIS /* C++, not ANSI C */
;
comma_opt_ellipsis:
ELLIPSIS /* C++, not ANSI C */
| ',' ELLIPSIS
;
parameter_list:
non_casting_parameter_declaration
| non_casting_parameter_declaration initializer /* C++, not ANSI C */
| type_name ',' parameter_declaration
| type_name initializer ',' parameter_declaration /* C++, not ANSI C */
| parameter_list ',' parameter_declaration
;
/* There is some very subtle disambiguation going on here. Do
not be tempted to make further use of the following production in
parameter_list, or else the conflict count will grow noticeably.
Specifically, the next set of rules has already been inline
expanded for the first parameter in a parameter_list to support a
deferred disambiguation. The subtle disambiguation has to do with
contexts where parameter type lists look like old-style-casts. */
parameter_declaration:
type_name
| type_name initializer /* C++, not ANSI C */
| non_casting_parameter_declaration
| non_casting_parameter_declaration initializer /* C++, not ANSI C */
;
/* There is an LR ambiguity between old-style parenthesized casts
and parameter-type-lists. This tends to happen in contexts where
either an expression or a parameter-type-list is possible. For
example, assume that T is an externally declared type in the
code:
int (T ((int
it might continue:
int (T ((int)0));
which would make it:
(int) (T) (int)0 ;
which is an expression, consisting of a series of casts.
Alternatively, it could be:
int (T ((int a)));
which would make it the redeclaration of T, equivalent to:
int T (dummy_name (int a));
if we see a type that either has a named variable (in the above
case "a"), or a storage class like:
int (T ((int register
then we know it can't be a cast, and it is "forced" to be a
parameter_list.
It is not yet clear that the ANSI C++ committee would decide to
place this disambiguation into the syntax, rather than leaving it
as a constraint check (i.e., a valid parser would have to parse
everything as though it were a parameter list (in these odd
contexts), and then give an error if is to a following context
(like "0" above) that invalidated this syntax evaluation. */
/* One big thing implemented here is that a TYPEDEFname CANNOT be
redeclared when we don't have declaration_specifiers! Notice that
when we do use a TYPEDEFname based declarator, only the "special"
(non-ambiguous in this context) typedef_declarator is used.
Everything else that is "missing" shows up as a type_name. */
non_casting_parameter_declaration: /*have names or storage classes */
declaration_specifier
| declaration_specifier abstract_declarator
| declaration_specifier identifier_declarator
| declaration_specifier parameter_typedef_declarator
| declaration_qualifier_list
| declaration_qualifier_list abstract_declarator
| declaration_qualifier_list identifier_declarator
| type_specifier identifier_declarator
| type_specifier parameter_typedef_declarator
| basic_type_name identifier_declarator
| basic_type_name parameter_typedef_declarator
| TYPEDEFname identifier_declarator
| TYPEDEFname parameter_typedef_declarator
| global_or_scoped_typedefname identifier_declarator
| global_or_scoped_typedefname parameter_typedef_declarator
| type_qualifier_list identifier_declarator
;
type_name:
type_specifier
| basic_type_name
| TYPEDEFname
| global_or_scoped_typedefname
| type_qualifier_list
| type_specifier abstract_declarator
| basic_type_name abstract_declarator
| TYPEDEFname abstract_declarator
| global_or_scoped_typedefname abstract_declarator
| type_qualifier_list abstract_declarator
;
initializer_opt:
/* nothing */
| initializer
;
initializer:
'=' initializer_group
;
initializer_group:
'{' initializer_list '}'
| '{' initializer_list ',' '}'
| assignment_expression
;
initializer_list:
initializer_group
| initializer_list ',' initializer_group
;
/*************************** STATEMENTS *******************************/
statement:
labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
| declaration /* C++, not ANSI C */
;
labeled_statement:
label ':' statement
| CASE constant_expression ':' statement
| DEFAULT ':' statement
;
/* I sneak declarations into statement_list to support C++. The
grammar is a little clumsy this way, but the violation of C
syntax is heavily localized */
compound_statement:
'{' statement_list_opt '}'
;
declaration_list:
declaration
| declaration_list declaration
;
statement_list_opt:
/* nothing */
| statement_list_opt statement
;
expression_statement:
comma_expression_opt ';'
;
selection_statement:
IF '(' comma_expression ')' statement
| IF '(' comma_expression ')' statement ELSE statement
| SWITCH '(' comma_expression ')' statement
;
iteration_statement:
WHILE '(' comma_expression_opt ')' statement
| DO statement WHILE '(' comma_expression ')' ';'
| FOR '(' comma_expression_opt ';' comma_expression_opt ';'
comma_expression_opt ')' statement
| FOR '(' declaration comma_expression_opt ';'
comma_expression_opt ')' statement /* C++, not ANSI C */
;
jump_statement:
GOTO label ';'
| CONTINUE ';'
| BREAK ';'
| RETURN comma_expression_opt ';'
;
/* The following actions should update the symbol table in the
"label" name space */
label:
IDENTIFIER
| TYPEDEFname
;
/***************************** EXTERNAL DEFINITIONS *****************************/
translation_unit:
/* nothing */
| translation_unit external_definition
;
external_definition:
function_declaration /* C++, not ANSI C*/
| function_definition
| declaration
| linkage_specifier function_declaration /* C++, not ANSI C*/
| linkage_specifier function_definition /* C++, not ANSI C*/
| linkage_sp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -