我正在尝试编写一个 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
一个,并且先前的有效指令丢失了,使得分号插入无用。
显然我不想让我的解析器丢弃有效的语句并转到下一个语句。
我怎样才能做到这一点?这是正确的方法还是我错过了什么?