以GCC8.2.0版本为例,介绍gcc语法解析器(parser)对声明即函数定义的解析过程以及structure/union的简单解析说明。
1. GCC中声明和定义的解析过程
1.1 解析入口 c_parse_file
GCC中gcc/c/c-parser.c文件主要负责解析GNU C的完整语法。其中单个源码文件的解析入口在void c_parse_file (void)函数中,函数代码如下:

先对c_parser struct进行初始化,再判断其pragma_kind。代码中的c_parser_translation_unit函数主要为解析当前translation unit(TU)。最后每一个parser解析完成时会被置为NULL,又开始解析下一个源文件。
其中一个c_parser对应着一个.c文件,c_parser struct解析器结构记录了相关解析状态和上下文的信息,以及词法分析器信息等,其代码如下:

1.2 解析TU c_parser_translation_unit
translation unit是gcc整个语法产生式的开始点,其注释说明如下:
/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
translation-unit:
external-declarations
external-declarations:
external-declaration
external-declarations external-declaration
GNU extensions:
translation-unit:
empty
*/
函数中ggc_collect函数进行一些顶级标记和清除处理,c_parser_external_declaration函数中进行非终结符语法解析,代码如下:

1.3 外部声明 c_parser_external_declaration
根据解析c_parser的&parser->tokens[0]->type执行不同规则的流程,即不同的语法产生式会走不同的执行路径。部分代码如下:

1.4 声明解析 c_parser_declaration_or_fndef
该方法首先会收集构建成声明或函数定义的信息,然后将它们组合成一个声明。其主要信息包含声明说明符(c_declspecs)、声明符(c_declarator),初始化值,参数列表等。该方法中首先根据build_null_declspecs方法创建一个structure的空declaration specifiers list,其后进行一系列的解析和处理操作。总体来说一个完整的声明包括start_decl、finish_decl两部分,其中一个非常重要的结构体是c_declspecs,主要用于在解析过程中存放声明信息。
build_null_declspecs函数代码如下:

c_declspecs struct的定义如下:
/* A sequence of declaration specifiers in C. When a new declaration
specifier is added, please update the enum c_declspec_word above
accordingly. */
struct c_declspecs {
source_location locations[cdw_number_of_elements];
/* The type specified, if a single type specifier such as a struct,
union or enum specifier, typedef name or typeof specifies the
whole type, or NULL_TREE if none or a keyword such as "void" or
"char" is used. Does not include qualifiers. */
tree type;
/* Any expression to be evaluated before the type, from a typeof
specifier. */
tree expr;
/* The attributes from a typedef decl. */
tree decl_attr;
/* When parsing, the attributes. Outside the parser, this will be
NULL; attributes (possibly from multiple lists) will be passed
separately. */
tree attrs;
/* The pass to start compiling a __GIMPLE or __RTL function with. */
char *gimple_or_rtl_pass;
/* The base-2 log of the greatest alignment required by an _Alignas
specifier, in bytes, or -1 if no such specifiers with nonzero
alignment. */
int align_log;
/* For the __intN declspec, this stores the index into the int_n_* arrays. */
int int_n_idx;
/* For the _FloatN and _FloatNx declspec, this stores the index into
the floatn_nx_types arr

最低0.47元/天 解锁文章
1214

被折叠的 条评论
为什么被折叠?



