PEG解析匹配至少一个保留顺序

时间:2016-02-22 10:46:45

标签: parsing ebnf peg grako

鉴于PEG规则:

rule = element1:'abc' element2:'def' element3:'ghi' ;

我如何重写这一点,使其至少与其中一个元素匹配,但可能同时强制执行其命令?

即。我想匹配以下所有行:

abc def ghi
abc def
abc     ghi
    def ghi
abc
    def
        ghi

但不是空字符串或错误的表达式,例如def abc

当然有三个元素,我可以在不同的规则中拼出组合,但随着元素数量的增加,这就容易出错。

有没有办法以简洁的方式指定它?

2 个答案:

答案 0 :(得分:1)

您可以使用选项:

rule = [element1:'abc'] [element2:'def'] [element3:'ghi'] ;

您将使用rule的语义操作来检查至少有一个令牌匹配:

def rule(self, ast):
    if not (ast.element1 or ast.element2 or ast.element3):
        raise FailedSemantics('Expecting at least one token')
    return ast

另一种选择是使用几种选择:

rule 
    = 
       element1:'abc' [element2:'def'] [element3:'ghi'] 
    | [element1:'abc']  element2:'def' [element3:'ghi'] 
    | [element1:'abc'] [element2:'def'] element3:'ghi' 
    ;

缓存会使后者与前者一样高效。

然后,您可以添加 cut 元素以获得更高的效率和更有意义的错误消息:

rule 
    = 
       element1:'abc' ~  [element2:'def' ~] [element3:'ghi' ~] 
    | [element1:'abc' ~]  element2:'def' ~  [element3:'ghi' ~] 
    | [element1:'abc' ~] [element2:'def' ~] element3:'ghi'  ~
    ;

或:

rule = [element1:'abc' ~] [element2:'def' ~] [element3:'ghi' ~] ;

答案 1 :(得分:1)

答案是:分离的一个先决条件,然后是一系列的选项。

rule = &(e1 / e2 / e3) e1? e2? e3?

这是标准PEG,含有&意思是“必须存在但不能消费”和?意思是'可选'。如果没有这些符号,大多数PEG解析器都具有这些功能。