/*鼠标点击特效*/

构建词法、语法分析器

这里通过使用2个工具(Flex和Bison)来构造词法、语法分析程序,语法正确后生成抽象语法树。

词法

按Flex要求的格式,编辑Lex.l文件(这里文件名可以自行定义,但扩展名一定要是.l),使用Flex编译后即可得到词法分析源程序Lex.yy.c,其中通过调用 yylex()进行词法分析,每当识别出一个单词,将该单词的(单词种类码,单词的自身值)输出或提供给语法分析程序;

语法

按Bison要求的格式,编辑Parser.y文件(这里文件名可以自行定义,但扩展名一定要是.y),使用Bison编译后即可得到语法法分析源程序Parser.tab.c,其中调用
parser()进行语法分析。

工作流程

二者联合完成词法与语法分析时,要统一单词的种类编码,这时可将各个单词在parser.y中逐个以标识符的形式,通过%token罗列出来,作为语法规则的终结符,同时用Bison编译后,生成一个文件Parser.tab.h,该文件中将这些标识符作为枚举常量,每一个就对应一个(类)单词。这些枚举常量提供给Lex.l使用,每一个对应一个单词的种类码;同时在Parser.y中,这些枚举常量,每一个对应一个终结符。联合使用FLEX和Bison构造词法、语法分析器的工作流程图示意图如图所示。

这个流程中,以语法分析作为主体,在语法分析过程中,每当需要读入下一个符号(单词)时,调用词法分析器,得到一个单词的(单词种类码,单词的自身值),其控制流程如图2-2所示。

/*实验参考书籍《编译原理实践与指导教程》、《Flex&Bison》*/
/*yylineno记录行号*/
%option yylineno
/*声明部分*/
%{
    #include "parser.tab.h"	/*bison编译parser.y产生的文件*/
    #include <string.h>
    #include "def.h"		/*自定义数据结构、函数头文件*/
    int yycolumn = 1;
    #define YY_USER_ACTION yylloc.first_line=yylloc.last_line=yylineno; yylloc.first_column=yycolumn; yylloc.last_column=yycolumn+yyleng-1; yycolumn+=yyleng;
    typedef union{
        int type_int;
        float type_float;
        char type_char;
        char type_id[32];
        struct node *ptr;
    }YYLVAL;
    #define YYSTYPE YYLVAL
%}

/*辅助定义*/
id [A-Za-z][A-Za-z0-9]*
int [0-9]+
float ([0-9]*\.[0-9]+)|([0-9]+\.)


/*规则部分:正规表达式+动作, 词法分析器识别出一个单词后,将该单词对应的字符串保存在 yytext中,其长度为yyleng*/
/* 通过yylval.type_int=atoi(yytext);将整常数的值保存在yylval的成员type_int中,这里 yylval 是一个 Flex 和 Bison 共用的内部变量,类型为 YYLVAL,按这样的方式,在 Flex 中通过 yylval 的成员保存单词属性值,在 Bison 中就可以通过yylval 的成员取出属性值,实现了数据的传递*/
%%
 /*注释处理 单行+多行*/
\/\/[^\n]*  {;}	//匹配注释的正则表达式
\/\*(\s|.)*?\*\/ {;}//匹配注释的正则表达式
{int} {yylval.type_int=atoi(yytext);return INT;}
{float} {yylval.type_float=atof(yytext); return FLOAT;}
"int" {strcpy(yylval.type_id,yytext); return TYPE;}
"float" {strcpy(yylval.type_id,yytext); return TYPE;}
"char" {strcpy(yylval.type_id,yytext); return TYPE;}
"return" {return RETURN;}
"if" {return IF;}
"else" {return ELSE;}
"while" {return WHILE;}
"for" {return FOR;}
{id} {strcpy(yylval.type_id,yytext); return ID;}

";" {return SEMI;}
"," {return COMMA;}
">"|"<"|">="|"<="|"=="|"!=" {strcpy(yylval.type_id,yytext); return RELOP;}
"=" {return ASSIGNOP;}
"+" {return PLUS;}
"-" {return MINUS;}
"+=" {return COMADD;}
"-=" {return COMSUB;}
"++" {return AUTOADD;}
"--" {return AUTOSUB;}
"*" {return STAR;}
"/" {return DIV;}
"&&" {return AND;}
"||" {return OR;}
"!" {return NOT;}
"(" {return LP;}
")" {return RP;}
"[" {return LB;}
"]" {return RB;}
"{" {return LC;}
"}" {return RC;}
[\n] {yycolumn=1;}
[ \r\t] {;}
.   {printf("Error type A: Mysterious character\"%s\" at line %d,column %d\n",yytext,yylineno,yycolumn);}/*输出词法分析错误编号、异常符号串、错误行列号*/


%%
/* 复制到lex.yy.c中,冲突不能用了
void main(int argc,char *argv[]){
    yylex();
    return;
}
*/
int yywrap(){
    return 1;
}
posted @ 2020-11-13 11:51  干饭啦  阅读(408)  评论(0编辑  收藏  举报