简体   繁体   English

为什么生成的解析器这么慢?

[英]Why is generated parser so slow?

I was playing around on PEG.js in an attempt to create a parser that is able to take a string and create an object. 我在玩PEG.js ,试图创建一个能够接受字符串并创建对象的解析器。

For example, take the string "a&b" and create: 例如,使用字符串“ a&b”并创建:

{type:"operator",value:operator, children:[a, b]}

However, I have reached the stage where returning a result can take over 10 seconds if there are two or more nests. 但是,我已经到达了一个阶段,如果有两个或多个嵌套,则返回结果可能需要10秒钟以上。

The test argument I have been using is: 我一直在使用的测试参数是:

(All a (All a (All a b)))

The grammar does return the right answer, but takes far too long. 语法确实返回了正确的答案,但是花费的时间太长。 My question is, what is causing this time delay for such a simple parse? 我的问题是,是什么原因导致如此简单的解析时间延迟?

It is possible to try and edit the grammar online at PEG.js 可以尝试在PEG.js上在线编辑语法

My grammar is: 我的语法是:

start = sep* All:All sep* {return All} 

All = sep* operator:"All" sep* xValue: Ex sep* pValue: Ex{return {type:"operator",value:operator, children:[xValue, pValue]}} /Ex

Ex = sep* operator:"Ex" sep* xValue: AND sep* pValue: AND {return {type:"operator",value:operator, children:[xValue, pValue]}} /AND

AND= left: Plus  sep* operator:"&" sep* right:AND {return {type:"operator", value:operator, children:[left,right]}} / Plus 

Plus = left: Equals sep* operator:"+" sep* right:Plus{return {type:"operator", value:operator, children:[left,right]}}/ Equals 

Equals = left:GEQ sep* operator:"=" sep* right:Equals{return {type:"operator", value:operator, children:[left,right]}}/GEQ

GEQ = left:implication  sep* operator:">=" sep* right:GEQ{return {type:"operator", value:operator, children:[left,right]}}/implication 

implication = left:OR sep* operator:"->" sep* right:implication{return {type:"operator", value:operator, children:[left,right]}}/OR 

OR =  left:Not  sep* operator:"|" sep* right:OR{return {type:"operator", value:operator, children:[left,right]}}/Not  

Not = sep* operator:"¬" sep* right:Suc{return {type:"operator", value:operator, children:[right]}}/Suc

Suc = sep* operator:"suc" sep* right:primary{return {type:"operator", value:operator, children:[right]}}/primary 

primary  = letter:letter{return {type:"variable", value:letter}}/ "{" sep* All:All sep* "}" {return All}/"(" sep* All:All sep* ")" {return All} 

sep = spaces:[' ',\\t] 

letter  = "false"/"0"/letters:[A-Za-z]

I'd guess it has something to do with all of your sep* s. 我猜想这与您所有的sep* s有关。 If you look at the examples in Bryan Ford's original PEG paper, the only rule that starts with white space is the first. 如果查看Bryan Ford原始PEG论文中的示例,则唯一以空白开头的规则是第一个。 He then logically breaks his grammar up so that the lexical portion (token rules) is at the bottom, each token definition followed by white space. 然后,他在逻辑上分解语法,以使词汇部分(令牌规则)位于底部,每个令牌定义后跟空白。 I think it'll solve your problem, but even if it doesn't, it'll make it more readable (and probably easier to fix). 我认为它可以解决您的问题,但是即使不能解决,也可以使其更具可读性(并且可能更易于修复)。

For example: 例如:

    start = SPACING All:All
    All   = operator:All_op xValue:Ex pValue: Ex
          / Ex
    Ex    = operator:Ex_op xValue:AND pValue:AND
    /* etc. */


    /* Lexical Portion */
    All_op = 'All' SPACING
    Ex_op  = 'Ex'  SPACING

    SPACING = [ \t]*

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM