2011-09-08 15 views
6

मैं जानता हूँ कि वहाँ अन्य उपकरणों SQL कथन पार्स करने के लिए कर रहे हैं, लेकिन मैं शैक्षिक उद्देश्यों के लिए अपने खुद के बाहर चल रहा पार्स करने के लिए प्लाई का उपयोग करना। मैं अभी अपने व्याकरण से फंस रहा हूं .. अगर आप वास्तव में एक त्रुटि खोज सकते हैं तो कृपया मुझे बताएं।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 

जब मैं 'से चुनें एक बी;' जैसे किसी बयान को पार्स करने का प्रयास करता हूं। मुझे 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

यदि आप 'बी' और'; 'के बीच कोई स्थान डालते हैं तो क्या होगा? – zerkms

+0

फिर भी एक ही परिणाम है, मैं जोड़ने कि यह रिक्त स्थान पर ध्यान नहीं देता ... मुझे लगता है कि संपादित करेंगे में भूल गया। – sampwing

+1

जहाँ तक मुझे पता है, सबसे डेटाबेस में कम से कम '[a-zA-Z_0-9]' तालिका के रूप में समर्थन करेंगे नाम। – NullUserException

उत्तर

4

मुझे लगता है कि तुम्हारी समस्या है कि t_TABLE और t_COLUMN के लिए अपने रेगुलर एक्सप्रेशन भी अपने आरक्षित शब्द (का चयन करें और से) मिलान कर रहे हैं। दूसरे शब्दों में, COLUMN COLUMN COLUMN COLUMN END की तरह कुछ (या कुछ अन्य अस्पष्ट tokenization) को SELECT a FROM b; tokenizes और यह आपकी प्रस्तुतियों में से किसी से मेल नहीं खाता है ताकि आप एक सिंटैक्स त्रुटि मिल में।

एक त्वरित मानसिक स्वास्थ्य की जांच के रूप में, मैच के लिए वास्तव में क्या आप इस तरह लिख रहे हैं उन नियमित अभिव्यक्ति बदलने के लिए:

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

आपको लगता है कि वाक्य रचना SELECT a FROM b; गुजरता दिखाई देगा क्योंकि नियमित अभिव्यक्ति 'एक' और ' बी 'अपने आरक्षित शब्दों से मेल नहीं खाते।

और, वहाँ एक और समस्या यह है कि टेबल और कॉलम ओवरलैप के लिए नियमित अभिव्यक्ति के रूप में अच्छी तरह से है, तो या तो lexer उन टोकन के संबंध में अस्पष्टता के बिना tokenize नहीं कर सकते।

इस संबंध में एक subtle, but relevant section in the PLY documentation है। यह सुनिश्चित करने का सबसे अच्छा तरीका नहीं है, लेकिन चाल यह है कि टोकननाइजेशन पास पहले होता है, इसलिए यह वास्तव में आपके उत्पादन नियमों से संदर्भ का उपयोग नहीं कर सकता है यह जानने के लिए कि यह एक टैबलेट टोकन या COLUMN टोकन में आया है या नहीं। आपको किसी प्रकार के ID टोकन में सामान्यीकृत करने की आवश्यकता है और फिर पार्स के दौरान चीजों को खरपतवार करना है।

अगर मैं कुछ और अधिक ऊर्जा मैं कुछ और अधिक अपने कोड के माध्यम से काम करते हैं और कोड में एक वास्तविक समाधान प्रदान करने की कोशिश करता हूँ था, लेकिन मुझे लगता है कि जब से तुम पहले से ही व्यक्त की है कि यह एक सीखने व्यायाम है कि शायद आप सामग्री हो जाएगा मेरे साथ सही दिशा में इशारा करते हुए।

+1

मैं अभी तक अपने कोड के साथ आपकी प्रतिक्रिया के माध्यम से नहीं चल रहा था .. लेकिन जब आपने प्रलेखन का संदर्भ दिया, तो उसने मुझे कुछ अंतर्दृष्टि दी .. बहुत सराहना की जो! – sampwing

+1

जब मैं अधिक जाग रहा था दस्तावेज़ के माध्यम से पढ़ें .. फिक्स स्पष्ट था, धन्यवाद फिर से जो। – sampwing