from SQLLexer import * import ply.yacc as yacc class SQLParser(object): def __init__(self): self.sqllex = SQLLexer() self.sqllex.build() #lexer = lex.lex(object=sqllex) self.tokens = self.sqllex.tokens self.parser = yacc.yacc(module=self) def p_select(self, p): 'select : SELECT columns FROM tables WHERE where_expression SEMI' p[0] = ('select-statement', p[2], p[4], p[6]) def p_columns_wild(self, p): '''columns : WILD | id_list''' p[0] = ('columns-list', p[1]) def p_id_list(self, p): '''id_list ''' # Use the following expressions to construct the AST as guide if len(p) > 2: p[0] = p[1] + ',' + p[3] else: p[0] = p[1] def p_tables(self, p): 'tables : id_list' p[0] = ('table-list', p[1]) def p_where_expression(self, p): '''where_expression : expression''' p[0] = ('where-expression', p[1]) def p_expression(self, p): '''expression : simple_expression AND expression | simple_expression OR expression | simple_expression''' if len(p) < 3: p[0] = p[1] else: p[0] = ('logical-expression', p[2], p[1], p[3]) def p_simple_expression(self, p): '''simple_expression : factor EQ factor | factor LT factor | factor''' if len(p) < 3: p[0] = p[1] else: p[0] = ('comparison-expression', p[2], p[1], p[3]) def p_factor_id(self, p): '''factor : ''' p[0] = ('ID', p[1]) def p_factor_lit(self, p): '''factor : ''' # Note that we do not add the actual literal value because # for the purpose of this module the input literals and numbers # can change. p[0] = ('LITERAL') def p_factor_num(self, p): '''factor : ''' # Note that we do not add the actual number value because # for the purpose of this module the input literals and numbers # can change. p[0] = ('NUMBER') def p_factor_expression(self, p): '''factor : ''' p[0] = ('group-expression', p[2]) def p_error(self, p): print("Syntax error in input!") raise def parse(self, text): return self.parser.parse(text, lexer=self.sqllex) def print_ast(self, ast): Q = ast while len(Q) > 0: NQ = [] for node in Q: if type(node) == tuple: print node[0], for i in range(1, len(node)): NQ.append(node[i]) else: print node, Q = NQ print if __name__ == '__main__': parser = SQLParser() while True: try: s = raw_input("sql> ") except EOFError: break if not s: continue try: ast = parser.parse(s) parser.print_ast(ast) except: print "Syntax error"