2011-09-08 8 views
6

SQL文を解析するための他のツールがあることは知っていますが、私は教育目的で自分自身を展開しています。私はすぐに私の文法に立ち往生しています。あなたが本当に間違いを見つけられたら、私に知らせてください。PLYを使用して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 

「SELECT a FROM b;」のような文を解析しようとすると、私はFROMトークンで構文エラーが発生しました...どんな助けもありがとうございます!

(編集)コード:

#!/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

'b'と'; 'の間にスペースを入れるとどうなりますか? – zerkms

+0

まだ同じ結果ですが、スペースを無視するように追加することを忘れました...それを編集します。 – sampwing

+1

私の知る限り、ほとんどのデータベースは少なくとも[a-zA-Z_0-9] 'をテーブルとしてサポートします名前。 – NullUserException

答えて

4

私はあなたの問題はt_TABLEt_COLUMNのためのあなたの正規表現は、あなたの予約語(SELECTとFROM)と一致していることだと思います。つまりはCOLUMN COLUMN COLUMN COLUMN END(またはその他のあいまいトークン化)にトークン化されますが、これはプロダクションと一致しないため、構文エラーが発生します。迅速な健全性チェックとして

、あなたがこのようで入力している正確に何を一致させるために、これらの正規表現を変更します。

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

あなたはその構文SELECT a FROM b;パスが表示されます正規表現「A」理由と ' b 'は予約語と一致しません。

また、TABLEとCOLUMNの正規表現も同様に重複しているため、レクサーはこれらのトークンに対してあいまいさもなくトークン化できないという別の問題があります。

これについてはsubtle, but relevant section in the PLY documentationがあります。これを説明する最善の方法はわかりませんが、トークン化のパスが最初に発生するので、実際には生産ルールのコンテキストを使用してTABLEトークンまたはCOLUMNトークンに出会ったかどうかを知ることができません。それらをある種のIDトークンに一般化して、解析中に物事を取り除く必要があります。

もし私がもう少しエネルギーを持っていれば、あなたのコードをもう少し実践し、コードで実際のソリューションを提供しようとしますが、これはおそらくあなたのコンテンツ私は正しい方向を指しています。

+1

あなたの回答は私のコードではまだ完全には歩いていませんでした。しかし、ドキュメンテーションを参照すると、それは私にいくつかの洞察力を与えました。 – sampwing

+1

私がもっと目を覚ましたときに、この文書を読んでください。 – sampwing

関連する問題