#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
внутри грамматики синтаксического анализатора (что вы должны сделать) позволит вам указать грамматику синтаксического анализатора на правила лексера, необходимые грамматике синтаксического анализатора. Импорт грамматик — это то, что помимо всего этого может делать грамматика с комбинированным синтаксическим анализатором или лексером.