1

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

2 回答 2

0

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

那解决了它。但这与我过去在编写 350 行解析器时所学的内容非常违反直觉......

于 2015-03-10T16:11:41.290 回答
0

问题在于,-某些解析器人员称之为“领先集”,float因此解析器不知道后面的不是 a float,而是愉快地继续尝试解析一个。由 PEGjs 实现的解析器的 Parsing Expression Grammar 样式不会在符号内进行回溯。

避免这种情况的唯一方法是向解析器提供更多信息,说明您正在尝试做什么,以避免通过允许-在前导集 ofstr和 in 中引入的前导集歧义float。您可以通过强制解析器[0-9]+在看到-. 实际上,我怀疑您的语法不能准确地表示您想要完成的内容,因为它也允许使用0123-456or123.456-789.987.123之类的字符串float。您需要强制将-a 作为可选的第一个字符,float然后需要一串数字才能使其正确浮动。

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

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

The first part of float captures the case where there are digits before the decimal point or the decimal point is missing. The second part captures the case where there are no digits before the decimal point, but it is present, and it enforces the requirement of digits after the decimal point in this case.

The fact that you have val = float / str rather than val = str / float is critical also. You have to try to match a float before you try to match a str for this to work. I'm not really sure about that definition for str, but I don't know the language you're trying to parse.

于 2016-10-11T19:00:43.733 回答