Есть ли способ улучшить эту грамматику ANTLR 3 для положительных и отрицательных целых и десятичных чисел?

#numbers #integer #decimal #grammar #antlr3

#числа #целое #десятичная #грамматика #antlr3

Вопрос:

Есть ли способ выразить это менее повторяющимся способом с необязательными положительными и отрицательными знаками?

Чего я пытаюсь достичь, так это того, как выразить необязательное предоставление положительных (по умолчанию) и отрицательных - знаков в числовых литералах, которые необязательно имеют показатели степени и / или десятичные части.

 NUMBER : (' '|'-')? DIGIT  '.' DIGIT* EXPONENT?
       | (' '|'-')? '.'? DIGIT  EXPONENT?
       ;

fragment 
EXPONENT : ('e' | 'E') (' ' | '-') ? DIGIT  
         ;

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

Я хочу иметь возможность распознавать NUMBER шаблоны, и на данный момент меня не так беспокоит арифметика для этих чисел, я расскажу позже, но я пытаюсь понять, как распознавать любые NUMBER литералы, где числа выглядят как:

 123
 123
-123
0.123
 .123
-.123
123.456
 123.456
-123.456
123.456e789
 123.456e789
-123.456e789 
  

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

Ответ №1:

Отвечая на ваш вопрос: нет, нет способа улучшить этот AFAIK. Вы могли бы поместить (' ' | '-') внутрь правила фрагмента и использовать этот фрагмент, точно так же, как фрагмент экспоненты, но я бы не назвал это реальным улучшением.

Обратите внимание, что унарные знаки и - обычно не являются частью числового токена. Рассмотрим источник ввода "1-2" . Вы не хотите, чтобы это обозначалось как 2 числа: NUMBER[1] и NUMBER[-2] , но как NUMBER[1] , MINUS[-] и NUMBER[2] , чтобы ваш анализатор содержал следующее:

 parse
  :  statement  EOF
  ;

statement
  :  assignment
  ;

assignment
  :  IDENTIFIER '=' expression
  ;

expression
  :  addition
  ;

addition
  :  multiplication ((' ' | '-') multiplication)*
  ;

multiplication
  :  unary (('*' | '/') unary)*
  ;

unary
  :  '-' atom
  |  ' ' atom
  |  atom
  ;

atom
  :  NUMBER
  |  IDENTIFIER
  |  '(' expression ')'
  ;

IDENTIFIER
  :  ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
  ;

NUMBER 
  :  DIGIT  '.' DIGIT* EXPONENT?
  |  '.'? DIGIT  EXPONENT?
  ;

fragment 
EXPONENT 
  :  ('e' | 'E') (' ' | '-') ? DIGIT  
  ;

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

и addition будет ли для этого соответствовать вводу "1-2" .

Редактировать

Выражение типа 111.222 -456 будет проанализировано следующим образом:

введите описание изображения здесь

и 123 -456 как:

введите описание изображения здесь

Комментарии:

1. @Jarrod, но как ты будешь анализировать 1--2 ? Мое предложение обрабатывает это должным образом.

2. … и - 3 (минус пробел)?

3. Как выглядит определение NUMBER в вашем примере, я не понимаю, как это работает без этого примера.

4. @Jarrod, да, это было немного запутанно. Добавлены правила лексера к моему примеру.

5. @Jarrod, я добавил несколько правил к грамматике моего примера.