Ошибка в грамматике распознавателя для анализа описаний типов данных и переменных в ANTLR4

#antlr4

#antlr4

Вопрос:

Мне нужно реализовать синтаксический анализатор для этого типа логики: указанная грамматика

Символ S является начальным символом грамматики; L, T, R, V, K, D, F и E обозначают нетерминальные символы. Конечный символ c соответствует одному из двух скалярных типов, указанных в задаче. Символ терминала t соответствует одному из типов данных, которые могут быть описаны в разделе тип. Я создал следующую грамматику:

 grammar Parse;
compileString: S ;

S:  TYPE L VAR R;
L:  T (SEPARATOR|SEPARATOR L);
R:  V (SEPARATOR|SEPARATOR R);
V:  [a-zA-Z] ([a-zA-Z]| [0-9]|'_')* DEFINITION (D|C);
T:  D|C;

TYPE:'type';
VAR:'var';

D: // acceptable data types
    'struct'
    | 'union'
    | 'array'
    ;
C:  'byte'
    |'word' //scalar type
;
SEPARATOR:';';
DEFINITION :':';
WS  : [ tnr]  -> skip ; // whitespaces
  

Но когда я пытаюсь выполнить его для построения: «введите byte; var p1:word;», я получаю следующий вывод:

 Tokens:
[@0,0:3='type',<6>,1:0]
[@1,5:9='byte;',<2>,1:5]
[@2,11:13='var',<7>,1:11]
[@3,15:22='p1:word;',<3>,1:15]
[@4,23:22='<EOF>',<-1>,1:23]

Parse Tree:
compileString (
  <Error>"type"
  <Error>"byte;"
  <Error>"var"
  <Error>"p1:word;"
)
  

Я не понимаю, в чем может быть проблема, отладка выполнялась в VS Code с помощью плагина от Antlr. Буду рад любому ответу!

Ответ №1:

В ANTLR правила лексера начинаются с заглавных букв, а правила синтаксического анализатора — со строчных букв. Итак, все ваши правила, кроме compileString правил лексера.

S: TYPE L VAR R; не соответствует вводу type byte; var p1:word; , потому что в нем есть пробелы, и ничто в определении S не соответствует пробелам. Вы, вероятно, думаете, что это не должно иметь значения, потому что вы пропускаете пробелы, но токены пропускаются только между правилами лексера, а не внутри них. Так что это сработало бы, если S бы было правилом синтаксического анализатора, но не как правило лексера.

То же самое относится к пробелам между разделителем и L / R в L и R .

PS: Я настоятельно рекомендую давать вашим правилам более длинные имена, поскольку довольно сложно следовать вашей грамматике. Вы также можете рассмотреть возможность использования оператора в L и R вместо рекурсии.

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

1. Большое вам спасибо! Ваш комментарий мне очень помог, я сделал так, как вы посоветовали, и все заработало!