GCC-3.4.6源代码学习笔记(87)

5.11. 解析编译单元入口

C++的语法可以以树的形式显示(当然,我们需要把父节点的递归处理为子节点,绝大部分这样的情况,我们在图中标记为红色)。树的根及起点是translation-unit(编译单元)。在下面的图中,可以看到构建C++解析器不是一件容易的工作。更有甚者,标准提供的语法,本质上,是左递归的。为了能够使用解析器构建器(parser builder)来构建解析器,需要把它转换为右递归形式,来顾及由底向上的LR解析器。即便有了右递归的语法,构建LR(1)解析器依然相当的困难。因此GCC采用了手写的尝试性LL(n)解析器——它支持回溯。毫无疑问,浏览这个解析器将是一个漫长的旅途。让我们出发!

GCC-3.4.6源代码学习笔记(87)_第1张图片

43声明的语法树

GCC-3.4.6源代码学习笔记(87)_第2张图片

44:类语法树

GCC-3.4.6源代码学习笔记(87)_第3张图片

45:语句语法树

c_parser_file的主体是cp_parser_translation_unit。根据【3】,编译单元的简要语法树如下:

translation-unit

  declaration-seq [opt] —— declaration-seq declaration

     declaration

在这个简要的视图中,一个编译单元仅包含一系列的声明。在C++中,编译单元通常包括一个源文件及多个头文件。从这个编译单元编译器将产生出目标文件,而后链接器将这些目标文件链接起来形成目的文件(target file)。

 

2319 static bool

2320 cp_parser_translation_unit (cp_parser* parser)                                             in parser.c

2321 {

2322   while (true)

2323   {

2324     cp_parser_declaration_seq_opt (parser);

2325

2326     /* If there are no tokens left then all went well.  */

2327     if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))

2328       break;

2329      

2330     /* Otherwise, issue an error message.  */

2331     cp_parser_error (parser, "expected declaration");

2332     return false;

2333   }

2334

2335  /* Consume the EOF token.  */

2336   cp_parser_require (parser, CPP_EOF, "end-of-file");

2337  

2338   /* Finish up.  */

2339   finish_translation_unit ();

2340

2341   /* All went well.  */

2342   return true;

2343 }

 

注意上面的WHILE,正常的处理是经2328行的break跳到2336行,这样就可以避免使用goto

 

 

你可能感兴趣的:(工作,File,gcc,token,编译器,translation)