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

发布于 2025-01-07 20:52:40 字数 2955 浏览 0 评论 0原文

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

原因是树的顶部节点包含未使用 NextNode 添加的子节点。

有什么方法可以改变表达以产生我想要的行为吗?我尝试在表达式中的多个位置插入 ^,但要么生成错误的结果,要么无法构建语法。

非常感谢,

-克雷格

I'm an ANTLR novice that's trying to update an early ANTLR 3.1 grammar to 3.4. The one stumbling block I'm hitting is with my generated parser. There's a line of code that calls NextNode(), and I want it to call NextTree() instead, so my parser performs the desired behavior.

My ANTLR expression in question is:

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

ssisType is defined as:

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)

In my parser (in C#), the generated portion of code that processes the right hand side of the expression is:

    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);
            }

        }

I'm looking for a way to change my expression so that

root_2 = (CommonTree)adaptor.BecomeRoot(stream_ssisType.NextNode(), root_2);

becomes

root_2 = (CommonTree)adaptor.BecomeRoot(stream_ssisType.NextTree(), root_2);

The reason is that the Tree's top node contains Children that aren't being added using NextNode.

Is there I way I can change the expression to produce my desired behavior? I've tried inserting an ^ at several spots within the expression but either the wrong result is generated or the grammar won't build.

Thanks very much,

-Craig

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初相遇 2025-01-14 20:52:40

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

不同的方式:

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

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

它将解析输入:

(DT_I2, 42, 666)123456

稍微 以下 AST:

在此处输入图像描述

You can't do that AFAIK: what you place directly after the ^( (the root) will always be considered a single node, no tree.

An slightly different way:

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

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

which will parse the input:

(DT_I2, 42, 666)123456

into the following AST:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文