Маркеры
 

Интерфейс

Основной глобальный интерфейс лексера из lex.bas:
    • lexGetToken(): Получить идентификатор текущей лексемы, значения FB_TK_*
    • lexGetLookAhead(N): Просмотр вперед N маркеров
    • lexSkipToken(): Переход к следующему маркеру
    • lexGetText(): Возвращает zstring ptr текста текущего маркера, например, литералы строки/числа , или текстовое представление других маркеров (например, операторы).
    •  lexGet*() метод доступа к данным текущего маркера
    • lexPeekLine(): Используется как отчет об ошибках для получения текущей строки кода.

Текущий маркер + вперед просматриваемые маркеры

Маркеры имеют короткий срок существования. Там только текущий код и несколько просматриваемых впереди маркеров в символической очереди. Это все потребности парсера дешифровать код FB. Обычный образец должен проверить текущий маркер, решить, что сделать затем на основе этого, затем пропустить его и идите дальше. Обратное перемещение не возможно. Имя файла, номер строки и символическая позиция, показанная во время сообщения об ошибке также, вытекают из текущего состояния лексера.

Маркер очереди является статическим массивом маркеров, содержащие ячейки для текущего маркера плюс немного просматриваемых впереди маркеров. Структуры маркеров содержат довольно огромные (статические) буферы для маркера текста. У каждого маркера есть указатель на следующий, таким образом, они формируют циклический список. Это - дешевый способ продвигаться и пропускать маркеры, не имея необходимости заботиться об индексе массива. Копирование вокруг самих маркеров исключено из-за огромных текстовых буферов. "head" указывает на текущий маркер; следующие "k" маркеры предусматривают вперед просматриваемые маркеры; остальные не используются. При пропуске мы просто делаем "head = head->next". Если новый head уже не содержит маркер (по некоторым прогнозам это сделано раньше), мы загружаем новый маркер в новый текущий маркер struct (через lexNextToken ()). Просматривается работа вперед , загружая следующие маркеры в очереди (но не пропуская текущий).

Разбиения на лексемы
lex.bas:lexNextToken()

Лексер разрывает файловый ввод на маркеры. Маркер концептуально - идентификатор, ключевое слово, строковый литерал, литерал числа, оператор, EOL или EOF или другие символы как круглые скобки и запятые. Каждый маркер как уникальное значение, присвоенное ему, будет использоваться парсером для идентификации его, вместо того, чтобы делать сравнения строк (которое было бы слишком медленным).

lexNextToken() использует текущий символ, и в случае необходимости также следующий символ, чтобы проанализировать ввод. Числовые и строковые литералы обрабатываются тоже здесь. Алфавитно-цифровые идентификаторы ищутся в symb хэш-таблице, которая скажет, является ли это ключевым словом, макросом или другим символом FB (тип, процедура, переменная...).

Идентификаторы, содержащие точки (совместимость QB) и суффиксы (как stringvar$), обрабатываются тоже здесь (но не доступ к элементам пространств имен или структуры). Маркер может иметь тип данных, связанный с ним. Это также используется с литералами чисел, у которых могут быть суффиксы (как &hFFFFFFFFFFFFFFFFull).

Примечание на однострочные комментарии

Довольно необычно обрабатывать однострочные комментарии парсером вместо того, чтобы пропустить их с помощью лексера. Это сделано так, чтобы использование REM могло быть легко ограничено, поскольку в QB REM больше походит на оператор, чем на комментарий. Кроме того, комментарии могут содержать QB мета заявления, так что комментарии нельзя просто игнорировать. Обратите внимание, что парсер будет пропускать оставшуюся часть комментария , если он не найдет QB мета заявление.

(Многострочные же комментарии полностью обрабатываются во время работы с маркерами)

Входной файл
lex.bas:hReadChar()

Входной файл открывается в fb.bas:fbCompile (); номер файла сохраняется в глобальном контексте (подобно для #includes в fb.bas:fbIncludeFile ()). Лексер использует номер файла из контекста, чтобы считать ввод оттуда. У него есть статический буфер zstring, который используется, чтобы передать содержимое файла потоком (вместо того, чтобы читать символ за символом), а для ввода Unicode, лексер использует буфер wstring и декодирует UTF32 или UTF8 к UTF16. Символы в буфере преобразоваются лексерем и затем идет чтение в следующем блоке файла. EOF представлен, как возврат нулевого символа.