我试图通过在PEG.js playground中输入简单的语法来围绕PEG。

示例1:

  • 输入:"abcdef1234567ghijklmn8901opqrs"
  • 所需的输出:["abcdef", "1234567", "ghijklmn", "8901", "opqrs"]
  • 实际输出:["abcdef", ["1234567", ["ghijklmn", ["8901", ["opqrs", ""]]]]]

  • 这个例子几乎可以用,但是我可以让PEG.js不将结果数组嵌套到一百万个级别吗?我认为诀窍是在某处使用concat()而不是join(),但我找不到位置。
    start
      = Text
    
    Text
      = Numbers Text
      / Characters Text
      / EOF
    
    Numbers
      = numbers: [0-9]+ {return numbers.join("")}
    
    Characters
      = text: [a-z]+ {return text.join("")}
    
    EOF
      = !.
    

    示例2:

    与示例1相同的问题和代码,但是将“字符”规则更改为以下内容,我希望这会产生相同的结果。
    Characters
      = text: (!Numbers .)+ {return text.join("")}
    

    结果输出为:
    [",a,b,c,d,e,f", ["1234567", [",g,h,i,j,k,l,m,n", ["8901", [",o,p,q,r,s", ""]]]]]
    

    为什么我得到所有这些空的比赛?

    示例3:

    最后一个问题。这根本不起作用。我该如何运作?对于奖励积分,是否有效率指标?例如,如果可能,我应该避免递归吗?

    我也很高兴链接到一个好的PEG教程。我已阅读(http://www.codeproject.com/KB/recipes/grammar_support_1.aspx),但是如您所见,我需要更多帮助...
  • 输入:'abcdefghijklmnop"qrstuvwxyz"abcdefg'
  • 所需的输出:["abcdefghijklmnop", "qrstuvwxyz", "abcdefg"]
  • 实际输出:"abcdefghijklmnop\"qrstuvwxyz\"abcdefg"
  • start
      = Words
    
    Words
      = Quote
      / Text
      / EOF
    
    Quote
      = quote: ('"' .* '"') Words {return quote.join("")}
    
    Text
      = text: (!Quote . Words) {return text.join("")}
    
    EOF
      = !.

    最佳答案

    我在PEG.js Google网上论坛收到了回复,这有助于我走上正确的道路。我正在发布所有这三个问题的答案,希望它们可以作为像我这样的其他PEG初学者的入门教程。请注意,不需要递归。

    范例1:

    一旦您了解了基本的PEG习惯用法,这便很简单。

    start
      = Text+
    
    Text
      = Numbers
      / Characters
    
    Numbers
      = numbers: [0-9]+ {return numbers.join("")}
    
    Characters
      = text: [a-z]+ {return text.join("")}
    

    范例2:

    这里的问题是PEG.js解析器生成器中针对Peek表达式(&expr和!expr)的特殊设计选择。两者都在不消耗任何字符的情况下窥视输入流,因此我错误地认为它们没有返回任何内容。但是,它们都返回一个空字符串。我希望PEG.js的作者可以更改此行为,因为(据我所知)这只是不必要的残料,会污染输出流。如果我错了,请纠正我!

    无论如何,这是一种解决方法:
    start
      = Text+
    
    Text
      = Numbers
      / Words
    
    Numbers
      = numbers: [0-9]+ {return numbers.join("")}
    
    Words
      = text: Letter+ {return text.join("")}
    
    Letter
      = !Numbers text: . {return text}
    

    范例3:

    问题是像('"' .* '"')这样的表达式永远无法成功。 PEG总是很贪婪,因此.*将占用其余的输入流,而永远不会看到第二个引号。这是一个解决方案(顺便需要与示例2相同的Peek解决方法)。
    start
      = Words+
    
    Words
      = QuotedString
      / Text
    
    QuotedString
      = '"' quote: NotQuote* '"' {return quote.join("")}
    
    NotQuote
      = !'"' char: . {return char}
    
    Text
      = text: NotQuote+ {return text.join("")}
    

    关于javascript - 使用PEG.js的简单解析问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3612836/

    10-09 03:40