首页 > 解决方案 > 在语法文件上运行 c++ 的 antlr4 解析器显示错误 33:缺少代码生成模板 NonLocalAttrRefHeader

问题描述

我对 ANTLR 比较陌生,我有一个当前项目需要从 ANTLR3(3.5 版)合并到 ANTLR4。我已经阅读了这本书并尝试了演示,这一切都很好,但是我自己的项目给了我以下问题:

将 ANTRL3 项目转换为 ANTLR4 项目(解决所有警告和错误)后,我能够构建 lexer.h 和 lexer.cpp 文件,但出现以下错误:错误(33):缺少代码生成模板 NonLocalAttrRefHeader 错误(33) :缺少代码生成模板 SetNonLocalAttrHeader(大约 50 次)。我无法在任何地方找到这些模板的任何引用。有没有人可以阐明这些错误消息?因为他们没有说任何关于行号或引用任何其他代码的内容,所以我完全不知道该去哪里看。

我已经建立了一个测试环境,测试演示 g4 文件。我已经从我的(VS2017)项目中提取了 g4 文件,并使用批处理文件单独尝试了它。

由于缺乏参考资料,我无法显示导致原因的实际代码。我尝试了部分解析,但我无法从中获得任何线索。

显示这些错误: 错误(33):缺少代码生成模板 NonLocalAttrRefHeader 错误(33):缺少代码生成模板 SetNonLocalAttrHeader

我构建了一个小例子来演示这个问题:

/*
 * AMF Syntax definition for ANTLR.
 *
 */
grammar amf;

options {
    language = Cpp;
}

amf_group[amf::AmfGroup& amfGroup] locals [int jsonScope = 2] 
    : statements=amf_statements (GROUPSEP WS? LINE_COMMENT? EOL? | EOF)
    {
        amfGroup.SetStatements(std::move($statements.stmts));
    }
    ;

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


amf_statement returns [amf::AmfStatementPtr value]
    : (
        {$amf_group::jsonScope == 1}? jsonparent_statement
        | {$amf_group::jsonScope == 2}? jsonvalue_statement
       )
    {
        value = std::move(context.expression(0).value);
    }
    ;


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

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

integer_const returns [amf::AmfArgPtr value]
    : p='%' (
        (signed_int)
        {
            long num = std::stol($signed_int.text);
            value = std::make_shared<amf::AmfArg>(ARG_TYPE::ARG_INTEGER, num);
        }
        | signed_float
        {
            value = std::make_shared<amf::AmfArg>(ARG_TYPE::ARG_INTEGER, std::stof($signed_float.text));
        }
        )
    ;


signed_int
    : MINUS? INT;

signed_float
    : MINUS? FLOAT;

    T_JSONPAR       : 'JSONPAR' | 'JSONPARENT';
    T_JSONVALUE     : 'JSONVAL' | 'JSONVALUE';


    /* Special tokens */
    GROUPSEP        : '%%';

    MINUS           : '-';

INT : DIGIT+;

FLOAT
    : DIGIT+ '.' DIGIT* EXPONENT?
    | '.' DIGIT+ EXPONENT?
    | DIGIT+ EXPONENT
    ;

ID  : ('A'..'Z'|'_') ('A'..'Z'|'0'..'9'|'_')*
    ;

COMMENT
    : ('/*' .*? '*/') -> channel(HIDDEN)
    ;

LINE_COMMENT
    : ('//' ~('\n'|'\r')* '\r'?) -> channel(HIDDEN)
    ;

EOL : ('\r'? '\n');


QOUTED_STRING
    : '"$' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

SIMPLE_STRING
    : '$' ~(' '|'\t'|'\r'|'\n')*
    ;

WS  : (' '|'\t')+;


fragment
DIGIT
    : '0'..'9'
    ;

fragment
EXPONENT
    : 'E' ('+'|'-')? ('0'..'9')+
    ;

fragment
ESC_SEQ
    : '\\' (
        'R'
        |'N'
        |'T'
        |'"'
        |'\''
        |'\\'
    )
    ;

一旦我为 amf_statement 添加谓词(在本例中为 4 次“NonLocalAttrTefHeader 缺少代码生成模板)”,就会发生错误。我尝试将输出语言更改为 Python 或 CSharp,但这无济于事。

标签: c++antlr4

解决方案


在仔细查看了所有步骤之后,我偶然发现了执行 java 命令的批处理命令的一个小但关键的区别:我使用了我以前使用 java -jar 选项的 antrl3 批处理文件的副本来执行 antlr-4.7.2 -complete.jar 而不是 cp 并执行 org.antlr.v4.Tool。一切似乎进展顺利,命令行选项显示良好,语法错误全部到位,直到创建实际的词法分析器和解析器代码:然后显示错误(33),但前提是使用动态范围,否则一切似乎都很顺利。

更新:我以为我可以继续我的项目,但这只是部分解决方案:当我切换回 Cpp 输出时,错误返回。标准输出和 CSharp 输出没问题,一旦我尝试生成 Cpp 输出,我就会收到相同的错误,再次使用动态范围:第 25 和 26 行。如果我删除谓词,错误就会消失。

所以我仍然遇到这些错误,但仅限于 C++。


推荐阅读