【问题标题】:ANTLR StringTemplate infinite loop while rendering the templateANTLR StringTemplate 在渲染模板时无限循环
【发布时间】:2012-07-23 08:25:01
【问题描述】:

我正在使用 antlr-3.4-complete.jar,我认为它使用的是 StringTemplate 3.2.1 版

我在树语法中有以下产生式

functionCall 
  : ^(FUNCCALL NCName pr+=params*) ->template(n={$NCName.text},p={$pr})"<n> <p>"

上面的 StringTemplate 运行正确,并且产生了正确的输出。

我有另一个使用相同语法的产生式,与上面的产生式非常相似

step  
  :  axisSpecifier nodeTest pred+=predicate* 
       ->template(a={$axisSpecifier.st},n={$nodeTest.st},pc={$pred})"<a> <n> <pc>"
  ;

但是当我打印模板时,它会无限递归,堆栈如下

Exception in thread "main" java.lang.StackOverflowError
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)
    at org.antlr.stringtemplate.StringTemplate.getAttributeRenderer(StringTemplate.java:1080)

上面生成的代码如下

retval.st = new StringTemplate(templateLib, "<a> <n> <pc>",new STAttrMap().put("a", (axisSpecifier14!=null?axisSpecifier14.st:null)).put("n", (nodeTest15!=null?nodeTest15.st:null)).put("pc", list_pred));

list_pred 是包含 predicate* 的 StringTemplates 的列表。 当我调试代码时,我发现就在上述行之前,各个 StringTemplates 都很好。很好,我的意思是我可以将调试器中的值读取为字符串值。但是一旦执行了上述行,即new StringTemplate 完成,toString() 方法就会开始失败。不仅适用于新的 StringTemplate,也适用于 StringTemplate list_pred

我无法继续我的工作,因为我认为这不是我的语法问题,因为另一个具有相同结构的作品运行良好。

会因为我选择的参数名称而发生此错误吗?

template(a={$axisSpecifier.st},n={$nodeTest.st},pc={$pred})"&lt;a&gt; &lt;n&gt; &lt;pc&gt;"

如果我将名称从 a,n,pc 更改为其他名称会有帮助吗?如我所见,我在语法中的其他地方也使用了相同的名称。

我怀疑方法

StringTemplate.breakTemplateIntoChunks() 可能是这里的原因?因为这个方法会解析模板。

熟悉 StringTemplate 内部的人可以帮我解决这个问题吗?

谢谢, 问候, 维马尔

更新: 这是我的 AST 构造的输出,这也构成了 treeGrammar 的输入。 (VARREF abc) / (STEPS (STEP child x (PRED (&lt; (STEPS (STEP child price)) 10)))) END

PRED 是谓词,也是Expr

我的 ST 的树语法如下。

expr  
   :  ^('<' e1=expr e2=expr) ->template(e11={$e1.st},e21={$e2.st})"\< <e11> <e21>"  
   | mainexpr -> template(mnexpr={$mainexpr.st})"<mnexpr>"  
   ;  

mainexpr  
scope  
{  
  boolean isRLP ;  
} :   
    filterExpr ('/' {$mainexpr::isRLP = true;} relativeLocationPath)?   
     -> {$mainexpr::isRLP}? template(filtr={$filterExpr.st},rlp=  {$relativeLocationPath.st})"<filtr> <rlp>"  
     -> template(filtr={$filterExpr.st})"<filtr>"  
  | relativeLocationPath -> template(rlp={$relativeLocationPath.st})"<rlp>"  
  ;  

relativeLocationPath : ^(STEPS st+=steps+) -> template(stps={$st})"<stps>";  

steps  
  :   ^(STEP step) ->template(stp={$step.st})"<stp>"    
  ;  
step   
  :  axisSpecifier nodeTest (pred+=predicate)*  
           ->template(axs={$axisSpecifier.st},ndtst={$nodeTest.st},stppred={$pred})"<axs> <ndtst> <stppred>"  
  ;  

