我在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.
答案 0 :(得分:0)
问题在于-
是某些解析器人称为float
的“前导集”,因此解析器不知道后面的内容不是float
,欢快地去试图解析一个。 PEGjs实现的解析器的解析表达式语法风格不会在符号内进行回溯。
避免这种情况的唯一方法是通过在-
的前导集合中允许str
来为解析器提供有关您尝试执行的操作的更多信息,以避免引入的主要集合歧义在float
。您可以通过强制解析器在看到[0-9]+
后需要-
来解决此问题。事实上,我怀疑你的语法没有准确地表示你想要完成的事情,因为它允许0123-456
或123.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的行解析器时学到的东西非常违反直觉......