Управление состояниями лексера Python PLY из синтаксического анализатора

Я работаю над простым 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

Буду признателен за любую помощь.

7
задан haridsv 28 March 2012 в 05:49
поделиться