predicate  
  : ^(PRED expr) ->template(predexp={$expr.st})"<predexp>"  
  ;  

LintMode 的输出:

Exception in thread "main" java.lang.IllegalStateException: infinite recursion to <anonymous([])@76> referenced in <anonymous([])@69>; stack trace:  
<anonymous([])@76>, attributes=[predexp=<anonymous()@75>], references=[predexp, stppred]>  
<anonymous([])@69>, attributes=[ndtst=<anonymous()@68>, stppred, axs=<anonymous()@67>], references=[axs, ndtst, stppred]>  
<anonymous([])@70>, attributes=[stp=<anonymous()@69>], references=[stp, stppred]>  
<anonymous([])@71>, attributes=[stps=List[..<anonymous()@70>..]], references=[stps, stppred]>  
<anonymous([])@72>, attributes=[rlp=<anonymous()@71>], references=[rlp, stppred]>  
<anonymous([])@73>, attributes=[mnexpr=<anonymous()@72>], references=[mnexpr, stppred]>  
<anonymous([])@75>, attributes=[e21=<anonymous()@74>, e11=<anonymous()@73>],   references=[e11, stppred]>  
<anonymous([])@76> (start of recursive cycle)  

【问题讨论】:

  • ANTLR 3.4 不使用 StringTemplate v4 吗?您可能想在StringTemplate mailing-list 上提出您的问题:Terence 时不时地漫游,但这里没有很多 StringTemplaters(还没有!):) 祝你好运!跨度>
  • @BartKiers,感谢您的回复。我打印变量StringTemplate.VERSION 的值,得到3.2.1,所以我说它使用3.2.1。此外,我为 3.2.1 下载的源代码在我调试时能够与代码匹配。
  • @BartKiers 问题出在 StringTemplate.toString() 中,调试此方法的问题在于,当我试图定位错误源时,每当我检查任何 StringTemplate 的值时,调试器在内部调用toString(),然后我才能完成对 toString() 的步进:)
  • 啊,我很快查看了 3.4 JAR 并看到了 org/stringtemplate/v4 路径,但 StringTemplate.VERSION 似乎很有结论性:)。我帮不上忙:对 ST 不太熟悉……

标签: antlr stringtemplate


【解决方案1】:

ANTLR v3.4 使用 ST v4 进行协同生成,但为了向后兼容,生成的代码使用 ST v3.2.1。

您已在其自身中嵌入了一个模板。开启 lint 模式,在模板嵌套图中找到无限循环。

【讨论】:

  • 您好 Terr,非常感谢先生抽出时间来回答。但是我的 StringTemplates 遵循与我的 CombinedGrammar 和 TreeGrammar 相同的模式。顶层是Expr,其中包含一个Predicate,它本身可以是一个Expr。 CombinedGrammar、TreeGrammar 可以支持这一点。我可以使用 TreeGrammar 在树上行走。但是当我引入 StringTemplates 时,我得到了这个错误。是的,Predicate 的 ST 调用 Expr 的 ST。我使用了 lint 模式并在 lint 输出中得到了相同的结果。这是否意味着ST不能支持这一点。或者可能是我不应该将 ST 视为语法......
  • 嗨,我在上面的主要问题中添加了带有 ST 的 TreeGrammar。你能看看它并提出任何改变吗? - 谢谢
  • 是否有可能因为我使用匿名模板('lambda' 生成的模板)我收到此错误?我将尝试使用“命名”模板并让您知道结果。
  • 嗨,Terr,现在工作正常。我将 ST 定义从 TreeGrammar 移到了单独的 stg 文件中,并从 TreeGrammar 调用了这些 ST,到目前为止一切正常:) 非常感谢您关注我的推文并花时间回答这个问题。
猜你喜欢
  • 2010-12-24
  • 2019-01-07
  • 1970-01-01
  • 2018-07-02
  • 2020-08-11
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多