为什么PEGjs /不能正常工作?

时间:2015-03-06 08:51:36

标签: pegjs

我在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.

2 个答案:

答案 0 :(得分:0)

问题在于-是某些解析器人称为float的“前导集”,因此解析器不知道后面的内容不是float,欢快地去试图解析一个。 PEGjs实现的解析器的解析表达式语法风格不会在符号内进行回溯。

避免这种情况的唯一方法是通过在-的前导集合中允许str来为解析器提供有关您尝试执行的操作的更多信息,以避免引入的主要集合歧义在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的事实也很重要。在尝试匹配float之前,您必须尝试匹配str才能生效。我对str的定义不太确定,但我不知道你要解析的语言。

答案 1 :(得分:-1)

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

修复了它。但这与我在编写一个350ish的行解析器时学到的东西非常违反直觉......