2013-12-12 1 views
0

Я начал работать с antlr несколько дней назад. Я хотел бы использовать его для анализа макросов #include в c. Только включает в мой интерес, все остальные части не имеют значения. здесь я написал простой файл грамматики:Antlr mismatched '>' для включения макроса

... parser part omitted... 

INCLUDE : '#include'; 
INCLUDE_FILE_QUOTE: '"'FILE_NAME'"'; 
INCLUDE_FILE_ANGLE: '<'FILE_NAME'>'; 

fragment 
FILE_NAME: ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'.'|' ')+; 

MACROS: '#'('if' | 'ifdef' | 'define' | 'endif' | 'undef' | 'elif' | 'else'); 
//MACROS: '#'('a'..'z'|'A'..'Z')+; 

OPERATORS: ('+'|'-'|'*'|'/'|'='|'=='|'!='|'>'|'>='|'<'|'<='|'>>'|'<<'|'<<<'|'|'|'&'|','|';'|'.'|'->'|'#'); 

... other supporting tokens like ID, WS and COMMENT ... 

Эта грамматика производит двусмысленности, когда такое заявление встречаются:

(;i<listLength;i++) 

output: mismatched character ';' expecting '>' 

Кажется, он пытается соответствовать INCLUDE_FILE_ANGLE вместо обработки «;» как ОПЕРАТОРЫ.

Я слышал, что есть оператор, называемый синтаксическим предикатом, но я не уверен, как его правильно использовать в этом случае.

Как я могу решить эту проблему в продвинутом режиме Antlr?

ответ

1

Похоже, здесь нет активного участия в antlr.

В любом случае я понял это.

INCLUDE_MACRO: ('#include')=>'#include'; 
VERSION_MACRO: ('#version')=>'#version'; 
OTHER_MACRO: 
    (
    |('#if')=>'#if' 
    |('#ifndef')=>'#ifndef' 
    |('#ifdef')=>'#ifdef' 
    |('#else')=>'#else' 
    |('#elif')=>'#elif' 
    |('#endif')=>'#endif' 
    ); 

Это разрешает первую половину проблемы. Во-вторых, нельзя использовать INCLUDE_FILE_ANGLE для соответствия нужной строке в директиве #include. Элементы '<' FILE_NAME '>' создают неоднозначность и должны быть разбиты на основные маркеры из lexer или использовать более сложные проверки контекстно-зависимого кода. Im не знаком с более поздней техникой, поэтому я написал это в правиле парсера:

include_statement : 
    INCLUDE_MACRO include_file 
    -> ^(INCLUDE_MACRO include_file); 

include_file 
    : STRING 
    | LEFT_ANGLE(INT|ID|OPERATORS)+RIGHT_ANGLE 
    ; 

Хотя это работает, но это правда, выглядит некрасиво. Надеюсь, опытные пользователи могут комментировать с гораздо лучшим решением.

+0

Вы можете принять свой собственный ответ ..... –