yacc简介

来源:互联网 发布:php视频网站 编辑:程序博客网 时间:2024/06/05 04:11

Yacc

简介

Yacc是一个工具,它将任何一种编程语言的所有语法翻译成针对此钟语言的Yacc语法解析器。
它用巴克斯范式(BNF)来书写

步骤

  1. 运行yacc处理语法文件,生成一个解析器
  2. 说明语法:
    -编写.y语法文件
    -编写一个词法分析器来处理输入并将标记传递给处解析器。这里可以使用Lex完成。
    -编写一个函数,使用yyparse()开始解析
    -编写错误处理例程 如yaerror()
  3. 编译yacc生成的代码以及其他相关源文件
  4. 将目标文件链接到适当的可执行解析器库

编写

和LEX类似,yacc的程序也分为三段

    declarations    %%    rules    %%    programs

rules

yacc中最重要的是其中的文法规则,首先来看文法如何书写
yacc文法使用BNF巴克斯范式书写
如下:

    result: components { /*    action to be taken in C */ }        | components        |...    ;

{}中书写识别出该表达式所做的动作
例:

    param : NAME EQ NAME {        printf("\tName:%s\tValue(name):%s\n", $1,$3);}        | NAME EQ VALUE{        printf("\tName:%s\tValue(value):%s\n",$1,$3);}    ;

其中n使nlexeryylval$表示规约后的值。

标记 NAME 的 Lex 代码是这样的:

   char [A-Za-z]    name {char}+    %%    {name} { yylval = strdup(yytext); //strdup函数是使用malloc函数进行字符串的复制    return NAME; }

declarations

与LEX类似,使用C语言的声明,需要用

%{   balabala%}

来声明,包括include等等,其中需要定义YYSTYPE,它是内置变量yylval的类型,默认为int,例如:

%{    #typedef char* string; /*    to specify token types as char* */    #define YYSTYPE string /*    a Yacc variable which has the value of returned token */%}

用户经常会希望语义值的类型比较复杂,如双精度浮点数,字符串或树结点的指针.这时就可以用语义值类型定义进行说明。因为不同的语法符号的语义值类型可能不同,所以语义值类型说明就是将语义值的类型定义为一个联合(Union),这个联合包括所有可能用到的类型(各自对应一个成员名),为了使用户不必在存取语义值时每次都指出成员名,在语义值类型定义部分还要求用户说明每一个语法符号(终结符和非终结符)的语义值是哪一个联合成员类型。

% union{int ivaldouble dvalINTERVAL VVal;}%token <ival> DREG VREG%token <dval> CONST%type <dyal>dexp%type <vval>vexP

使用%union来定义一个联合类型,作为yylval的类型,当声明TOKEN和非终结符时,在中间加<…>来声明语义值的类型,非终结符不需要声明语义值时,不用刻意声明

声明终结符,即lexer返回的TOKEN:

%token NAME EQ AGE

每个 Yacc 声明段声明了终端符号和非终端符号(标记)的名称,还可能描述操作符优先级和针对不同符号的数据类型。

% start 非终结符……//声明文法起始符

如果没有上面的说明,yacc自动将语法规则部分中第一条语法规则左部的非终结符作为语法开始符。

%left '+' '-'%left '*' '/'

%left 表示左结合,%right 表示右结合。最后列出的定义拥有最高的优先权。因此乘法和除法拥有比加法和减法更高的优先权。+ - * / 所有这四个算术符都是左结合的。运用这个简单的技术,我们可以消除文法的歧义。

在表达式中有时要用到一元运算符,而且它可能与某个二元运算符是同一个符号,例如一元运算符负号“-”就与减号’-’相同,显然一元运算符的优先级应该比相应的二元运算符的优先级高。至少应该与’*’的优先级相同,这可以用yacc的%Prec子句来定义,请看下面的文法:

%token NAME%left '-''+’%left '*''/'%%expr;expr'+' expr|expr'+' expr|expr'-’expr|expr'*' expr|expr'/’ expr|'-'expr %prec'*'|NAME;

在上述文法中,为使一元’-’的优先级与’*’相同,我们使用了子句

%prec’*’

它说明它所在的语法规则中最右边的运算符或终结符的优先级与%Prec后面的符号的优先级相同,注意%Prec子句必须出现在某语法规则结尾处分号之前,%prec子句并不改变’-’作为二元运算符时的优先级。

programs

    void main()    {        yyparse();    }    int yyerror(char* msg)  //用户可以自己实现错误函数    {    printf("Error: %s    encountered \n", msg);

programs

    void main()    {        yyparse();    }    int yyerror(char* msg)  //用户可以自己实现错误函数    {    printf("Error: %s    encountered \n", msg);

参考

LEX和YACC的使用
Yacc 与 Lex 快速入门

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子爱打人怎么办 6招 一岁宝宝爱打人怎么办 2岁小朋友爱打人怎么办 小朋友爱动手怎么办4岁 5,6岁爱动手打人怎么办 七个月宝宝大便干燥怎么办 两岁宝宝吐奶怎么办 2岁宝宝轻微蛀牙怎么办 2岁宝宝喝水都吐怎么办 2岁宝宝吐的厉害怎么办 两岁宝宝个子矮怎么办 宝宝吐了一天了怎么办 3岁宝宝吃饭呕吐怎么办 3岁宝宝突然呕吐怎么办 11个月婴儿呕吐怎么办 2岁宝宝呕吐是怎么办 2岁宝宝呕吐腹泻怎么办 七个月的宝宝拉肚子怎么办 两岁宝宝玩手机怎么办 5岁宝宝突然口吃怎么办 3岁宝宝突然口吃怎么办 2岁半宝宝结巴怎么办 卤门2岁未闭合怎么办 宝宝2岁说话结巴怎么办 4岁半的宝宝口臭怎么办 2岁宝宝口气重怎么办 2岁宝宝有口气怎么办 2岁宝宝头大怎么办 2周宝宝讲话结巴怎么办 宝贝烧到39度怎么办 4岁宝宝有点口吃怎么办 不小心建了群聊怎么办 宝宝着凉了吐奶怎么办 宝宝便秘肛裂了怎么办 1岁多的宝宝便秘怎么办 8个月小宝宝便秘怎么办 跟他说话不说话怎么办 天猫客服不回复怎么办 三岁宝宝不说话怎么办 六个月宝宝粘人怎么办 11个月宝宝粘人怎么办