zoukankan      html  css  js  c++  java
  • 构建词法、语法分析器

    这里通过使用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 的成员取出属性值,实现了数据的传递*/
    %%
     /*注释处理 单行+多行*/
    //[^
    ]*  {;}	//匹配注释的正则表达式
    /*(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;}
    [
    ] {yycolumn=1;}
    [ 
    	] {;}
    .   {printf("Error type A: Mysterious character"%s" at line %d,column %d
    ",yytext,yylineno,yycolumn);}/*输出词法分析错误编号、异常符号串、错误行列号*/
    
    
    %%
    /* 复制到lex.yy.c中,冲突不能用了
    void main(int argc,char *argv[]){
        yylex();
        return;
    }
    */
    int yywrap(){
        return 1;
    }
    
  • 相关阅读:
    【数据结构】KMP算法
    【数据结构】银行问题
    ejs模板渲染页面
    node的知识点
    http搭建服务器
    http接收页面传递的数据
    http模块
    node的http模块
    node的fs模块
    base.css
  • 原文地址:https://www.cnblogs.com/CSE-kun/p/13968622.html
Copyright © 2011-2022 走看看