zoukankan      html  css  js  c++  java
  • Lex与Yacc学习(九)之Yacc语法

    Yacc语法

    本文讨论yacc语法的格式并描述可用的各种特征和选项

    yacc语法结构

    yacc语法包括三部分:定义段、规则段和用户子例程段

    ...定义段...

    %%

    ...规则段...

    %%

    ...用户子例程段...

    各部分由以两个百分号开头的行分开,尽管某一个部分可以为空,但是前两部分是必须的,第三部分和前面的百分号可以省略。

    符号

    yacc 语法由符号组成,即语法的“词”。符号是一串不以数字开头的字母、数字、句点和下划线。符号error专用于错误恢复,另外,yacc对任何符号都不会附加“先验”的意义。

    由词法分析程序产生的符号叫做终结符号或者标记。定义在规则左侧的叫做非终结符号或者非终结。标记也可能是字面上引用的字符,通常遵循约定:标记大写,非终结符号小写。

    定义段

    定义段包括文字块,逐字拷贝到生成的C文件开头部分的C代码,通常包括声明和#include行。可能有%union  %start   %token   %type   %left  %right  和 %nonassoc声明。

    也可以包含普通的C语言风格的注释,所有这些都是可选的,在简单的语法分析程序中,定义段可能完全是空的。

    规则段

    规则段由语法规则和包括C代码的动作组成。

    用户子例程段

    yacc 将用户子例程段的内容完全拷贝到C文件中,通常这部分包括从动作调用的例程。

    动作

    动作是yacc与在语法中规则相符时执行的C代码,动作一定是C复合语句。

    通过使用后面跟有数字的美元符号,动作可以查阅在规则中与符号有关的值,冒号后面跟的第一个符号是数字1,例如:

    date:month  '/'  day   '/'  year
    
                                              { printf ("date %d-%d-%d  found",$1,$3,$5);}

    而名字,$$是指冒号左边符号的值,符号值可以有不同的C类型。

    歧义和冲突

    由于语法有歧义或者包含冲突,yacc对于语法规范的翻译可能会失败。一些情况下,语法确实有歧义,也就是说对于一个单独的输入字符串有两种可能的分析而且yacc处理不了。

    另外一些情况,语法并无歧义,但yacc使用的语法分析技术不足以分析这个语法。

    移进/归约冲突

    当一个输入字符串有两种可能的分析时,而且其中一个分析完成一个规则(归约选项),而另一个却没有(移进选项)时,移进/归约冲突便发生了。

    例如:

    %%
    
    e:                   ‘X’
    
                           |   e  '+'   e
    
                           ;

    对于输入字符串“X+X+X” ,有两种可能的分析: “(X+X)+X”或者“X+(X+X)”,采用归约选项使得语法分析程序使用第一个分析,而采用移进选项则使用另一个。


    归约/归约冲突

    当同样的标记可以完成两个不同的规则时,就会发生归约/归约冲突。

    例如:

    %%
    
    prog:    proga | progb
    
    proga:       'X' ;
    
    progb:       'Y' ;

    一个“X”可能是proga,也可能是progb。

    大多数归约/归约冲突没这么明显,但是几乎在任何情况下它们在语法中都表现为错误。

    特殊字符

    由于yacc处理符号标记而不是文本,它的输入字符集比起lex来说就简单的多,下面列出了yacc所使用的特殊符号的列表:

    %

    具有两个%标记的行将yacc语法分成了几部分;

    定义段的所有声明都是以%开始,包括%{ %}    %union  %start   %token   %type   %left  %right  和 %nonassoc声明。

    反斜线符号是废弃的百分号同义词,在动作中,C语言字符串中有其通常作用。

    $

    在动作中,美元符号引入一个值引用,举例来说,$3表示规则右端第3个符号的值。

    '

    文字标记由一个单引号结束,例如 'z' 。

    <>

    在一个动作的值引用中,可以不考虑尖括号包围起来的默认类型。

    "

    有些yacc版本在文字标记中将单引号和双引号同等对待,这样使用根本不方便。

    {}

    动作中C代码在大括号中。

    ;

    除了后面紧接着是以竖线开头的规则外,规则部分每个都是以分号结束。

    |

    当连续两个规则具有相同的左端,第二个规则可用一个 | 代替符号和冒号。

    :

    在每一条规则里,左端的每个符号后面都跟着一个冒号。

    _

    符号可以包括和字母、数字以及句点在一起的下划线。

    .

    符号可以包括与字母、数字、下划线一起的句点。

    =

    早期版本使用,现已不推荐。






  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/shine-yr/p/5214968.html
Copyright © 2011-2022 走看看