Я хочу реализовать настраиваемый и расширяемый класс лексеров.
Моя идея
2 различных типа обработчиков :
- Обработчики набора символов
- Обработчики функций
Когда символ читается, он проталкивается через все обработчики, зарегистрированные в лексере.Как только обработчик сопоставляет и возвращает действительный токен , он возвращается.Когда ни один обработчик не соответствует символу, вызывается функция в худшем случае , и если она не возвращает действительный токен , следующий символ читается и он рекурсивно продолжается.
Обработчик набора символов состоит из строки и функции, принимающей три аргумента.Строка представляет собой набор символов, которые будут вызывать функцию, если в этой строке содержится текущий проанализированный символ.Функция может возвращать Нет , если она не может создать токен следующих символов.Функция должна отодвинуть все символы обратно для чтения, чтобы создать Token , если они не могут быть обработаны.Символы, которые были перенесены обратно в сканер, будут возвращены при следующем вызове scanner.read_next_char()
, это позволяет читать входной поток байтов, как будто функция никогда не касалась сканера.
A обработчик функции - это функция, принимающая три аргумента, которая возвращает действительный токен или нет , если не удалось создать действительный токен со следующими символамисимвол, который вызывал обработчик, точно так же, как функции, связанные с набором символов выше.
Функция в худшем случае вызывается, когда никакой обработчик не может создатьдействительный токен от текущего и последующих символов, соответствующий описанному выше шаблону.
Каждый обработчик принимает три аргумента: лексер , сканер используется лексером (для чтения следующих символов) и текущим символом, который фактически вызвал обработчик.
Сам лексер и дескрипторrs разделены.
class LexingRules(object):
def __init__(self):
self.charset_handlers = []
self.function_handlers = []
self.worst_case = None
# convenient methods for adding handlers
class Lexer(object):
def __init__(self, scanner, rules):
self.scanner = scanner
self.rules = rules
self.current_token = None
self.read_next_token()
def read_next_token(self):
current_char = self.scanner.current_char
for charset, handler in self.rules.charset_handlers:
if current_char in charset:
token = handler(self, self.scanner, current_char)
if isinstance(token, Token):
self.current_token = token
return token
for function in self.rules.function_handlers:
token = function(self, self.scanner, current_char)
if isinstance(token, Token):
self.current_token = token
return token
if self.rules.worst_case:
token = self.rules.worst_case(self, self.scanner, current_char)
if isinstance(token, Token):
self.current_token = token
return token
self.scanner.read()
return self.read_next_token()
Возможный подкласс LexingRules
import string
class MyLexingRules(LexingRules):
def __init__(self):
super(MyLexingRules, self).__init__()
self.charset_handlers.append(string.ascii_letters, self.handle_letters)
def handle_letters(self, lexer, scanner, char):
tkn = ''
while scanner.current_char in string.ascii_letters:
tkn += scanner.current_char
scanner.read()
return Token(tkn, TOKEN_ID_IDENTIFIER)
Цель
Разделениебазовых реализаций Lexer и жестко запрограммированных операций Lexing.
В настоящее время я нахожусь в начале собственного проекта.Я хочу создать расширяемый скомпилированный / переведенный язык.Синтаксис, оператор-расширение и т. Д. Должны быть возможны для создания.
Вопрос
Что вы думаете о дизайне лексера, есть ли у вас на что жаловаться?о, или идея, как его улучшить, добавив больше функциональности?