ANLTR4: анализировать как целочисленные, так и с плавающей точкой

#antlr #antlr4

#antlr #antlr4

Вопрос:

Я пытаюсь использовать ANLTR4 для анализа 2 типов выражений:

  1. парные выражения представляют собой пару целых или чисел с плавающей запятой, например (1,2) или (1.0 , 2.0) .
  2. отдельные выражения представляют собой одно целое (1) число.

Я разработал свою грамматику, как показано ниже, но

  • Если я напишу INT раньше NUM , выражения пары с целыми числами, например (1, 2) , не могут быть помечены из-за ожидания NUM ;
  • Если я напишу NUM раньше INT , отдельные выражения, такие как (1) , не могут быть помечены из-за ожидания a INT .
 grammar Expr;

prog   : single | pair ;
single : '(' INT ')' ;
pair   : '(' NUM ',' NUM ')' ;

INT   : [0-9]  ;
NUM   : INT | FLOAT ;
FLOAT : '-'? INT '.' INT ;
WS    : [ trn] -> skip ;
  

Чтобы оба выражения можно было маркировать, я могу удалить NUM lexer и вручную написать pair , как:

 pair : '(' INT   ',' INT   ')'
     | '(' INT   ',' FLOAT ')'
     | '(' FLOAT ',' INT   ')'
     | '(' FLOAT ',' FLOAT ')'
     ;
  

тогда можно анализировать оба выражения, а выражение pair поддерживает как целые числа, так и числа с плавающей запятой.

Но это глупо, поскольку, если это не пара, а tuple10, невозможно записать 1024 случая.

Есть ли лучшее решение?

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

1. ДА. Поднимите NUM до уровня синтаксического анализатора, num : INT | FLOAT; tuple10 : '(' num, num, num, ....... ')'; , и удалите NUM .

Ответ №1:

Как уже упоминалось в комментарии kaby76: переход NUM к правилу синтаксического анализа. Не имеет большого смысла определять INT и FLOAT в лексере, а затем определять a NUM , который создает токены INT и FLOAT никогда не становится реальными токенами самостоятельно.

 prog   : single | pair ;
single : '(' INT ')' ;
pair   : '(' num ',' num ')' ;
num    : INT | FLOAT ;

INT    : [0-9]  ;
FLOAT  : '-'? INT '.' INT ;
WS     : [ trn] -> skip ;