我正在开发一个简单的 SQL 选择,例如查询解析器,我需要能够从字面上捕获可能在某些地方发生的子查询。我发现词法分析器状态是最好的解决方案,并且能够使用花括号来标记开始和结束来进行 POC。但是,子查询将由括号而不是花括号分隔,并且括号也可以出现在其他地方,所以我不能成为每个开放括号的状态。解析器很容易获得此信息,因此我希望在解析器规则中的适当位置调用开始和结束。然而这并没有奏效,因为词法分析器似乎一次对流进行了标记,因此标记是在 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
词法分析器标记只是用来检测近括号:
@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
我将不胜感激任何帮助。