2014-12-23 4 views
1

У меня есть огромная грамматика ANTLR, и я столкнулся с проблемой с ее маленьким кусочком. Грамматика имеет два правила выраж и наборы, как определено ниже:Неопределенность преемственности в ANTLR 4

expr: 
    id 
    |(PLUS|MINUS|MULTIPLY|AND|NEGATION)expr 
    | expr (MULTIPLY |DIVIDE| MODULO) 
    | expr (PLUS | MINUS) expr 
; 

set: 
    EMPTY 
    | MULTIPLY set 
    | set PLUS set 
    | UNION '(' set (COMMA set)* ')' 
    | INTER '(' set (COMMA set)* ')' 
    | expr 
    ; 

Проблема здесь состоит в том, что для набора формы * s1 + * s2 должна быть уменьшена в следующем:

set -> set PLUS set 

, а затем каждый из множества в RHS должны сводиться к:

set -> MULTIPLY set 
set -> expr 
term -> id 

Но вместо этого они уменьшают как:

set -> MULTIPLY set 
set -> expr 
expr -> expr PLUS expr 

Из-за чего набор forn *s1 +*s2 разобран как *(s1 + *s2) вместо (*s1) + (*s2).

Одно из правил набора, сводит его к выражению. Существует много других аналогичных правил в грамматике, которые сводятся к expr. Проблема возникает здесь, потому что некоторые из правил в set и expr аналогичны. Но поскольку некоторые правила разные, я не могу объединить их вместе.

В наборе, даже если приоритет правила MULTIPLY set выше set PLUS set, набор уменьшается на MUTIPLY set правило.

Есть ли способ исправить эту проблему?

EDIT:

Добавление рабочий пример:

Грамматика:

grammar T; 

expr 
: ID 
    | (PLUS | MINUS | MULTIPLY | AND | NEGATION) expr 
    | expr (MULTIPLY | DIVIDE | MODULO) 
    | expr (PLUS | MINUS) expr 
; 

set: 
    EMPTY 
    | MULTIPLY set 
    | set PLUS set 
    | UNION '(' set (COMMA set)* ')' 
    | INTER '(' set (COMMA set)* ')' 
    | expr 
    ; 
ID : [a-zA-Z] [a-zA-Z0-9]*; 
PLUS : '+'; 
MINUS : '-'; 
MULTIPLY : '*'; 
AND : '&&'; 
NEGATION : '!'; 
DIVIDE : '/'; 
MODULO : '%'; 
COMMA : ','; 
EMPTY: '\\empty'; 
UNION: '\\union'; 
INTER: '\\inter'; 
SPACES : [ \t\r\n] -> skip; 

код для его выполнения:

TLexer lexer = new TLexer(new ANTLRInputStream("*s1 + *s2")); 
TParser parser = new TParser(new CommonTokenStream(lexer)); 
RuleContext tree = parser.set(); 
tree.inspect(parser); 

Выход он генерировал:

set 
/\ 
* set 
    | 
    expr 
    /| \ 
/| \ 
expr + expr 
    |  /\ 
    s1  * expr 
      | 
      s2 
+0

Можете ли вы предоставить [SSCCE] (http://sscce.org/), так как я не мог воспроизвести его? (см. мой ответ) –

+0

@BartKiers, я добавил рабочий пример. Извините, что раньше не приводил пример. – user2888308

ответ

0

Я не могу воспроизвести это.

Учитывая грамматику:

grammar T; 

expr 
: ID 
| (PLUS | MINUS | MULTIPLY | AND | NEGATION) expr 
| expr (MULTIPLY | DIVIDE | MODULO) 
| expr (PLUS | MINUS) expr 
; 

ID : [a-zA-Z] [a-zA-Z0-9]*; 
PLUS : '+'; 
MINUS : '-'; 
MULTIPLY : '*'; 
AND : '&&'; 
NEGATION : '!'; 
DIVIDE : '/'; 
MODULO : '%'; 
SPACES : [ \t\r\n] -> skip; 

ваш вход *s1 + *s2 будет анализироваться как:

 expr 
    /| \ 
/| \ 
expr + expr 
/\ /\ 
* expr * expr 
    |  | 
    s1  s2 

Или в простом коде:

TLexer lexer = new TLexer(new ANTLRInputStream("*s1 + *s2")); 
TParser parser = new TParser(new CommonTokenStream(lexer)); 
System.out.println(parser.expr().toStringTree(parser)); 

напечатает:

(expr (expr * (expr s1)) + (expr * (expr s2))) 
+0

Проблема, с которой я сталкиваюсь, возникает, когда вход * s1 + * s2 анализируется как «заданный» в качестве отправной точки. И поскольку expr используется во многих других правилах в грамматике, я не могу объединить набор в выражение. – user2888308

Смежные вопросы