解析器是否必须使用所有文本输入流?



我正在构建一个解析器生成器,目前它接受自定义语法,并生成一个C程序来解析文本流并生成graphviz树表示。

在我定义示例语法的实验中,我发现在某些情况下,解析被终止,但并非所有文本输入流都已被消耗。我用'terminated'表示语法中的主要规则已被求值为真。

是否应该修改语法以始终使用解析器来处理所有源输入文本?

谢谢


我的用例是要完全解析的单个文本文件。只是一个简单的语法示例:

Main_rule: ID ID* ;
// ID is Terminal (a C variable token)
// Source text follows
var1 var2 123 var3

我的C解析器在123(不是ID)之前停止解析,但在主规则中求值为true,并且文本输入流没有完全解析。

我可以做一些调整修改语法(语言),如果我添加一个任意的结束标记。即

main_rule: ID ID* END_TOKEN;

与此类问题一样,答案是"这取决于用例"。

通常,解析器将使用整个文本,但并不总是清楚"整个文本"的含义。在某些情况下,一个已解析的文本流嵌入到另一个文本流中,并且终止不是文件结束(或字符串结束)标记。

在某些情况下,通过首先提取嵌入内容,然后解析提取的字符串,可以最方便地发现嵌入内容的范围。然而,这需要扫描嵌入的字符串两次,通常情况下存在更有效的解决方案。此外,在某些情况下,如果不进行标记,确实没有办法发现嵌入内容的结尾;例如,考虑解析嵌入式$( & help;在shell表达式内的)子shell

解析嵌入式语言是复杂的,并且通常没有优雅的解决方案。使用传统的扫描器/解析器二分法通常更容易处理这种复杂性,在这种二分法中,嵌入完全在扫描器内部处理,可能使用对另一个解析器的递归调用。在这种情况下,解析器本身并不直接处理输入,扫描器负责生成"输入结束"标记。

如果在完全解析的前缀末尾出现意外文本,则必须将其标记为错误。因此,解析器至少需要能够与它的调用者通信,是否已经消耗了整个输入,如果没有,则确切地知道还需要消耗什么。

显式的"end- input"标记的存在允许完全的灵活性;如果语法需要"输入结束"(以start': start END_OF_INPUT的形式生成),那么解析的文本当然必须在输入结束时终止。然后,用户可以自由定义不需要解析整个输入文本的语法。但是这种灵活性是有代价的:在正常情况下,用户需要添加显式的增强启动生产,而naïve用户很可能会忘记这样做。bison/yacc(自动增强启动生产)和lemon(如果需要,用户必须提供增强启动生产)是这两种模型之间的区别的例子。

最新更新