2011-09-08 17 views
6

So che esistono altri strumenti là fuori per analizzare le istruzioni SQL, ma sto sviluppando il mio per scopi didattici. Mi sto bloccando con la mia grammatica in questo momento .. Se riesci a individuare un errore molto veloce per favore fammi sapere.Utilizzo di PLY per analizzare le istruzioni 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 

Quando si tenta di analizzare un'istruzione come "SELECT a FROM b;" Ricevo un errore di sintassi al token FROM ... Qualsiasi aiuto è molto apprezzato!

(Edit) Codice:

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

Cosa succede se metti uno spazio tra 'b' e'; '? – zerkms

+0

Sempre lo stesso risultato, ho dimenticato di aggiungere che ignora gli spazi ... Lo modificherò. – sampwing

+1

Per quanto ne so, la maggior parte dei database supporterà almeno '[a-zA-Z_0-9]' come tabella nomi. – NullUserException

risposta

4

Credo che il problema è che le espressioni regolari per t_TABLE e t_COLUMN sono anche combinato disposto con la parole riservate (SELECT e FROM). In altre parole, SELECT a FROM b; tokenizza a qualcosa come COLUMN COLUMN COLUMN COLUMN END (o qualche altra tokenizzazione ambigua) e questo non corrisponde a nessuna delle tue produzioni in modo da ottenere un errore di sintassi.

Come un controllo di integrità rapida, modificare tali espressioni regolari per corrispondere esattamente quello che stai digitando come questo:

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

vedrete che la sintassi SELECT a FROM b; passaggi perché le espressioni regolari 'a' e ' b 'non corrisponde alle tue parole riservate.

E, c'è un altro problema che anche le espressioni regolari di TABLE e COLUMN si sovrappongono, quindi il lexer non può tokenizzare senza ambiguità rispetto a quei token.

C'è uno subtle, but relevant section in the PLY documentation a riguardo. Non sei sicuro del modo migliore per spiegarlo, ma il trucco è che il tokenization passa prima, quindi non può davvero usare il contesto dalle tue regole di produzione per sapere se ha incontrato un token TABLE o un token COLUMN. È necessario generalizzare quelli in una specie di token ID e poi eliminare le cose durante l'analisi.

Se avessi ancora un po 'di energia, proverei a lavorare di più sul tuo codice e fornire una soluzione reale nel codice, ma penso che, visto che hai già detto che questo è un esercizio di apprendimento, forse sarai contento con me che punta nella giusta direzione.

+1

Non ho ancora completamente risposto alla tua risposta con il mio codice .. Ma quando hai fatto riferimento alla documentazione, mi ha dato un po 'di intuizione .. Molto apprezzato Joe! – sampwing

+1

Leggere il documento quando ero più sveglio .. La correzione era ovvia, grazie ancora Joe. – sampwing

Problemi correlati