为什么 PEGjs / 无法正常工作?

Why is PEGjs / not working correctly?

我在 PEGjs 中有一个简单的解析器

start = val
ln = [\n\r]
float = digits:$[-0-9\.]+ { return parseFloat(digits, 10) }
str = str:$(!ln !"\"" .)+
val = float / str

我试着匹配

-this

但它没有得到 "str",而是在解析 "float"

时出错
Line 1, column 2: Expected [\-0-9.] or end of input but "t" found.

float = digits:$([-0-9.]+ !str) { return parseFloat(digits, 10) }

这就解决了。但这与我过去在编写 350 行解析器时学到的东西非常违反直觉...

问题是 - 在某些解析器中称为 "leading set" 的 float 所以解析器不知道接下来的内容不是 float,愉快地继续并尝试解析一个。由 PEGjs 实现的解析器的解析表达式语法样式不会在符号内进行回溯。

避免这种情况的唯一方法是向解析器提供有关您尝试执行的操作的更多信息,以避免通过在 [=15= 的前导集中允许 - 而引入的前导集歧义] 和 float。您可以通过另一种方式解决此问题,即强制解析器在看到 - 后要求 [0-9]+。事实上,我怀疑你的语法没有准确地表示你想要完成的事情,因为它也允许像 0123-456123.456-789.987.123 这样的字符串作为 float。您需要 强制将 - 作为 float 的可选第一个字符,然后需要一串数字才能使其正确浮动。

我建议你这样写你的语法:

start = val
ln = [\n\r]
float = digits:$('-'? [0-9]+ '.'? [0-9]*
               / '-'? '.' [0-9]+) { return parseFloat(digits, 10) }
str = str:$(!ln !"\"" .)+
val = float / str

float的第一部分捕获小数点前有数字或小数点缺失的情况。第二部分捕获小数点前没有数字但存在的情况,并在这种情况下强制执行小数点后数字的要求。

您拥有 val = float / str 而不是 val = str / float 这一事实也很重要。在尝试匹配 str 之前,您必须先尝试匹配 float 才能正常工作。我不太确定 str 的定义,但我不知道您要解析的语言。