# coding=UTF-8 # Relational # Copyright (C) 2008 Salvo "LtWorf" Tomaselli # # Relation is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # author Salvo "LtWorf" Tomaselli '''This module optimizes relational expressions into ones that require less time to be executed''' RELATION=0 UNARY=1 BINARY=2 class node (object): '''This class is a node of a relational expression. Leaves are relations and internal nodes are operations.''' def __init__(self,expression): expression=expression.strip() print "Parsing: ",expression '''expression must be a valid relational algrbra expression that would be accepted by the parser and must be utf16''' self.kind=0 self.name="a" self.prop="" '''*-ᑌᑎᐅᐊᐅLEFTᐊᐅRIGHTᐊᐅFULLᐊπσρ''' binary=(u"*",u"-",u"ᑌ",u"ᑎ") unary=(u"π",u"σ",u"ρ") '''(a ᑌ (a ᑌ b ᑌ c ᑌ d)) ᑎ c - σ i==3(πa,b(aᑌ b ᑎ c))''' level=0 #Current parentesis level start=-1 #Start of the parentesis end=-1 #End of the parentesis. tokens=list(expression) #Splitted expression r=range(len(tokens)) r.reverse() lev_non_zero_chars=0 #Number of chars inside parentesis for i in r: #Parses expression from end to begin, to preserve operation's order if tokens[i]==u"(": if level==0: start=i print start level+=1 elif tokens[i]==u")": level-=1 if level==0: end=i print end if level!=0: lev_non_zero_chars+=1 if i==0 and level==0 and tokens[i] in unary: #Unary operator found, must grab its parameters and its child relation they child="" for q in tokens[start+1:end]: child+=q self.name= tokens[i] print "-----",tokens[i] print "---",start,end,lev_non_zero_chars print child #print prop #self.child=node(child) if level==0 and tokens[i] in binary: #Binary operator found, everything on left will go in the left subree and everhthing on the right will go in the right subtree self.kind=BINARY left="" right="" if start==end==-1:#No parentesis before end=i for q in tokens[start+1:end]: left+=q self.name= tokens[i] for q in tokens[i+1:]: right+=q print "self: ",tokens[i] print "left: ",left print "right:" ,right self.left=node(left) self.right=node(right) return if lev_non_zero_chars!=0 and lev_non_zero_chars+1==len(expression):#Expression is entirely contained in parentesis, removing them n=node(expression[1:-1]) self.name=n.name self.kind=n.kind if n.kind==UNARY: self.child=n.child elif n.kind==BINARY: self.left=n.left self.right=n.right self.prop=n.prop return self.kind=RELATION self.name=expression def __str__(self): if (self.kind==RELATION): return self.name elif (self.kind==UNARY): return self.name + " "+ self.prop+ " (" + self.child +")" elif (self.kind==BINARY): if self.left.kind==RELATION: left=self.left.__str__() else: left=u"("+self.left.__str__()+u")" if self.right.kind==RELATION: right=self.right.__str__() else: right=u"("+self.right.__str__()+u")" return (left+ self.name +right) if __name__=="__main__": #n=node(u"((a ᑌ b) - c ᑌ d) - b") #n=node(u"((((((((((((2)))))))))))) - (3 * 5) - 2") n=node(u"π a,b (d-a*b)") print n.__str__()