Estoy trabajando en un SQL simple como el analizador de consultas y necesito poder capturar subconsultas que pueden ocurrir literalmente en ciertos lugares. Encontré que los estados de Lexer son la mejor solución y pude hacer un POC usando llaves para marcar el inicio y el final. Sin embargo, las subconsultas estarán delimitadas por paréntesis, no por curlys, y el paréntesis también puede ocurrir en otros lugares, por lo que no puedo ser el estado con cada tabla abierta. Esta información está disponible con el analizador, por lo que esperaba llamar a inicio y final en las ubicaciones apropiadas en las reglas del analizador. Sin embargo, esto no funcionó porque Lexer parece tokenizar la secuencia de una sola vez, por lo que los tokens se generan en el estado INICIAL. ¿Hay alguna solución alternativa a este problema? He aquí un resumen de lo que he intentado hacer:Controlando Python PLY estados lexer del analizador
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
El start_subquery() y end_subquery() se definen así:
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
Las fichas lexer simplemente están ahí para detectar los primeros 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
Agradeceria cualquier ayuda.
Gracias por el puntero a acciones dmbedded, parece muy prometedor. Sin embargo, en tu ejemplo, se supone que debemos verificar el token de búsqueda anticipada en lugar del último token. El último token sería 'B', pero el lookahead sería' LBRACE' ¿verdad? – haridsv