我是一名ANTLR新手,试图将早期的ANTLR 3.1语法更新为3.4。我正在遇到的一个绊脚石是我生成的解析器。有一行代码调用NextNode(),我希望它调用NextTree(),所以我的解析器执行所需的行为。
我的ANTLR表达方式是:
cast : ('(' ssisType (',' INT)* ')') term -> ^(CAST ^( ssisType INT*) term)
;
ssisType定义为:
ssisType
:
( typeCode ='DT_I1'
| typeCode ='DT_I2'
| typeCode ='DT_I4'
| typeCode ='DT_I8'
| typeCode ='DT_R4'
| typeCode ='DT_R8'
| typeCode ='DT_CY'
| typeCode ='DT_DATE'
| typeCode ='DT_BOOL'
| typeCode ='DT_NUMERIC'
| typeCode ='DT_DECIMAL'
| typeCode ='DT_UI1'
| typeCode ='DT_UI2'
| typeCode ='DT_UI4'
| typeCode ='DT_UI8'
| typeCode ='DT_GUID'
| typeCode ='DT_BYTES'
| typeCode ='DT_STR'
| typeCode ='DT_WSTR'
| typeCode ='DT_DBDATE'
| typeCode ='DT_DBTIME'
| typeCode ='DT_DBTIME2'
| typeCode ='DT_DBTIMESTAMP'
| typeCode ='DT_DBTIMESTAMP2'
| typeCode ='DT_DBTIMESTAMPOFFSET'
| typeCode ='DT_FILETIME'
| typeCode ='DT_IMAGE'
| typeCode ='DT_TEXT'
| typeCode ='DT_NTEXT') -> ^(SSISTYPE $typeCode)
在我的解析器中(在C#中),处理表达式右侧的代码的生成部分是:
retval.Tree = root_0;
RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.Tree:null);
root_0 = (CommonTree)adaptor.Nil();
// 99:44: -> ^( CAST ^( ssisType ( INT )* ) term )
{
DebugLocation(99, 47);
// SsisGrammar.g:99:47: ^( CAST ^( ssisType ( INT )* ) term )
{
CommonTree root_1 = (CommonTree)adaptor.Nil();
DebugLocation(99, 49);
root_1 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(CAST, "CAST"), root_1);
DebugLocation(99, 54);
// SsisGrammar.g:99:54: ^( ssisType ( INT )* )
{
CommonTree root_2 = (CommonTree)adaptor.Nil();
DebugLocation(99, 57);
root_2 = (CommonTree)adaptor.BecomeRoot(stream_ssisType.NextNode(), root_2);
DebugLocation(99, 66);
// SsisGrammar.g:99:66: ( INT )*
while ( stream_INT.HasNext )
{
DebugLocation(99, 66);
adaptor.AddChild(root_2, stream_INT.NextNode());
}
stream_INT.Reset();
adaptor.AddChild(root_1, root_2);
}
DebugLocation(99, 72);
adaptor.AddChild(root_1, stream_term.NextTree());
adaptor.AddChild(root_0, root_1);
}
}
我正在寻找一种方法来改变我的表达方式,以便
root_2 = (CommonTree)adaptor.BecomeRoot(stream_ssisType.NextNode(), root_2);
变为
root_2 = (CommonTree)adaptor.BecomeRoot(stream_ssisType.NextTree(), root_2);
原因是Tree的顶级节点包含未使用NextNode添加的子节点。
我是否有办法改变表达式以产生我想要的行为?我已经尝试在表达式中的几个位置插入^但是生成了错误的结果或者语法不会构建。
非常感谢,
-Craig
答案 0 :(得分:1)
你不能这样做AFAIK:在^(
(根)之后直接放置的内容将始终被视为单个节点,而不是树。
略有不同的方式:
cast
: ('(' ssisType (',' INT)* ')') term -> ^(CAST ^(SSISTYPE ssisType INT*) term)
;
ssisType
: 'DT_I1'
| 'DT_I2'
// ...
;
将解析输入:
(DT_I2, 42, 666)123456
进入以下AST: