Для начало скажу, что не прямой анализатор - это анализатор с возможностью отката при не удачной попытке распознать лексему. Он очень удобен для развивающихся языков и прост в создании и улучшении. Единственный недостаток - он работает медленнее прямого анализатора. Но этот недостаток всегда легко устраним.
Теперь о самом базовом классе анализатора. Все что нужно базовому классу, так это: считывание следующего символа во входном коде, откат, откат на один символ и обнуление отката. Из числа переменных, следующие: считанный символ, значение лексемы (к примеру название идентификатора), размер буффера для хранения значения лексемы, текущая позиция (строка и столбец) при чтении символа из вх. кода, кол-во пройденных строк и стоблцов при распозновании лексемы для возможности ее отката, код ошибки произошедший в случае не распознования лексемы (в данном случае допущенной ошибки со стороны пользователя), сам буффер входного кода ввиде массива и переменная достижения конца вх. кода.
Всего этого достаточно для того, чтобы на основе даного базового класса построить свой конечный класс, в которым вы определяете методы проверки принадлежности символа к определенным классам символов (к примеру класс чисел, игнорируемых и пробельных символов и т.д.), там же прописываете все методы для запуска анализатора и выдачи списка готовых и разобранных лексем, которые нужны для синтаксического анализа.
Нужно учитывать некоторые ньюансы.
Во-первых, перед запуском лексического анализатора (именно для него и создан данный класс), присвоить текущей строке ноль, а столбцу -1 и не трогать в процессе лексического разбора переменную тек. поз., т.о. устанавливается начальная позиция пера для считывания первого символа.
Во-вторых, перед запуском анализатора, нужно ввести значение для массива вх.кода, иначе вы можете вызвать неуправляемое исключение. Такое исключение не имеет смысла отлавливать в базовом классе, т.к. перед считыванием символа из вх.кода, массив вх. кода не должен быть пустым, иначе работа анализатора лишена всякого смысла.
В-третьих, чтобы не сделать бесконечный цикл, нжуно использовать переменную достижения конца файла, т.к. при истине данной переменной считываемый последний символ останется тем же и вы будете постоянно достигать конца вх.кода, хотя ошибки это не вызовет.
И в-четвертых, данный анализатор нужно использовать для распознования лексем в последовательном порядке, а не хаотичном. Т.е. распознование символов пробела и игнорируемых, а также лексем комментария стоит ставить на проверку раньше остальных.
Данного объяснения на мой взгляд достаточно для тех, кто уже имел дело с анализатора вх.кода или хотя бы читал о них.
Неактивен
Начну от частного к общему.
Eten написал:
размер буффера для хранения значения лексемы,
Я думал, что современные языки программирования (венцом которых, несомненно, является Си шарп ;) свободны от такой чепухи, как ручное выделение памяти под строки. Или я ошибался?
текущая позиция (строка и столбец) при чтении символа из вх. кода,
Текст (в частности и особенно, XML) для алгоритма разбора удобнее воспринимать линейным потоком символов, нежели двумерным массивом со стоками и колонками. Кстати, раньше ты говорил, что твоему анализатору всё равно откуда подают текст. Так вот, в цивилизованном мире давно уже пользуются потоками (stream) для этих целей, а не передают массивом в памяти.
Даже если ты пишешь абстрактный анализатор, он должен работать со словарём, а не с отдельными символами.
Сдаётся мне, что СТК начал буксовать и ты пытаешься спасти наработанное для будущих поколений. Скажи, что я не прав. %)
Неактивен
Eten написал:
Так, что смысл применения словаря в данном предложении совершенно не понятен.
У тебя нет механизмов поддержки словаря. Отдельные символы текста интереса для анализа не представляют. Интерес представляют слова и словосочетания. В нашем случае нужен именно анализатор слов.
класс Алфавита разрабтывался вовсе не для анализатора, что в принципе не мешает ему быть использованным здесь - это я и называю хорошим программированием и разработкой классов в одном флаконе, также делают и остальные.
Я называю программирование хорошим, если в результате программа отлично выполняет то, что от неё требуется. Если при этом ещё и в исходник не страшно заглянуть, то вообще замечательно.
Неактивен