По соглашению, синтаксис нашего исходного языка имеет вид:
ТипДанных идентификатор1[, идентификатор2[, … [, идентификаторN]]]
begin
[последовательность команд]
end
Так как мы реализуем однопроходный транслятор, синтаксический и лексический анализ должны выполняться параллельно, поэтому методы лексического анализатора будут вызываться преимущественно из методов синтаксического анализатора.
В первую очередь в синтаксическом анализаторе (класс SyntaxAnalyzer) необходимо определить вспомогательный метод, который будет проверять текущую лексему на соответствие лексеме ожидаемой.
проверитьЛексему(Lexems ожидаемаяЛексема)
{
если(LexicalAnalyzer.текущаяЛексема!= ожидаемаяЛексема)
ошибка();
иначе
LexicalAnalyzer.разобратьСледующуюЛексему();
}
Далее определим метод разбора секции объявления переменных:
разобратьОбъявлениеПеременных()
{
проверитьЛексему(Lexems.ТипДанных);
если(LexicalAnalyzer.текущаяЛексема!= Lexems.Идентификатор)
ошибка();
иначе
{
NameTable.добавитьИдентификатор(LexicalAnalyzer.текущееИмя,, tCat.Var);
LexicalAnalyzer.разобратьСледующуюЛексему();
}
пока(LexicalAnalyzer.текущаяЛексема == Lexems.Запятая)
{
если(LexicalAnalyzer.текущаяЛексема!= Lexems.Идентификатор)
ошибка();
иначе
{
NameTable.добавитьИдентификатор(LexicalAnalyzer.текущееИмя,, tCat.Var);
LexicalAnalyzer.разобратьСледующуюЛексему();
}
}
}
Основным методом анализатора будет метод запуска синтаксического разбора. В нем мы и будем вызывать описанный выше метод.
компилировать()
{
LexicalAnalyzer.инициализировать();
разобратьОбъявлениеПеременных();
проверитьЛексему(Lexems.ПереносСтроки);
}
Тестирование описанного функционала можно провести, вызывая метод SyntaxAnalyzer.компилировать() для разных (в том числе некорректных) вариантов объявления переменных.
Замечания по коду:
1) Реализация метода ошибка() не должна допускать остановки синтаксического разбора. По окончанию разбора пользователю должны быть выведены все ошибки, возникшие в ходе синтаксического анализа.
2) В сообщениях о синтаксических ошибках необходимо указывать информацию о месте их возникновения. Получить эти сведения можно с помощью методов-свойств класса Reader: Reader.номерСтроки, Reader.позицияСимволаВСтроке, Reader.текущийСимвол.
Примеры кода:
Файл SyntaxAnalyzer.cs в проекте.
Лабораторная работа № 6.
Лабораторная работа №3.2. Синтаксический анализатор.