yacc 语法文件

要使用 yacc 命令生成解析器,请为其提供描述输入数据流和解析器将如何处理数据的语法文件。

语法文件包括的规则描述了输入结构、当这些规则被识别时要调用的代码以及用来处理基本输入的子例程。

yacc 命令使用语法文件中的信息生成控制输入过程的解析器。 此解析器调用输入子例程(词法分析器)从输入流检取基本项(称为标记)。 标记是告诉解析器输入子例程正在将哪一种模式发送给它的符号或者名称。 非终止符号是解析器识别的结构。 解析器根据语法文件中的结构规则组织这些标记。 结构规则被称为语法规则。 当解析器识别这些规则中的一条时,它就执行为该规则提供的用户代码。 用户代码称为操作。 操作返回值并使用其他操作返回的值。

请使用 C 编程语言写操作码和其他子例程。 yacc 命令对语法文件使用很多 C 语言语法转换。

main 和 yyerror 子例程

您必须为解析器提供 mainyyerror 子例程。 为了简化使用 yacc 命令的初始操作, yacc 库包含 mainyyerror 子例程的简化版本。 通过对 ld 命令 (或 cc 命令) 使用 -ly 参数来包含这些子例程。 main 库程序的源代码如下:
#include <locale.h>
main()
{
     setlocale(LC_ALL, "");
     yyparse();
}
yyerror 库程序的源代码如下:
#include <stdio.h>
yyerror(s)
        char *s;
{
        fprintf( stderr, "%s\n" ,s);
}

yyerror 子例程的自变量是包含错误消息的字符串,通常是字符串syntax error.

因为这些程序被限制,请在这些子例程中提供更多函数。 例如,记录输入行号,当检测到语法错误时将它与消息一起显示出来。 您可能还想使用外部整型变量 yychar 的值。 此变量在检测到错误时包含先行标记号。

yylex 子例程

您为语法文件提供的输入子例程必须能执行以下操作:

  • 读输入流。
  • 识别输入流中的基本模式。
  • 将模式和定义解析器模式的标记一起传递给解析器。

例如,输入子例程将输入流分隔为以下对象的标记:WORD, NUMBERPUNCTUATION,并接收以下输入:

I have 9 turkeys.

程序可选择将下面的字符串和标记传递给解析器:

String 标记
I WORD
have WORD
9 编号
turkeys WORD
. PUNCTUATION

解析器必须包含输入子例程传递给它的标记的定义。 使用 yacc 命令的 -d 选项,它会在名为 y.tab.h的文件中生成令牌列表。 此列表是一组 #define 语句,允许词法分析器 (yylex) 使用与解析器相同的标记。

注: 为了避免与解析器冲突,请勿使用以字母 yy开头的子例程名称。

您可以使用 lex 命令生成输入子例程,或者您可用 C 语言写例程。