昨天我们开始设计了一门新语言,制定了基本的开发架构,今天我们就先来了解一下,两个非常好用的工具,编译器前端构建的神器——Lex&Yacc,这两个工具在linux下叫做flex和bison。
Lex是词法分析器构建工具,我们安装对应的词法规则书写,那么就能够为我们生成对应的词法分析器,自动帮我们分好token,而分词工作,一直是编译系统的基础任务。
我们今天,先来尝试编写一个BNF语法的解析器,将我们的BNF解析成代码可以识别的数据格式,BNF的格式大概是这样:
{
{ do_init() }}
# 定义列表
<definelist> = <definelist> <define> | e ;
<define> = <constdef> | <vardef> | <functiondef> ;
# 变量和常量定义
<constdef> = "const" <const_def_run> <vardef> {
{ isconstdef = false }} ;
<vardef> = "int" <iddeflist> ";" ;
<iddeflist> = <iddeflist> "," <iddef> | <iddef> ;
这里就是我们的原始输入文件了,我们希望将其解析成为内存中的树结构,供我们的编译器使用,目前的任务就是,读入这样的文本,解析成树状结构。
这里我们可以发现,这种定义方式就是扩展BNF范式,而其中添加了语义动作的脚本{
{ }}
,脚本也可以单独使用,用来做一些初始化工作等。
利用词法分析程序处理单词
我们先看一下基本的Lex扫描器如何编写:
/* scanner.l */
%{
#include <stdio.h>
#include "parser.hpp"
#define SAVE_TOKEN yylval.str = yytext
extern "C" int yywrap() { return 1; }
%}
/* show the line number */
%option yylineno
%%
"/*"([^\*]|(\*)*[^\*/])