不明确的ANTLR解析器规则 - 第2部分

时间:2015-04-01 08:43:11

标签: parsing antlr antlr4

好的,在这里发布一个简单的例子后: Ambiguous ANTLR parser rule

我认为过度简化这个例子并不适合我。 所以,我现在正在添加真实的例子。

以下是要解析的文字:

#ifndef _EVENTS_H
#define _EVENTS_H
#define EVENTS_LOGGER_VER 3.0f
/******************************************************************************************************
<Start of event definitions section - Do not edit this comment.
******************************************************************************************************/
#define EVT_FLOW_HW_ASSERTION_BASE              0x0     // Hw assertion base event
#define EVT_FLOW_HW_ASSERTION_PMG               0x1    // Hw assertion detected on PMG module. Module = 0x%x. Status is 0x%x.
#define EVT_I2C_SECTION_START                   0x20
#define EVT_I2C_DRIVER_ERROR                    0x26    //  I2C driver returns with error 0x%x on Device 0x%x Offset 0x%x
#define EVT_I2C_TARGET_DEVICE_ERROR             0x27    //  I2C interrupt on error: Status=0x%x%x
#define EVT_TIME_MEASUREMENTS                   0x2A    // Time measurement. Line : %d; Spare : %d; Time, us : %d
#define EVT_DFU_AFTER_UPDATE_STATE_REG          0x2D    // Going to DFU  (REG_RESET_STATUS = %x)
#define EVT_MNOT_SAFE_DEBUG_INFO_CTL_RO_P1      0xC3    // ctl ro data 0x99-0xa0: 0x%x 0x%x 0x%x

这是语法:

grammar EventsHFile;

/*
 * Parser Rules
 */

prog : ifndefEvents defineEvents defineVersion event+ EOF;

ifndefEvents : IFNDEF '_EVENTS_H';

defineEvents : DEFINE '_EVENTS_H';

defineVersion: DEFINE 'EVENTS_LOGGER_VER' version=versionRule 'f';

versionRule:   REAL   ;

event : DEFINE EVT_HEADER eventName=eventNameRule HEX eventId=eventIdRule (COMMENT_HEADER commentRule)?;

eventNameRule : ID;

eventIdRule : HEX_VALUE;

commentRule: (ID | hexArgumentRule | decimalArgumentRule | numericArgumentRule | HEX | HEX_VALUE | COMMENTCHAR)+;

numericArgumentRule : '%x';

hexArgumentRule : HEX numericArgumentRule+;

decimalArgumentRule : '%d';

IFNDEF : '#ifndef';
DEFINE : '#define';

EVT_HEADER : 'EVT_';

COMMENT_HEADER : '//';

fragment
DIGIT                   :           [0-9];

fragment
LETTER                  :           [a-zA-Z];

fragment
UNDERSCORE              :           '_';

fragment
HEXADIGIT
    :   [0-9a-fA-F]
    ;

ID : LETTER (LETTER|DIGIT|UNDERSCORE)* ;

REAL : DIGIT+ '.' DIGIT+;

HEX : '0' [xX] ;

HEX_VALUE : HEXADIGIT HEXADIGIT* ;

COMMENTCHAR : ('(' | ')' | '=' | '-' | ':');

BLOCKCOMMENT :   '/*' .*? '*/' -> channel(HIDDEN);
WS     :   (' ' | '\r' | '\n' | '\t') -> channel(HIDDEN);

现在,问题是,正如前一篇文章中所解释的那样,eventNameRule可能是不明确的,它捕获'EVT_'前缀,导致后面的树(我添加了一个事件树,所有事件都看起来像相同):  enter image description here

像往常一样,任何帮助都表示赞赏。

谢谢, 布丝

1 个答案:

答案 0 :(得分:0)

词法分析器独立于解析器运行。词法分析器将匹配与大多数字符匹配的规则。对于EVT_FLOW_HW_ASSERTION_BASE,这是ID

您可以为事件名称定义单独的词法分析器规则:

EVT_ID : 'EVT_' ID;

将它放在ID之前,以便匹配,因为在这种情况下,如果多个规则匹配相同的长度(EVT_ID和ID),词法分析器将选择第一个规则。

编辑:您需要相应更改event规则:

grammar EventsHFile;

/*
 * Parser Rules
 */

prog : ifndefEvents defineEvents defineVersion event+ EOF;

ifndefEvents : IFNDEF '_EVENTS_H';

defineEvents : DEFINE '_EVENTS_H';

defineVersion: DEFINE 'EVENTS_LOGGER_VER' version=versionRule 'f';

versionRule:   REAL   ;

event : DEFINE eventName=eventNameRule HEX eventId=eventIdRule (COMMENT_HEADER commentRule)?;

eventNameRule : EVT_ID;

eventIdRule : HEX_VALUE;

commentRule: (ID | hexArgumentRule | decimalArgumentRule | numericArgumentRule | HEX | HEX_VALUE | COMMENTCHAR)+;

numericArgumentRule : '%x';

hexArgumentRule : HEX numericArgumentRule+;

decimalArgumentRule : '%d';

IFNDEF : '#ifndef';
DEFINE : '#define';

EVT_ID : EVT_HEADER ID;
EVT_HEADER: 'EVT_';
COMMENT_HEADER : '//';

fragment
DIGIT                   :           [0-9];

fragment
LETTER                  :           [a-zA-Z];

fragment
UNDERSCORE              :           '_';

fragment
HEXADIGIT
    :   [0-9a-fA-F]
    ;

ID : LETTER (LETTER|DIGIT|UNDERSCORE)* ;

REAL : DIGIT+ '.' DIGIT+;

HEX : '0' [xX] ;

HEX_VALUE : HEXADIGIT HEXADIGIT* ;

COMMENTCHAR : ('(' | ')' | '=' | '-' | ':');

BLOCKCOMMENT :   '/*' .*? '*/' -> channel(HIDDEN);
WS     :   (' ' | '\r' | '\n' | '\t') -> channel(HIDDEN);

请注意,您的单行注释规则也是错误的,因为它与.个字符不匹配。我会把那个留给你,应该有很多例子。