如何更改表达式以强制在生成的解析器中调用RewriteRuleSubtreeStream.NextTree()?

时间:2012-02-21 02:40:10

标签: antlr antlr3

我是一名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

1 个答案:

答案 0 :(得分:1)

你不能这样做AFAIK:在^((根)之后直接放置的内容将始终被视为单个节点,而不是树。

略有不同的方式:

cast
 : ('('  ssisType (',' INT)* ')') term -> ^(CAST ^(SSISTYPE ssisType INT*) term)
 ;

ssisType
 : 'DT_I1'
 | 'DT_I2'
 // ...
 ;

将解析输入:

(DT_I2, 42, 666)123456

进入以下AST:

enter image description here