Я работаю над простым SQL-выбором, подобным синтаксическому анализатору запросов, и мне нужно иметь возможность перехватывать подзапросы, которые могут встречаться в определенных местах буквально. Я обнаружил, что лексеры - лучшее решение, и я смог создать POC с помощью фигурных скобок, чтобы отметить начало и конец. Тем не менее, подзапросы будут разделяться круглыми, а не фигурными скобками, и скобки могут встречаться и в других местах, поэтому я не могу быть государством с каждым открытым пареном. Эта информация легко доступна с анализатором, поэтому я надеялся вызвать начало и конец в соответствующих местах в правилах синтаксического анализа. Это, однако, не сработало, потому что лексер, кажется, токенизировал поток сразу, и поэтому токены генерируются в начальном состоянии. Есть ли решение этой проблемы? Вот схема того, что я пытался сделать:
def p_value_subquery(p):
"""
value : start_sub end_sub
"""
p[0] = "( " + p[1] + " )"
def p_start_sub(p):
"""
start_sub : OPAR
"""
start_subquery(p.lexer)
p[0] = p[1]
def p_end_sub(p):
"""
end_sub : CPAR
"""
subquery = end_subquery(p.lexer)
p[0] = subquery
start_subquery () и end_subquery () определены следующим образом:
def start_subquery(lexer):
lexer.code_start = lexer.lexpos # Record the starting position
lexer.level = 1
lexer.begin('subquery')
def end_subquery(lexer):
value = lexer.lexdata[lexer.code_start:lexer.lexpos-1]
lexer.lineno += value.count('\n')
lexer.begin('INITIAL')
return value
Жетоны лексеров просто существуют для обнаружения близких:
@lex.TOKEN(r"\(")
def t_subquery_SUBQST(t):
lexer.level += 1
@lex.TOKEN(r"\)")
def t_subquery_SUBQEN(t):
lexer.level -= 1
@lex.TOKEN(r".")
def t_subquery_anychar(t):
pass
Буду признателен за любую помощь.