クエリパーサーのような単純な SQL 選択に取り組んでおり、特定の場所で発生する可能性のあるサブクエリを文字通りキャプチャできるようにする必要があります。lexer 状態が最適なソリューションであることがわかり、中かっこを使用して POC を実行して開始と終了をマークすることができました。ただし、サブクエリは中括弧ではなく括弧で区切られ、括弧は他の場所でも発生する可能性があるため、すべてのオープン括弧で状態になることはできません. この情報はパーサーですぐに利用できるので、パーサー ルールの適切な場所で begin と end を呼び出したいと考えていました。ただし、レクサーはストリームを一度にトークン化するように見えるため、これは機能しませんでした。したがって、トークンは INITIAL 状態で生成されます。この問題の回避策はありますか? これが私がやろうとしたことの概要です:
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
lexer トークンは、閉じ括弧を検出するためだけに存在します。
@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
助けていただければ幸いです。