Merge pull request #23 from ltworf/improve_parser

Improve parser
This commit is contained in:
Salvo 'LtWorf' Tomaselli 2020-06-18 17:16:53 +02:00 committed by GitHub
commit 3b1e90b30e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

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