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代码在大括号中。

    ;

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

    |

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

    :

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

    _

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

    .

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

    =

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






  • 相关阅读:
    runAllManagedModulesForAllRequests 和 invalid url
    zip file 压缩文件
    asp.net framework identity 学习笔记
    angular2 学习笔记 (Typescript)
    angular2 学习笔记 ( DI 依赖注入 )
    angular2 学习笔记 ( rxjs 流 )
    Visual Studio and Visual Studio Code (vscode)
    FluentValidation
    想提高面试通过率?回答好这10个问题征服面试官
    【拿来就用】20款婚礼婚庆网站模板, 轻松打造幸福满满的网站设计
  • 原文地址:https://www.cnblogs.com/shine-yr/p/5214968.html
Copyright © 2011-2022 走看看