2011-09-08 36 views
6

Tôi biết có các công cụ khác để phân tích cú pháp câu lệnh SQL, nhưng tôi đang triển khai các mục đích giáo dục của riêng mình. Tôi đang bị mắc kẹt với ngữ pháp của tôi ngay bây giờ .. Nếu bạn có thể phát hiện ra một lỗi thực sự nhanh chóng xin vui lòng cho tôi biết.Sử dụng PLY để phân tích cú pháp câu lệnh SQL

SELECT = r'SELECT' 
FROM = r'FROM' 
COLUMN = TABLE = r'[a-zA-Z]+' 
COMMA = r',' 
STAR = r'\*' 
END = r';' 
t_ignore = ' ' #ignores spaces 

statement : SELECT columns FROM TABLE END 

columns : STAR 
     | rec_columns 

rec_columns : COLUMN 
      | rec_columns COMMA COLUMN 

Khi tôi cố gắng phân tích cú pháp câu lệnh như 'CHỌN TỪ b;' Tôi nhận được lỗi cú pháp tại mã thông báo FROM ... Bất kỳ trợ giúp nào đều được đánh giá cao!

(Chỉnh sửa) Code:

#!/usr/bin/python 
import ply.lex as lex 
import ply.yacc as yacc 

tokens = (
    'SELECT', 
    'FROM', 
    'WHERE', 
    'TABLE', 
    'COLUMN', 
    'STAR', 
    'COMMA', 
    'END', 
) 

t_SELECT = r'select|SELECT' 
t_FROM  = r'from|FROM' 
t_WHERE  = r'where|WHERE' 
t_TABLE  = r'[a-zA-Z]+' 
t_COLUMN = r'[a-zA-Z]+' 
t_STAR  = r'\*' 
t_COMMA  = r',' 
t_END  = r';' 

t_ignore = ' \t' 

def t_error(t): 
    print 'Illegal character "%s"' % t.value[0] 
    t.lexer.skip(1) 

lex.lex() 

NONE, SELECT, INSERT, DELETE, UPDATE = range(5) 
states = ['NONE', 'SELECT', 'INSERT', 'DELETE', 'UPDATE'] 
current_state = NONE 

def p_statement_expr(t): 
    'statement : expression' 
    print states[current_state], t[1] 

def p_expr_select(t): 
    'expression : SELECT columns FROM TABLE END' 
    global current_state 
    current_state = SELECT 
    print t[3] 


def p_recursive_columns(t): 
    '''recursive_columns : recursive_columns COMMA COLUMN''' 
    t[0] = ', '.join([t[1], t[3]]) 

def p_recursive_columns_base(t): 
    '''recursive_columns : COLUMN''' 
    t[0] = t[1] 

def p_columns(t): 
    '''columns : STAR 
       | recursive_columns''' 
    t[0] = t[1] 

def p_error(t): 
    print 'Syntax error at "%s"' % t.value if t else 'NULL' 
    global current_state 
    current_state = NONE 

yacc.yacc() 


while True: 
    try: 
     input = raw_input('sql> ') 
    except EOFError: 
     break 
    yacc.parse(input) 
+1

Điều gì xảy ra nếu bạn đặt dấu cách giữa 'b' và'; '? – zerkms

+0

Vẫn còn kết quả tương tự, tôi quên thêm rằng nó bỏ qua các khoảng trống ... Tôi sẽ chỉnh sửa điều đó. – sampwing

+1

Theo như tôi biết, hầu hết các cơ sở dữ liệu sẽ hỗ trợ ít nhất '[a-zA-Z_0-9]' làm bảng tên. – NullUserException

Trả lời

4

Tôi nghĩ vấn đề của bạn là cụm từ thông dụng cho t_TABLEt_COLUMN cũng phù hợp với từ dành riêng của bạn (SELECT và FROM). Nói cách khác, SELECT a FROM b; mã thông báo cho một cái gì đó như COLUMN COLUMN COLUMN COLUMN END (hoặc một số mã thông báo mơ hồ khác) và điều này không khớp với bất kỳ sản phẩm nào của bạn để bạn nhận được lỗi cú pháp.

Là một kiểm tra sanity nhanh chóng, thay đổi những biểu thức thông thường để phù hợp chính xác những gì bạn đang gõ vào như thế này:

t_TABLE = r'b' 
t_COLUMN = r'a' 

Bạn sẽ thấy rằng cú pháp SELECT a FROM b; đèo vì biểu thức chính quy 'a' và ' b 'không phù hợp với các từ dành riêng của bạn. Và, có một vấn đề khác nữa là các biểu thức chính quy cho TABLE và COLUMN trùng lặp, vì vậy, từ khoá không thể mã hóa mà không có sự mơ hồ đối với các mã thông báo đó.

Có một số subtle, but relevant section in the PLY documentation liên quan đến điều này. Bạn không chắc chắn cách tốt nhất để giải thích điều này, nhưng mẹo là mã thông báo xảy ra đầu tiên để nó không thể sử dụng ngữ cảnh từ các quy tắc sản xuất của bạn để biết liệu nó có gặp mã thông báo TABLE hay mã thông báo COLUMN hay không. Bạn cần phải khái quát hóa chúng thành một loại mã thông báo ID và sau đó loại bỏ mọi thứ trong khi phân tích cú pháp.

Nếu tôi có nhiều năng lượng hơn, tôi sẽ cố gắng làm việc thông qua mã của bạn và cung cấp giải pháp thực tế về mã, nhưng tôi nghĩ vì bạn đã cho biết đây là bài tập học tập có lẽ bạn sẽ có nội dung với tôi chỉ đúng hướng.

+1

Tôi chưa đọc hết câu trả lời của bạn với mã của tôi .. Nhưng khi bạn tham chiếu tài liệu, nó đã cho tôi một số thông tin chi tiết .. Nhiều đánh giá cao Joe! – sampwing

+1

Đọc qua tài liệu khi tôi tỉnh táo hơn .. Bản sửa lỗi hiển nhiên, cảm ơn Joe một lần nữa. – sampwing

Các vấn đề liên quan