yacc 命令生成的解析器操作

yacc 命令将语法文件转换为 C 语言程序。

当程序被编译并执行时,会根据提供的语法规则对输入进行语法分析。

解析器是带有堆栈的有限状态机。 解析器可以读出并记住预测标记。 当前状态始终是位于堆栈顶部的状态。 有限状态机的状态用小整数表示。 最初,机器处于状态 0,堆栈仅包含 0 且不读出预测标记。

机器能够执行下面的一个操作:
操作 描述
shift 状态 解析器将当前状态送入堆栈,使得 State 为当前状态,并清除预测标记。
reduce 规则 当解析器在输入流中查找 Rule (规则号)定义的字符串时,解析器用输出流中的 Rule 替换该字符串。
accept 解析器查看所有的输入,将其匹配到语法规则并将输入识别为满足(启动符号定义的)最高级别的结构。 仅当预测标记为结束符时才出现此操作,指示解析器已经成功完成它的作业。
错误 解析器无法继续处理输入流并仍然成功将它与语法规范中定义的任何规则匹配。 解析器查看的输入标记以及预测标记的后面不能有任何会产生有效输入的内容。 解析器报告错误,试图恢复状态并继续语法分析。

解析器在一个进程步骤中执行下面的操作:

  1. 基于其当前状态,解析器决定它是否需要预测标记来决定要采取的操作。 如果解析器需要预测标记但并不具有预测标记,那么它将调用 yylex 子例程来获得下一个标记。
  2. 通过使用当前状态和预测标记(如果需要),解析器决定其下一个操作并执行。 结果是状态可能被推送到堆栈或是被弹出堆栈,预测标记可能被处理或者留下。

Shift 操作

移位操作是解析器执行的最普遍的操作。 当解析器进行移位时,总是存在预测标记。 例如,考虑下面的语法说明规则:
IF shift 34
如果解析器处于包含此规则的状态,并且预测标记为IF,解析器:
  1. 将当前状态推送到堆栈上。
  2. 使状态34当前状态 (将其置于堆栈的顶部)。
  3. 清除预测标记。

减少操作

操作使得堆栈无法变得太大。 解析器在将规则右侧与输入流匹配之后使用减操作。 然后解析器准备使用规则左侧替换输入流中的字符。 解析器可能必须使用预测标记决定模式是否完全匹配。

减操作与个别的语法规则关联。 因为语法规则也有小整数,所以很容易混淆 移位 (shift)减 (reduce) 两个操作中的数字的意义。 例如,以下操作引用语法规则18:
. reduce 18
以下操作引用状态34:
IF shift 34
例如,要减少下面的规则,解析器从堆栈中弹出顶部的三个状态:
A  :  x y z ;

弹出的状态号等于规则右侧的标记号。 这些状态是在识别时放在堆栈上的状态x,yz. 弹出这些状态后,将发现一个状态,即解析器在开始处理规则之前所处的状态; 即需要识别规则的状态A以满足其规则。 通过使用此未覆盖状态和规则左侧的符号,解析器将执行名为 goto的操作,这类似于A获取新状态,将其推送到堆栈上,然后继续进行解析。

goto 操作与标记的普通移位不同。 预测标记被移位清除,但是不受 goto 操作影响。 当弹出三个状态时,发现的状态包含如下的项:
A  goto 20

此条目导致状态20将其推送到堆栈上并成为当前状态。

在处理用户提供的操作和值时,减操作也很重要。 当规则被减时,解析器在调整堆栈之前执行您包含在规则中的代码。 与存放状态的堆栈并行运行的另一个堆栈存放词法分析器和操作返回的值。 当发生移位时,yylval 外部变量被复制到存放值的堆栈。 在执行您提供的代码之后,解析器执行减。 当解析器执行 goto 操作时,它将 yylval 外部变量复制到值堆栈上。 以以下内容开头的 yacc 关键字$请参阅值堆栈。