yacc 语法文件声明

yacc 语法文件的声明部分包含以下内容:

  • 语法文件的其他部分所使用的任何变量或者常量的声明
  • 将其他文件作为本文件的一部分使用的 #include 语句(用于库头文件)
  • 定义生成的解析器的处理条件的语句

如果用户定义的 C 语言并集的成员与语法文件中的各种名称相关联,您就能够将与当前在语法分析堆栈上的标记关联的语义信息保存在并集中。

变量或者常量的声明使用下面的 C 编程语言语法:
TypeSpecifier Declarator ;

TypeSpecifier 是数据类型关键字,Declarator 是变量或者常量的名称。 名称可为任意长度,可包含字母、点、下划线和数字。 名称不可以数字开始。 区分大写和小写字母。

可以使用以下命令声明终端 (或令牌) 名称:%token 声明,非终端名称可以使用%type 声明。 该%非终端名称不需要 type 声明。 如果非终止名称出现在至少一条规则的左边,那么它们将被自动定义。 您可以将该名称仅作为非终止符号使用,无需在声明部分声明名称。 该#include 语句与 C 语言语法相同,并执行相同的函数。

yacc 程序有关键字集合,这些关键字定义生成的解析器的处理条件。 每个关键字都以%(百分号) ,后跟令牌或非终端名称。 这些关键字如下:

关键词 描述
%向左 标识与其他标记左关联的标记。

%非指定 标识不与其他标记关联的标记。

%向右 标识与其他标记右关联的标记。

%开始 标识起始符号的非终止符名称。

%令牌/标记 (token) 标识 yacc 命令接受的标记名称。 请在声明部分声明所有的标记名称。

%TYPE 标识非终止符的类型。 当此构造存在时,将执行类型检查。

%UNION 将 yacc 值堆栈标识为所需值的各种不同类型的并集。 缺省情况下,返回值为整数。 此构造的效果是直接从输入提供 YYSTYPE 的声明。

%{
Code
%}
将指定的代码复制到代码文件中。 此构造可用来将 C 语言声明和定义添加到声明部分。
注:%{(百分号,左括号) 和%}(百分号,右括号) 符号必须独自出现在行上。
%token%%right%nonassoc 关键字 (可选) 支持 C 联合成员的名称 (由以下对象定义)%union) 调用了<标记>(联合成员名周围的文字尖括号)。 该%type 关键字需要<标记>. 使用<标记>指定在行上指定的标记将与所引用的并集成员具有相同的 C 类型<标记>例如,以下声明将 Name 参数声明为令牌:
%token [<Tag>] Name [Number] [Name [Number]]...

如果<标记>存在,将此行上所有标记的 C 类型声明为由以下对象引用的类型:<标记>。如果正整数 Number跟在 Name 参数后面,那么会将该值分配给令牌。

同一行中的所有标记都具有相同的优先级和关联性。 行按照上升的优先顺序或者绑定强度出现在文件中。 例如,下面描述了四个算术运算符的优先顺序和关联性:
%left '+' '-'
%left '*' '/'

+(加号) 和-(减号) 是左关联的,其优先顺序低于*(星号) 和/(斜杠) ,它们也是左关联的。

定义全局变量

要定义要由某些或所有操作以及词法分析器使用的变量,请将这些变量的声明括在%{(百分号,左括号) 和%}(百分号,右括号) 符号。 括在这些符号中的声明称为全局变量。 例如,要使 var 变量对于整个程序的所有部分均可用,请在语法文件的声明部分使用下面的项:

%{
int var = 0;
%}

启动条件

解析器能识别称为起始符号的特殊符号。 起始符号是语法文件的规则部分中的规则名,该文件描述了要进行语法分析的语言最通用的结构。 因为它是最通用的结构,所以解析器在这一点开始自顶向下分析输入流。 使用以下命令在声明部分中声明开始符号:%start 关键字。 如果您不声明起始符号的名称,那么解析器会使用语法文件中的第一条语法规则的名称。

例如,当对 C 语言函数进行语法分析时,解析器能识别的最通用的结构如下:
main()
{
        code_segment
}

起始记号指向描述此结构的规则。 文件中剩下的所有规则描述了标识函数中较低级别结构的方式。

标记号

标记号是非负整数,它们代表标记名称。 如果词法分析器将标记号而不是实际的标记名称传递给解析器,那么两个程序都必须同意指定给标记的号码。

您可为 yacc 语法文件中使用的标记指定号码。 如果您不为标记指定号码,那么 yacc 语法文件使用下面的规则指定号码:
  • 文字字符是 ASCII 字符集中字符的数字值。
  • 从 257 开始为其他的名称指定标记号。
    注: 请勿分配令牌号 0。 此数字将分配给结束标记令牌。 您不可对它重新定义。

要在语法文件的声明部分中为令牌 (包括字面值) 指定数字,请将正整数 (而不是 0) 紧跟在令牌名称之后,%token行。 此整数为名称或者文字的标记号。 每个标记号必须是唯一的。 当与 yacc 命令一起使用的所有词法分析器到达它们的输入的末尾时,它们必须为标记返回 0 或者负值。