ANTLR4简单语法不匹配

本文关键字:不匹配 语法 简单 ANTLR4 | 更新日期: 2023-09-27 18:18:32

我使用最新版本的Antlr(4.3)来解析这个简单的源文件。我正在使用Visual Studio插件,但这应该与我的问题没有任何关系。

源文件:

OBJECT Codeunit 80 Sales-Post
{
  OBJECT-PROPERTIES
  {
    Date=11/12/10;
    Time=12:00:00;
    Version List=NAVW16.00.10,NAVBE6.00.01;
  }
}

这应该是相当简单的解析,但我一直得到两个错误,而解析:

line 1:16 mismatched input '80' expecting DOCUMENT_ID
line 5:4 mismatched input 'Date' expecting {DOCUMENT_PROPERTY_ID, '}'}

完整的语法:

grammar Cal;
/*
 * Parser Rules
 */
document
    : document_header OPEN_BRACE document_content CLOSE_BRACE
    ;
document_header
    : OBJECT_DEFINITION DOCUMENT_TYPE DOCUMENT_ID DOCUMENT_NAME
    ;
document_content
    : document_properties
    ;
document_properties
    : OBJECT_PROPERTIES OPEN_BRACE document_property* CLOSE_BRACE
    ;
document_property
    : DOCUMENT_PROPERTY_ID EQ DOCUMENT_PROPERTY_VALUE LINE_TERM
    ;

/*
 * Lexer Rules
 */
OBJECT_PROPERTIES
    : 'OBJECT-PROPERTIES'
    ;
OBJECT_DEFINITION
    : 'OBJECT'
    ;
DOCUMENT_TYPE
    : 'Codeunit'
    | 'Table'
    ;
DOCUMENT_PROPERTY_VALUE
    : ([0-9a-zA-Z]|'_'|'-'|'.'|'/'|','|':')+
    ;
DOCUMENT_PROPERTY_ID
    : 'Date'
    | 'Time'
    | 'Version List'
    ;
DOCUMENT_ID
    : [0-9]+
    ;
DOCUMENT_NAME
    : ID
    ;
OPEN_BRACE
    : '{'
    ;
CLOSE_BRACE
    : '}'
    ;
LINE_TERM
    : ';'
    ;
EQ
    : '='
    ;
ID
    : ([a-zA-Z]|'_'|'-')+
    ;
INT
    : [0-9]+
    ;
WS
    : [ 't]+ -> channel(HIDDEN)
    ;
NEWLINE
    :''r'? ''n' -> channel(HIDDEN)
    ;

这是标记流的输出(标记被'<>'包围:

<OBJECT> < > <Codeunit> < > <80> < > <Sales-Post> <
> <{> <
> <  > <OBJECT-PROPERTIES> <
> <  > <{> <
> <    > <Date> <=> <11/12/10> <;> <
> <    > <Time> <=> <12:00:00> <;> <
> <    > <Version List> <=> <NAVW16.00.10,NAVBE6.00.01> <;> <
> <  > <}> <
> <}> <<EOF>

ANTLR4简单语法不匹配

在ANTLR中,当两个词法分析器规则可以匹配相同的令牌(长度相同)时,最先出现的规则获胜。

80可以被DOCUMENT_ID匹配,但也可以被DOCUMENT_PROPERTY_VALUEINT匹配,所以这里只是重新排列这些规则。

你在DOCUMENT_PROPERTY_ID有同样的问题,它低于DOCUMENT_PROPERTY_VALUE(两者都可以匹配Date)。

我建议你把DOCUMENT_PROPERTY_VALUE放在WS上面:最具体的规则(即关键字)放在前面,更广泛的规则放在最后。

您还必须去掉DOCUMENT_IDINT,因为它们具有相同的定义。其中一个永远不会匹配。您似乎没有在解析器中使用INT,因此只需删除规则。