【发布时间】:2018-09-26 07:57:13
【问题描述】:
我正在尝试编写一个 Bison C++ 解析器来解析 JavaScript 文件,但我不知道如何使分号成为可选。
对于 ECMAScript 2018 规范(https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf,第 11.9 章),分号实际上不是可选的,而是在解析过程中自动插入。在规范中指出:
当从左到右解析源文本时,遇到一个标记(称为违规标记),它是 语法的任何产生都不允许,然后在违规之前自动插入分号 如果以下一个或多个条件为真,则令牌:
- 有问题的令牌与前一个令牌之间至少有一个 LineTerminator[...]
据此,我正在尝试以这种幼稚的方式解决这个问题:
- 检测错误,使用
error特殊标记; - 告诉词法分析器在操作过程中发生了语法错误;如果在当前标记之前遇到换行符,则词法分析器将在下一次
yylex调用时返回一个新的分号标记;在随后的调用中,它将返回之前发生语法错误时出现问题的令牌。
我的解析器的一个非常简化的结构如下:
program:
stmt_list END
;
stmt_list:
%empty
| stmt_list stmt
| stmt_list error { /* error detected; tell the lexer about the syntax error */ }
;
stmt:
value SEMICOLON
| [other types of statements...]
;
value:
NUMBER
| STRING
;
但是这样做,如果文件包含一个没有终止分号但有换行符的有效 JavaScript 语句,当遇到违规标记时,解析器会将语句的其余部分缩减为一个 error 特殊标记。当我告诉词法分析器有关语法错误时,解析器已经将error 标记减少为stmt_list 一个,并且先前的有效指令丢失,使得分号插入无用。
显然我不想让我的解析器丢弃有效语句并转到下一个。
我怎样才能做到这一点?这是正确的方法还是我错过了什么?
【问题讨论】:
标签: javascript c++ bison error-recovery