从ANTLR生成的java代码是一条规则,大多数时候都是一种方法。但是对于以下规则:
switchBlockLabels[ITdcsEntity _entity,TdcsMethod _method,List<IStmt> _preStmts]
: ^(SWITCH_BLOCK_LABEL_LIST switchCaseLabel[_entity, _method, _preStmts]* switchDefaultLabel? switchCaseLabel*)
;
它生成一个名为synpred125_TreeParserStage3_fragment()
的子方法,其中调用了switchCaseLabel(_entity, _method, _preStmts)
:
synpred125_TreeParserStage3_fragment(){
......
switchCaseLabel(_entity, _method, _preStmts);//variable not found error
......
}
switchBlockLabels(ITdcsEntity _entity,TdcsMethod _method,List<IStmt> _preStmts){
......
synpred125_TreeParserStage3_fragment();
......
}
问题是switchCaseLabel
有参数且参数来自switchBlockLabels()
方法的参数,因此发生“未找到变量错误”。
我该如何解决这个问题?
答案 0 :(得分:0)
我的猜测是你已经在语法中启用了全局回溯:
options {
backtrack=true;
}
在这种情况下,您无法将参数传递给不明确的规则。要在启用全局回溯时在不明确的规则之间进行通信,必须使用规则范围。 “谓词方法”做可以访问规则范围变量。
假设我们有这种含糊不清的语法:
grammar Scope;
options {
backtrack=true;
}
parse
: atom+ EOF
;
atom
: numberOrName+
;
numberOrName
: Number
| Name
;
Number : '0'..'9'+;
Name : ('a'..'z' | 'A'..'Z')+;
Space : ' ' {skip();};
(对于记录,atom+
和numberOrName+
会使其模糊不清)
如果你现在想要在parse
和numberOrName
规则之间传递信息,比如整数n
,那么这样的事情就会失败(这是你试过的方式):< / p>
grammar Scope;
options {
backtrack=true;
}
parse
@init{int n = 0;}
: (atom[++n])+ EOF
;
atom[int n]
: (numberOrName[n])+
;
numberOrName[int n]
: Number {System.out.println(n + " = " + $Number.text);}
| Name {System.out.println(n + " = " + $Name.text);}
;
Number : '0'..'9'+;
Name : ('a'..'z' | 'A'..'Z')+;
Space : ' ' {skip();};
为了使用规则范围执行此操作,您可以这样做:
grammar Scope;
options {
backtrack=true;
}
parse
scope{int n; /* define the scoped variable */ }
@init{$parse::n = 0; /* important: initialize the variable! */ }
: atom+ EOF
;
atom
: numberOrName+
;
numberOrName /* increment and print the scoped variable from the parse rule */
: Number {System.out.println(++$parse::n + " = " + $Number.text);}
| Name {System.out.println(++$parse::n + " = " + $Name.text);}
;
Number : '0'..'9'+;
Name : ('a'..'z' | 'A'..'Z')+;
Space : ' ' {skip();};
如果您现在运行以下类:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String src = "foo 42 Bar 666";
ScopeLexer lexer = new ScopeLexer(new ANTLRStringStream(src));
ScopeParser parser = new ScopeParser(new CommonTokenStream(lexer));
parser.parse();
}
}
您将看到以下内容正在打印到控制台:
1 = foo
2 = 42
3 = Bar
4 = 666
我不知道你正在解析什么语言,但启用全局回溯通常是过度的,并且会对解析器的性能产生很大影响。在少数情况下,计算机语言通常是模糊的。您应该考虑添加语法谓词,或者启用那些不明确的规则的回溯,而不是启用全局回溯。有关详细信息,请参阅The Definitive ANTLR Reference。