Advertisement
Guest User

aaaaa

a guest
Mar 15th, 2022
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.51 KB | None | 0 0
  1. import string
  2.  
  3.  
  4.  
  5.  
  6. class ProjectorError(Exception):
  7.     def __str__(self):
  8.         return "Unknown error"
  9.  
  10.  
  11. class InvalidSymbolError(ProjectorError):
  12.     def __init__(self, symbol):
  13.         self.symbol = symbol
  14.  
  15.     def __str__(self):
  16.         return f"Invalid symbol '{self.symbol}'"
  17.  
  18.  
  19. class UnmatchedParenthesesError(ProjectorError):
  20.     def __init__(self, opening_index):
  21.         self.opening_index = opening_index
  22.  
  23.     def __str__(self):
  24.         return f"Unmatched parentheses at {self.opening_index}"
  25.  
  26.  
  27. class OperatorAbsentError(ProjectorError):
  28.     def __str__(self):
  29.         return "Expected operator after value"
  30.  
  31.  
  32.  
  33. class ValueToken:
  34.     def __init__(self, value):
  35.         self.value = value
  36.  
  37.     def __str__(self):
  38.         return f"<Token: VAL> {self.value}"
  39.  
  40.  
  41. class OperatorToken:
  42.     def __init__(self, symbol):
  43.         self.symbol = symbol
  44.  
  45.         match symbol:
  46.             case '*': self.precedence = 5
  47.             case '/': self.precedence = 4
  48.             case '+': self.precedence = 3
  49.             case '-': self.precedence = 2
  50.             case '=': self.precedence = 1
  51.             case _: self.precedence = 0
  52.  
  53.     def __str__(self):
  54.         return f"<Token: OP> {self.symbol}"
  55.  
  56.  
  57. class IntegerToken(ValueToken):
  58.     def __init__(self, value):
  59.         super().__init__(value)
  60.  
  61.     def __str__(self):
  62.         return f"<Token: INT> {self.value}"
  63.  
  64.  
  65. class OperatorAddToken(OperatorToken):
  66.     def __init__(self):
  67.         super().__init__('+')
  68.  
  69.  
  70. class OperatorSubToken(OperatorToken):
  71.     def __init__(self):
  72.         super().__init__('-')
  73.  
  74.  
  75. class OperatorMulToken(OperatorToken):
  76.     def __init__(self):
  77.         super().__init__('*')
  78.  
  79.  
  80. class OperatorDivToken(OperatorToken):
  81.     def __init__(self):
  82.         super().__init__('/')
  83.  
  84.  
  85. class OperatorAssignToken(OperatorToken):
  86.     def __init__(self):
  87.         super().__init__('=')
  88.  
  89.  
  90. class TokenGroup:
  91.     def __init__(self, token_list = []):
  92.         self.token_list = token_list
  93.         self.operative, self.nested = get_token_list_attributes(token_list)
  94.  
  95.     def __len__(self):
  96.         return len(self.token_list)
  97.  
  98.     def __str__(self, indent_level=0):
  99.         hash_signature = str(hash(self))
  100.         indent_padding = indent_level * '\t'
  101.  
  102.         group_string = f"{indent_padding}<Token: GRP -- {hash_signature}"
  103.  
  104.         if self.operative: group_string += " (operative)"
  105.         if self.nested: group_string += " (nested)"
  106.  
  107.         for token in self.token_list:
  108.             if isinstance(token, TokenGroup):
  109.                 subgroup_string = token.__str__(indent_level + 1)
  110.                 group_string += f"\n{subgroup_string}"
  111.             else:
  112.                 group_string += f"\n{indent_padding}\t{str(token)}"
  113.  
  114.         group_string += f"\n{indent_padding}{hash_signature} -- >"
  115.  
  116.         return group_string
  117.  
  118.  
  119.  
  120. class ValueExpression:
  121.     def __init__(self, value_token):
  122.         self.value_token = value_token
  123.  
  124.  
  125. class OperationExpression:
  126.     def __init__(self, operator_token, left=None, right=None):
  127.         self.operator_token = operator_token
  128.         self.left = left
  129.         self.right = right
  130.  
  131.  
  132.  
  133.  
  134. def get_next_operator_index(token_group):
  135.     operator_precedence = 0
  136.     operator_index = -1
  137.  
  138.     for index, token in enumerate(token_group.token_list):
  139.         if isinstance(token, OperatorToken) and \
  140.                 token.precedence > operator_precedence:
  141.             operator_index = index
  142.             operator_precedence = token.precedence
  143.  
  144.     return operator_index
  145.  
  146.  
  147. def get_token_list_attributes(token_list):
  148.     operative = False
  149.     nested = False
  150.  
  151.     for token in token_list:
  152.         if isinstance(token, OperatorToken): operative = True
  153.         elif isinstance(token, TokenGroup): nested = True
  154.  
  155.         if operative and nested: break
  156.  
  157.     return operative, nested
  158.  
  159.  
  160. def extract_integer(expression, starting_index):
  161.     number_string = expression[starting_index]
  162.  
  163.     if starting_index < len(expression) - 1:
  164.         for character in expression[starting_index + 1 :]:
  165.             if character not in string.digits: break
  166.  
  167.             number_string += character
  168.  
  169.     return number_string
  170.  
  171.  
  172. def extract_group(expression, opening_index):
  173.     if opening_index == len(expression) - 1:
  174.         raise UnmatchedParenthesesError(opening_index)
  175.  
  176.     closing_index = expression.rfind(')', opening_index + 1)
  177.  
  178.     if closing_index == -1:
  179.         raise UnmatchedParenthesesError(opening_index)
  180.  
  181.     token_list = tokenize(expression[opening_index + 1 : closing_index])
  182.  
  183.     return TokenGroup(token_list), closing_index
  184.  
  185.  
  186.  
  187. def tokenize(expression):
  188.     token_list = []
  189.  
  190.     index = 0
  191.     while index < len(expression):
  192.         if expression[index] == '(':
  193.             token_group, index = extract_group(expression, index)
  194.             token_list.append(token_group)
  195.         elif expression[index] in string.digits:
  196.             number_string = extract_integer(expression, index)
  197.             index += len(number_string) - 1
  198.             token_list.append(IntegerToken(number_string))
  199.         elif expression[index] == '+':
  200.             token_list.append(OperatorAddToken())
  201.         elif expression[index] == '-':
  202.             token_list.append(OperatorSubToken())
  203.         elif expression[index] == '*':
  204.             token_list.append(OperatorMulToken())
  205.         elif expression[index] == '/':
  206.             token_list.append(OperatorDivToken())
  207.         elif expression[index] == '=':
  208.             token_list.append(OperatorAssignToken())
  209.         else:
  210.             raise InvalidSymbolError(expression[index])
  211.  
  212.         index += 1
  213.  
  214.     return token_list
  215.  
  216.  
  217. def parse(token_group):
  218.     execution_tree = None
  219.  
  220.     if not token_group.operative:
  221.         if len(token_group) > 1:
  222.             raise OperatorAbsentError
  223.  
  224.         if isinstance(token_group[0], TokenGroup):
  225.             execution_tree = parse(token_group[0])
  226.         else:
  227.             execution_tree = ValueExpression(token_group[0])
  228.     else:
  229.         operator_index = get_next_operator_index(token_group)
  230.  
  231.         operator = token_group.token_list[operator_index]
  232.  
  233.     return execution_tree
  234.  
  235.  
  236. def evaluate(execution_tree):
  237.     result = 0
  238.  
  239.     return result
  240.  
  241.  
  242. def main():
  243.     try:
  244.         expression = input("ProjectOr expression: ").replace(' ', '')
  245.         token_list = tokenize(expression)
  246.         execution_tree = parse(TokenGroup(token_list))
  247.         result = evaluate(execution_tree)
  248.         print(result)
  249.     except ProjectorError as ex:
  250.         print(ex)
  251.  
  252.  
  253. if __name__ == "__main__":
  254.     main()
  255.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement