2013-02-12 7 views
3

У меня есть грамматик и все отлично работают до этой части:ANTLR неоднозначности «-»

lexp 
: factor (('+' | '-') factor)* 
; 

factor :('-')? IDENT; 

Это, конечно, вносит неоднозначность. Например a-a может соответствовать либо Factor - Factor или Factor -> - IDENT

Я получаю следующее предупреждение об этом:

[18:49:39] warning(200): withoutWarningButIncomplete.g:57:31: 
Decision can match input such as "'-' {IDENT, '-'}" using multiple alternatives: 1, 2 

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

Вот полная грамматика:

program 
    : includes decls (procedure)* 
    ; 

/* Check if correct! */ 
includes 
    : ('#include' STRING)* 
    ; 

decls 
    : (typedident ';')* 
    ; 

typedident 
: ('int' | 'char') IDENT  
; 

procedure 
    : ('int' | 'char') IDENT '(' args ')' body 
    ; 

args 
: typedident (',' typedident)* /* Check if correct! */ 
| /* epsilon */ 
; 

body 
: '{' decls stmtlist '}' 
; 

stmtlist 
: (stmt)*; 

stmt 

: '{' stmtlist '}' 
| 'read' '(' IDENT ')' ';' 
| 'output' '(' IDENT ')' ';' 
| 'print' '(' STRING ')' ';' 
| 'return' (lexp)* ';' 
| 'readc' '(' IDENT ')' ';' 
| 'outputc' '(' IDENT ')' ';' 
| IDENT '(' (IDENT (',' IDENT)*)? ')' ';' 
| IDENT '=' lexp ';'; 



lexp 
: term (('+' | '-') term) * /*Add in | '-' to reveal the warning! !*/ 
; 

term 
    : factor (('*' | '/' | '%') factor)* 
; 


factor : '(' lexp ')' 
| ('-')? IDENT 
| NUMBER; 




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

IDENT : ('A' .. 'Z' | 'a' .. 'z') (('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_'))* ; 


NUMBER 
: (('-')? DIGIT+) 
; 

CHARACTER 
: '\'' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '\\n' | '\\t' | '\\\\' | '\\' | 'EOF' |'.' | ',' |':' ) '\'' /* IS THIS COMPLETE? */ 
; 
+0

Возникает ли ошибка только с этой простой грамматики? Я не знаком с ANTLR, и я должен упустить что-то очевидное здесь, но это не кажется мне двусмысленным. Минус, следующий за множителем, всегда следует интерпретировать как бинарный оператор здесь. Второй минус, если он присутствует, станет дополнительным унарным минусом. Анализ «фактор-фактор» как «фактор» «-IDENT» не будет действительным синтаксисом в соответствии с грамматикой, поскольку вы не можете перейти от первого фактора, не потребляя ни +, ни. –

+0

Что вы подразумеваете под * "add in' | '-'' "*? Добавить туда где? Можете ли вы опубликовать двусмысленное правило? –

+0

Я удалил этот комментарий. Как бы то ни было, эти правила неоднозначны. Вот правило Lexer, если это помогает: IDENT \t: ('A' .. 'Z' | 'a' .. 'z') (('A' .. 'Z' | 'a' .. ' z '|' 0 '..' 9 '|' _ ')) * \t; – Awoken

ответ

2

Как уже упоминалось в комментариях: эти правила не неоднозначным:

lexp 
: factor (('+' | '-') factor)* 
; 

factor : ('-')? IDENT; 

Это является причиной неоднозначности:

'return' (lexp)* ';' 

который может анализировать ввод a-b в два различных способа:

  1. a-b в качестве одного двоичного выражения
  2. a как единое выражение, и -b как одноместного выражения

Вам нужно будет изменить свою грамматику. Возможно, добавьте запятую в несколько возвращаемых значений? Что-то вроде этого:

'return' (lexp (',' lexp)*)? ';' 

который будет соответствовать:

return; 
return a; 
return a, -b; 
return a-b, c+d+e, f; 
...