Использование анализатора ANTLR и лексера отдельно

#c# #grammar #antlr4 #lexer

#c# #грамматика #antlr4 #лексер

Вопрос:

Я использовал ANTLR версии 4 для создания компилятора.Первым этапом была часть лексера. Я создал файл «CompilerLexer.g4» и поместил в него правила лексера.Это работает нормально.

CompilerLexer.g4:


 lexer grammar CompilerLexer;

INT         :   'int'   ;   //1
FLOAT       :   'float' ;   //2
BEGIN       :   'begin' ;   //3
END         :   'end'   ;   //4
To          :   'to'    ;   //5
NEXT        :   'next'  ;   //6
REAL        :   'real'  ;   //7
BOOLEAN     :   'bool'  ;   //8
.
.
.
NOTEQUAL    :   '!='    ;   //46
AND         :   'amp;amp;'    ;   //47
OR          :   '||'    ;   //48
POW         :   '^'     ;   //49
ID          : [a-zA-Z]  ;   //50




WS
:   ' ' -> channel(HIDDEN)  //50
;
  

Теперь пришло время для фазы 2, которая является синтаксическим анализатором.Я создал файл «CompilerParser.g4» и вставил в него грамматики, но получил десятки предупреждений и ошибок.

CompilerParser.g4:


 parser grammar CompilerParser;

options {   tokenVocab = CompilerLexer; }

STATEMENT   :   EXPRESSION SEMIC
        |   IFSTMT
        |   WHILESTMT
        |   FORSTMT
        |   READSTMT SEMIC
        |   WRITESTMT SEMIC
        |   VARDEF SEMIC
        |   BLOCK
        ;

BLOCK       : BEGIN STATEMENTS END
        ;

STATEMENTS  : STATEMENT STATEMENTS*
        ;

EXPRESSION  : ID ASSIGN EXPRESSION
        | BOOLEXP
        ;

RELEXP      : MODEXP (GT | LT | EQUAL | NOTEQUAL | LE | GE | AND | OR) RELEXP
        | MODEXP
        ;

.
.
.

VARDEF      : (ID COMA)* ID COLON VARTYPE
        ;

VARTYPE     : INT
        | FLOAT
        | CHAR
        | STRING
        ;
compileUnit
:   EOF
;
  

Предупреждение и ошибки:

  • неявное определение «БЛОКА» токена в анализаторе
  • неявное определение токена ‘BOOLEXP’ в синтаксическом анализаторе
  • неявное определение токена ‘EXP’ в синтаксическом анализаторе
  • неявное определение маркера ‘EXPLIST’ в синтаксическом анализаторе
  • правило лексера «БЛОК» не разрешено в синтаксическом анализаторе
  • правило лексера ‘EXP’ не разрешено в синтаксическом анализаторе
  • правило лексера ‘EXPLIST’ не разрешено в синтаксическом анализаторе
  • правило лексера «ВЫРАЖЕНИЕ» не разрешено в синтаксическом анализаторе

Есть десятки таких предупреждений и ошибок. В чем причина?

Общие вопросы: В чем разница между использованием комбинированной грамматики и использованием лексера и синтаксического анализатора по отдельности? Как объединить отдельные файлы грамматики и лексера?

Ответ №1:

Правила лексера начинаются с заглавной буквы, а правила синтаксического анализатора начинаются со строчной буквы. В грамматике синтаксического анализатора вы не можете определять токены. И поскольку ANTLR считает, что все ваши правила в верхнем регистре являются правилами лексера, он выдает ошибки / предупреждения.

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

пользователь2998131 написал:

Общие вопросы: В чем разница между использованием комбинированной грамматики и использованием лексера и синтаксического анализатора по отдельности?

Разделение правил синтаксического анализатора и синтаксического анализатора позволит упорядочить вещи. Кроме того, при создании отдельных грамматик лексера и синтаксического анализатора вы не можете (случайно) поместить литеральные токены в свою грамматику синтаксического анализатора, но вам нужно будет определить все токены в вашей грамматике lexer. Это сделает очевидным, какие правила лексера сопоставляются раньше других, и вы не сможете сделать никаких опечаток внутри повторяющихся литеральных токенов:

 grammar P;

r1 : 'foo' r2;

r2 : r3 'foo '; // added an accidental space after 'foo'
  

Но когда у вас есть грамматика синтаксического анализатора, вы не можете совершить эту ошибку. Вам нужно будет использовать правило лексера, соответствующее ‘foo’:

 parser grammar P

options { tokenVocab=L; }

r1 : FOO r2;

r2 : r3 FOO;


lexer grammar L;

FOO : 'foo';
  

пользователь2998131 написал:

Как объединить отдельные файлы грамматики и лексера?

Точно так же, как вы делаете в своей грамматике синтаксического анализатора: вы указываете на правильное tokenVocab значение внутри options { ... } блока.

Обратите внимание, что вы также можете импортировать грамматики, что является чем-то другим: https://github.com/antlr/antlr4/blob/master/doc/grammars.md#grammar-imports

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

1. @user2998131, ах, пропустил это. Ответит на них позже.

2. @user2998131, проверь мою ПРАВКУ .

3. Если бы я мог пойти немного дальше, написание комбинированной грамматики означает, что язык подталкивает вас к написанию контекстно-зависимых правил лексера. Это противоречит тому, как работают большинство лексеров, включая лексер ANTLR. В моем случае — как, вероятно, обычный случай — используя комбинированную грамматику, я добавлял ключевые слова в ряде мест, которые удаляли набор строк для моего общего ID правила лексера. С разделенными файлами грамматики лексера / синтаксического анализатора это становится действительно очевидным, поскольку теперь вы должны объявить запись лексера для каждого ключевого слова, и это подчеркивает отсутствие контекста, в котором должен работать лексер.

4. @Peanut изменил ссылку

5. Да, «комбинированная» грамматика содержит как правила лексера, так и правила синтаксического анализатора в 1 файле грамматики. Использование tokenVocab внутри грамматики синтаксического анализатора (что вы должны сделать) позволит вам указать грамматику синтаксического анализатора на правила лексера, необходимые грамматике синтаксического анализатора. Импорт грамматик — это то, что помимо всего этого может делать грамматика с комбинированным синтаксическим анализатором или лексером.