Tôi đang làm việc trên một SQL đơn giản giống như trình phân tích cú pháp truy vấn và tôi cần có khả năng nắm bắt các truy vấn phụ có thể xảy ra ở một số nơi nhất định. Tôi tìm thấy các trạng thái lexer là giải pháp tốt nhất và có thể làm một POC sử dụng dấu ngoặc nhọn để đánh dấu sự bắt đầu và kết thúc. Tuy nhiên, các truy vấn phụ sẽ được phân cách bằng dấu ngoặc đơn, không phải dấu ngoặc và dấu ngoặc đơn cũng có thể xuất hiện ở những nơi khác, vì vậy tôi không thể là trạng thái với mọi dấu ngoặc mở. Thông tin này có sẵn với trình phân tích cú pháp, vì vậy tôi đã hy vọng sẽ bắt đầu và kết thúc tại các vị trí thích hợp trong các quy tắc của trình phân tích cú pháp. Tuy nhiên, điều này không hiệu quả vì lexer dường như mã hóa luồng tất cả cùng một lúc và do đó các mã thông báo được tạo trong trạng thái INITIAL. Có cách giải quyết nào cho vấn đề này không? Dưới đây là một phác thảo của những gì tôi đã cố gắng để làm:Kiểm soát trạng thái PLY của Python PLY từ trình phân tích cú pháp
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
Các start_subquery() và end_subquery() được định nghĩa như thế này:
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
Các thẻ lexer chỉ đơn giản là có để phát hiện các cận 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
Tôi sẽ đánh giá cao bất kỳ trợ giúp nào.
Cảm ơn con trỏ đến hành động được nhúng, có vẻ rất hứa hẹn. Tuy nhiên, trong ví dụ của bạn, chúng ta phải kiểm tra mã thông báo tra cứu thay vì mã thông báo cuối cùng? Mã thông báo cuối cùng sẽ là 'B', nhưng lookahead sẽ là' LBRACE' đúng không? – haridsv