Как решить эту разбор неоднозначности в Antlr3 - PullRequest
2 голосов
/ 11 ноября 2011

Надеюсь, это именно тот объем информации, который поможет мне решить эту проблему.

С учетом следующего синтаксиса ANTLR3

grammar mygrammar;

program : statement* | function*;

function : ID '(' args ')' '->' statement+ (','statement+) '.' ;    

args    : arg (',' arg)*;       

arg     : ID ('->' expression)?;

statement : assignment
          | number
          | string
          ;

assignment : ID '->' expression;    

string  : UNICODE_STRING;

number : HEX_NUMBER | INTEGER ( '.' INTEGER )?;


// ================================================================

HEX_NUMBER : '0x' HEX_DIGIT+;

INTEGER : DIGIT+;

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

Вот строка, которая вызывает проблемы в парсере.

my_function(x, y, z -> 42) -> 10001.

ANTLRWorks выделяет last . после 10001 красным цветом как проблему со следующей ошибкой.

Как я могу сделать так, чтобы этот бросок прекратился org.antlr.runtime.EarlyExitException?

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

Ответы [ 2 ]

3 голосов
/ 11 ноября 2011

Существует еще одна неопределенность, которая также нуждается в исправлении.Измените:

program : statement* | function*;

на:

program  : (statement | function)*;

(хотя 2 не эквивалентны, я полагаю, вы хотите последнее)

И в вашем function правиле вы теперь определили, что по крайней мере 2 statement s:

function : ID '(' args ')' '->' statement (','statement)+ '.' ; 

, хотя я предполагаю, что вы действительно хотите по крайней мере один:

function : ID '(' args ')' '->' statement (','statement)* '.' ; 

Теперь ваша реальная проблема: поскольку вы создаете числа с плавающей точкой в ​​правиле синтаксического анализатора, с конца вашего ввода, 10001., анализатор пытается создать number из него, в то время как вы хотите, чтобы он соответствовалINTEGER, а затем ., как вы уже сказали в своем ОП.

Чтобы исправить это, вам нужно дать парсеру немного дополнительного упреждения, чтобы «увидеть» за пределами этой двусмысленности.Сделайте это, добавив предикат (INTEGER '.' INTEGER)=> перед фактическим сопоставлением указанного ввода:

number
  :  HEX_NUMBER 
  |  (INTEGER '.' INTEGER)=> INTEGER '.' INTEGER 
  | INTEGER
  ;

Теперь ваш ввод сгенерирует следующее дерево разбора:

enter image description here

1 голос
/ 11 ноября 2011

Возможно, не связано, но мне все равно любопытно:

function : ID '(' args ')' '->' statement+ (','statement+) '.' ;

Должно ли это быть вместо:

function : ID '(' args ')' '->' statement (',' statement)* '.' ;

Я думаю, что для первого потребуется одна запятая в определении функции, а для второго потребуется запятая в качестве разделителя операторов.

Кроме того, правило для args разрешает z -> 42 правильно?

...