Sto lavorando su una semplice selezione SQL come il parser di query e devo essere in grado di acquisire le sottoquery che possono verificarsi in determinati posti letteralmente. Ho trovato gli stati lexer sono la soluzione migliore ed è stato in grado di fare un POC utilizzando parentesi graffe per segnare l'inizio e la fine. Tuttavia, le subquery saranno delimitate da parentesi, non da curlys, e la parentesi può verificarsi anche in altri luoghi, quindi non posso essere lo stato di ogni open-paren. Queste informazioni sono prontamente disponibili con il parser, quindi speravo di chiamare begin e end nelle posizioni appropriate nelle regole del parser. Ciò tuttavia non ha funzionato perché il lexer sembra tokenizzare il flusso tutto in una volta, e così i token vengono generati nello stato INITIAL. C'è una soluzione per questo problema? Ecco una descrizione di ciò che ho cercato di fare:Controllo degli stati lexer di PLY Python dal parser
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
Lo start_subquery() e end_subquery() sono definiti in questo modo:
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
I gettoni lexer sono semplicemente lì per rilevare i primi paren :
@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
Apprezzerei qualsiasi aiuto.
Grazie per il puntatore alle azioni incorporate, sembra molto promettente. Tuttavia, nel tuo esempio, dovremmo controllare il token lookahead invece dell'ultimo token? L'ultimo token sarebbe 'B', ma il lookahead sarebbe' LBRACE' giusto? – haridsv