使用backtrack选项时,编译器的性能急剧下降

迈克·施密特(Maik Schmidt)

我已经在Windows7上使用ANTLR3的C#版本为类C语言实现了Transpiler。

为了解析if / else语句,我使用以下规则:

ifStatement
: 'if' '(' expression ')' b1=block
   (
       'else' b2=block      -> ^('if' expression $b1 $b2 'else')
   |   'else' ifStatement   -> ^('if' expression $b1 ^(ELSIF ifStatement))
   |                        -> ^('if' expression $b1)
   )
;

要将此规则生成的树从我自己的语言转换为C#,我使用以下语法片段:

ifStatement
options { backtrack = true; }
: 
     ^(n='if' expression b1=block)
     -> if(
          node={$n},
          cond={$expression.st},
          block1={$b1.st},
          block2={null},
          isElsif={($n.Parent.Text == "ELSIF") ? "true" : null},
          node2={null}
        )
|
     ^(n='if' expression b1=block b2=block n2='else')
     -> if(
          node={$n},
          cond={$expression.st},
          block1={$b1.st},
          block2={$b2.st},
          isElsif={($n.Parent.Text == "ELSIF") ? "true" : null},
          node2={$n2}
        )
|
     ^(n='if' expression b1=block b2=ifStatement)
     -> elsif(
          node={$n},
          cond={$expression.st},
          block1={$b1.st},
          block2={$b2.st},
          isElsif={($n.Parent.Text == "ELSIF") ? "true" : null}
        )
|
     ^(ELSIF i=ifStatement) -> { $i.st }
;

在大多数情况下,这可以正常工作,例如,它可以毫无问题地转换以下代码:

if (x == "1") {
}
else if (x == "2") {
}
else if (x == "3") {
}

但是,当我有20个以上的“ else if”子句时,编译器需要几分钟来完成其工作。编译所需的时间不会线性增加,也就是说,编译器会立即为17或18个“ else if”子句返回。

更新:

我已经解决了这个问题。我已更换

     ^(n='if' expression b1=block b2=ifStatement)
     -> elsif(
          node={$n},
          cond={$expression.st},
          block1={$b1.st},
          block2={$b2.st},
          isElsif={($n.Parent.Text == "ELSIF") ? "true" : null}
        )
|
     ^(ELSIF i=ifStatement) -> { $i.st }

     ^(n='if' expression b1=block ^(ELSIF b2=ifStatement))
     -> elsif(
          node={$n},
          cond={$expression.st},
          block1={$b1.st},
          block2={$b2.st},
          isElsif={($n.Parent.Text == "ELSIF") ? "true" : null}
        )

那就是我已经将最后两个选择合并为一个。

现在,Transpiler的运行速度非常快,并且仍然可以返回正确的结果。

我真的很想知道为什么这种变化会带来如此大的变化。

艾拉·巴克斯特(Ira Baxter)

欢迎回溯。

如果强制解析器在(例如)三个选项之间进行选择(如您在语法中一样),并且必须回溯,并且这些选项嵌套(如if-then-else一样),则嵌套的N集构造可能需要3 ^ N个工作单元来解析。3 ^ 20是3 ^ 17的27倍。

教训:回溯有时很有用,但通常应该避免。

对于您的语法,为什么不像对待其他所有语句一样对待if构造?这样就不会出现特殊情况,您可以完全避免回溯。您甚至可以获得标准的“否则,则附加到最接近的if”规则,这是大多数编程语言中的标准规则。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Azure VM磁盘性能急剧下降

来自分类Dev

为什么以其他用户身份运行命令时性能急剧下降

来自分类Dev

为什么当记录> 600左右时查询性能急剧下降

来自分类Dev

为什么网络工作者的性能在30秒后急剧下降?

来自分类Dev

使用Android Gradle插件进行编译时如何添加Java编译器选项?

来自分类Dev

在对代码进行性能分析时,应该使用匹配的(gcc)编译器优化标志吗?

来自分类Dev

Swift编译器性能

来自分类Dev

随着集群规模的增加,在带有AMI 3.1.0和Hadoop 2.4.0的Elastic MapReduce上,每个节点的并发运行的映射器数量急剧下降

来自分类Dev

为什么通过缓存c ++访问静态ram的速度急剧下降?

来自分类Dev

为什么memcpy()的速度每4KB急剧下降?

来自分类Dev

使用cmake传递复合编译器选项

来自分类Dev

使用WCONTINUED选项的waitpid()编译器错误

来自分类Dev

使用cmake传递复合编译器选项

来自分类Dev

使用Edgetpu编译器进行Tensorflow编译时出错

来自分类Dev

Libtorch使用g ++,但使用Intel编译器时失败

来自分类Dev

添加不使用的内存时性能下降

来自分类Dev

tsc未知编译器选项allowNonTsExtensions

来自分类Dev

原生比。Protoc编译器选项

来自分类Dev

编译器选项以禁用C ++“功能”

来自分类Dev

资产目录编译器选项丢失

来自分类Dev

GCC编译器优化选项

来自分类Dev

用于调试的Delphi编译器选项

来自分类Dev

如何设置编译器选项?

来自分类Dev

使用抽象类型时的编译器错误

来自分类Dev

使用pyximport时如何设置Cython编译器标志?

来自分类Dev

使用Jam时如何查看g ++编译器输出?

来自分类Dev

使用某些开关时的gcc编译器错误

来自分类Dev

使用constexpr和lambda时的编译器错误

来自分类Dev

使用抽象类型时的编译器错误

Related 相关文章

  1. 1

    Azure VM磁盘性能急剧下降

  2. 2

    为什么以其他用户身份运行命令时性能急剧下降

  3. 3

    为什么当记录> 600左右时查询性能急剧下降

  4. 4

    为什么网络工作者的性能在30秒后急剧下降?

  5. 5

    使用Android Gradle插件进行编译时如何添加Java编译器选项?

  6. 6

    在对代码进行性能分析时,应该使用匹配的(gcc)编译器优化标志吗?

  7. 7

    Swift编译器性能

  8. 8

    随着集群规模的增加,在带有AMI 3.1.0和Hadoop 2.4.0的Elastic MapReduce上,每个节点的并发运行的映射器数量急剧下降

  9. 9

    为什么通过缓存c ++访问静态ram的速度急剧下降?

  10. 10

    为什么memcpy()的速度每4KB急剧下降?

  11. 11

    使用cmake传递复合编译器选项

  12. 12

    使用WCONTINUED选项的waitpid()编译器错误

  13. 13

    使用cmake传递复合编译器选项

  14. 14

    使用Edgetpu编译器进行Tensorflow编译时出错

  15. 15

    Libtorch使用g ++,但使用Intel编译器时失败

  16. 16

    添加不使用的内存时性能下降

  17. 17

    tsc未知编译器选项allowNonTsExtensions

  18. 18

    原生比。Protoc编译器选项

  19. 19

    编译器选项以禁用C ++“功能”

  20. 20

    资产目录编译器选项丢失

  21. 21

    GCC编译器优化选项

  22. 22

    用于调试的Delphi编译器选项

  23. 23

    如何设置编译器选项?

  24. 24

    使用抽象类型时的编译器错误

  25. 25

    使用pyximport时如何设置Cython编译器标志?

  26. 26

    使用Jam时如何查看g ++编译器输出?

  27. 27

    使用某些开关时的gcc编译器错误

  28. 28

    使用constexpr和lambda时的编译器错误

  29. 29

    使用抽象类型时的编译器错误

热门标签

归档