diff --git a/relational/parser.py b/relational/parser.py index a5d6d34..1015dbf 100644 --- a/relational/parser.py +++ b/relational/parser.py @@ -150,7 +150,7 @@ class Node: elif isinstance(self, Binary) and self.name == DIVISION: return list(set(self.left.result_format(rels)) - set(self.right.result_format(rels))) elif self.name == PROJECTION: - return [i.strip() for i in self.prop.split(',')] + return self.get_projection_prop() elif self.name == PRODUCT: return self.left.result_format(rels) + self.right.result_format(rels) elif self.name == SELECTION: @@ -231,7 +231,7 @@ class Unary(Node): # Converting parameters if self.name == PROJECTION: - prop = '\"%s\"' % prop.replace(' ', '').replace(',', '\",\"') + prop = repr(self.get_projection_prop()) elif self.name == RENAME: prop = repr(self.get_rename_prop()) else: # Selection @@ -270,8 +270,6 @@ class Unary(Node): self.prop = ','.join(f'{k}{ARROW}{v}' for k, v in renames.items()) - - def parse_tokens(expression: List[Union[list, str]]) -> Node: '''Generates the tree from the tokenized expression If no expression is specified then it will create an empty node''' @@ -281,12 +279,14 @@ def parse_tokens(expression: List[Union[list, str]]) -> Node: while len(expression) == 1 and isinstance(expression[0], list): expression = expression[0] + if len(expression) == 0: + raise ParserException('Failed to parse empty expression') + # The list contains only 1 string. Means it is the name of a relation if len(expression) == 1: - if not rtypes.is_valid_relation_name(expression[0]): raise ParserException( - u"'%s' is not a valid relation name" % expression[0]) + f'{expression[0]!r} is not a valid relation name') return Variable(expression[0]) #FIXME Move validation in the object # Expression from right to left, searching for binary operators @@ -302,28 +302,27 @@ def parse_tokens(expression: List[Union[list, str]]) -> Node: for i in range(len(expression) - 1, -1, -1): if expression[i] in b_operators: # Binary operator - if len(expression[:i]) == 0: raise ParserException( - u"Expected left operand for '%s'" % self.name) + f'Expected left operand for {expression[i]!r}') if len(expression[i + 1:]) == 0: raise ParserException( - u"Expected right operand for '%s'" % self.name) + f'Expected right operand for {expression[i]!r}') return Binary(expression[i], parse_tokens(expression[:i]), parse_tokens(expression[i + 1:])) '''Searches for unary operators, parsing from right to left''' for i in range(len(expression) - 1, -1, -1): if expression[i] in u_operators: # Unary operator if len(expression) <= i + 2: raise ParserException( - u"Expected more tokens in '%s'" % self.name) + f'Expected more tokens in {expression[i]!r}') return Unary( expression[i], prop=expression[1 + i].strip(), child=parse_tokens(expression[2 + i]) ) - raise ParserException('Parse error') #FIXME more details + raise ParserException(f'Parse error on {expression!r}') def _find_matching_parenthesis(expression: str, start=0, openpar='(', closepar=')') -> Optional[int]: