我可以在ANTLR4中使用类似于c ++的虚拟令牌(具有相同返回值的令牌)吗?

时间:2019-05-30 20:28:26

标签: c++ antlr4

在C ++中,我可以使用虚拟函数来处理来自具有相同父/祖先的相似类的数据,ANTLR4是否支持此功能,我将如何设置语法?

我试图使用具有相同返回值的参数来建立语法,并在包含不同“子类化”标记的标记中使用该值。

以下是我尝试使用的一些代码:

    amf_group 
        : statements=amf_statements (GROUPSEP WS? LINE_COMMENT? EOL? | EOF)
        ;

    amf_statements returns [amf::AmfStatements stmts]
        : ( WS? ( stmt=amf_statement { stmts.emplace_back(std::move($stmt.stmtptr)); } WS? EOL) )*
        ;

    amf_statement returns [amf::AmfStatementPtr stmtptr] 
        : (
            stmt = jsonparent_statement 

            | stmt = jsonvalue_statement

           )
        { 
            $stmtptr = std::move($stmt.stmtptr);
        }
        ;

    jsonparent_statement returns [amf::AmfStatementPtr stmtptr] locals [int lineno=0]
        :
        (T_JSONPAR      { $lineno = $T_JSONPAR.line;} )  WS (arg=integer_const)
        {
            $stmtptr = std::make_shared<amf::JSONParentStatement>($lineno, nullptr);
        }
        ;

    jsonvalue_statement returns [amf::AmfStatementPtr stmtptr] locals [int lineno=0]
        : ( T_JSONVALUE { $lineno = $T_JSONVALUE.line; } ) WS (arg=integer_const) (WS fmt=integer_const)?
        {
            $stmtptr = std::make_shared<amf::JSONValueStatement>($lineno, std::move($arg.argptr), std::move($fmt.argptr));
        }
        ;

我收到以下错误:

错误(75):amf1.g4:23:10:标签stmt = jsonvalue_statement类型与先前的定义不匹配:stmt = jsonparent_statement

这个错误或者说是很合乎逻辑的,因为令牌确实是不同的类型,但是返回值的类型是相同的。对于两个(虚拟)令牌,我可以单独编写所有代码,但就我而言,我有大约40多个不同的令牌,它们分别表示参数或语句,并且编写所有组合将很麻烦。上面的代码确实在Antlr3中起作用。

是否有另一种方法可以使用ANTLR4解决这些错误?有人有什么建议吗?

1 个答案:

答案 0 :(得分:0)

从功能上来说,规则返回值中指定的内容实际上不是返回值。取而代之的是,表示规则的上下文将获得一个新的成员字段,该字段采用“返回”值。鉴于试图像C ++函数那样处理解析器规则没有任何意义,因此它们根本不可比。

除了处理语法中的所有字段外,我建议采用另一种方法:使用ANTLR4,您将获得一个解析树(如果启用),该树使用解析规则上下文表示匹配的规则(这是以前生成的规则的超级视图) AST)。该上下文包含所有已解析的值。解析运行后(通常称为语义阶段),您只需要在第二步中使用侦听器来遍历该树,拾取这些值并从中创建您自己的数据结构即可。这种分离还允许您使用解析器进行快速语法检查,因为您无需在解析运行中进行所有繁重的工作。