jewalky

parser.py

Mar 1st, 2016
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.95 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2.  
  3. from tokenizer import ZTokenizer
  4.  
  5. class ZParserError(Exception):
  6.     pass
  7.  
  8. # X.Y.Z() = call. X.Y.Z should be callable type.
  9. # call(..., ..., ..., ...) = call expression. contains call name and list of subexpressions (parameters)
  10. # X ... Y = regular expession between X and Y
  11.  
  12. # 4 + 8 * 6 * 2 + 4
  13. # push 2
  14. # push 6
  15. # mul
  16. # push 8
  17. # mul
  18. # push 4
  19. # add
  20. # push 4
  21. # add
  22. # top of stack should contain result of the expression
  23.  
  24. # then:
  25. # (4 + 8) * 6 * 2 + 4
  26. # push 8
  27. # push 4
  28. # add
  29. # push 6
  30. # mul
  31. # push 2
  32. # mul
  33. # push 4
  34. # add
  35.  
  36.  
  37. class ZExpression:
  38.     def __init__(self, t, v):
  39.         self.type = t
  40.         self.value = v
  41.        
  42.     def __repr__(self):
  43.         return repr({'type': self.type, 'value': self.value})
  44.  
  45.    
  46. class ZParser:
  47.     def __init__(self, fn):
  48.         with open(fn, 'r') as f:
  49.             text = f.read()
  50.             tok = ZTokenizer(text)
  51.             self.parse(tok)
  52.        
  53.     def parse_expression_part(self, tok, depth, args):
  54.         tok.get_whitespace()
  55.         paren = tok.get_other('(')
  56.         if paren is not None:
  57.             return ZExpression('expression', self.parse_expression(tok, depth+1, False))
  58.         id = tok.get_identifier()
  59.         if id is not None:
  60.             if id == 'true' or id == 'false':
  61.                 return ZExpression('bool', id=='true')
  62.             # otherwise store an identifier
  63.             # identifier can be either dot-separated or simple
  64.             idc = id
  65.             tok.get_whitespace()
  66.             dot = tok.get_other('.')
  67.             while dot is not None:
  68.                 tok.get_whitespace()
  69.                 id = tok.require_identifier()
  70.                 idc += '.'+id
  71.                 tok.get_whitespace()
  72.                 dot = tok.get_other('.')
  73.             return ZExpression('id', idc)
  74.         num = tok.require_integer()
  75.         return ZExpression('int', num)
  76.            
  77.     def parse_expression(self, tok, depth=0, args=False):
  78.         current_level = []
  79.         current_level.append(self.parse_expression_part(tok, depth, args))
  80.         while not tok.is_eof():
  81.             tok.get_whitespace()
  82.             op = tok.get_other('<>=-+/*;,()')
  83.             if op == '=' or op == '<' or op == '>':
  84.                 op2 = tok.get_other('=')
  85.                 if op2 is not None:
  86.                     op += '='
  87.             if op is None or op == ';' or op == ',' or op == ')':
  88.                 if op is None:
  89.                     raise ZParserError('Invalid operator at line %d'%tok.line)
  90.                 elif op == ')' and (depth < 0 or (depth == 0 and not args)):
  91.                     raise ZParserError('Invalid expression at line %d'%tok.line)
  92.                 elif op == ',' and not args:
  93.                     raise ZParserError('Invalid expression at line %d'%tok.line)
  94.                 break
  95.             rvalue = self.parse_expression_part(tok, depth, args)
  96.             if op == '==' or op == '>' or op == '<' or op == '>=' or op == '<=':
  97.                 # whole current level goes into first subexpression.
  98.                 opa = {'==': 'eq', '>': 'gt', '<': 'lt', '>=': 'ge', '<=': 'le'}
  99.                 current_level = [ZExpression('operator', ['cmp_%s'%opa[op], ZExpression('expression', current_level), rvalue])]
  100.             elif op == '*' or op == '/':
  101.                 #current_level[:] = current_level[:-1]
  102.                 #current_level.append()
  103.                 if current_level[-1].type == 'operator':
  104.                     current_level[-1].value[2] = ZExpression('expression', [ZExpression('operator', ['mul' if op == '*' else 'div', current_level[-1].value[2], rvalue])])
  105.                 else:
  106.                     current_level[-1] = ZExpression('expression', [ZExpression('operator', ['mul' if op == '*' else 'div', current_level[-1], rvalue])])
  107.             elif op == '+' or op == '-':
  108.                 #tok.position = posa
  109.                 lvalue = current_level[-1]
  110.                 current_level[:] = current_level[:-1]
  111.                 current_level.append(ZExpression('operator', ['add' if op == '+' else 'sub', lvalue, rvalue]))
  112.             else:
  113.                 raise ZParserError('Invalid operator at line %d'%tok.line)
  114.         return current_level
  115.  
  116.     def compile_expression(self, exprl, depth=0):
  117.         expra = []
  118.         for expr in exprl:
  119.             if expr.type == 'expression':
  120.                 expra += self.compile_expression(expr.value, depth+1)
  121.             elif expr.type == 'operator':
  122.                 #expra.append(expr)
  123.                 expra += self.compile_expression([expr.value[1]]) # push ...
  124.                 expra += self.compile_expression([expr.value[2]]) # push ...
  125.                 expra.append([expr.value[0]])
  126.             elif expr.type == 'int':
  127.                 expra.append(['push', expr.value])
  128.             elif expr.type == 'bool':
  129.                 expra.append(['push', 1 if expr.value else 0])
  130.         return expra
  131.            
  132.     def parse(self, tok):
  133.         actions = self.compile_expression(self.parse_expression(tok))
  134.         self.code = actions
  135.        
  136.  
  137. par = ZParser('test.zs')
  138. for action in par.code:
  139.     actionstr = []
  140.     for actionany in action:
  141.         actionstr.append(str(actionany))
  142.     print('%s' % (' '.join(actionstr)))
  143.  
  144.    
  145. class ZExecutor:
  146.     def __init__(self):
  147.         self.stack = []
  148.        
  149.     def stack_pop(self):
  150.         val = self.stack[-1]
  151.         self.stack[:] = self.stack[:-1]
  152.         return val
  153.        
  154.     def op_push(self, what):
  155.         self.stack.append(what)
  156.        
  157.     def op_mul(self):
  158.         val2 = self.stack_pop()
  159.         val1 = self.stack_pop()
  160.         self.stack.append(val1 * val2)
  161.        
  162.     def op_div(self):
  163.         val2 = self.stack_pop()
  164.         val1 = self.stack_pop()
  165.         self.stack.append(val1 / val2)
  166.        
  167.     def op_add(self):
  168.         val2 = self.stack_pop()
  169.         val1 = self.stack_pop()
  170.         self.stack.append(val1 + val2)
  171.        
  172.     def op_sub(self):
  173.         val2 = self.stack_pop()
  174.         val1 = self.stack_pop()
  175.         self.stack.append(val1 - val2)
  176.        
  177.     def op_cmp_gt(self):
  178.         val2 = self.stack_pop()
  179.         val1 = self.stack_pop()
  180.         self.stack.append(1 if val1 > val2 else 0)
  181.        
  182.     def op_cmp_lt(self):
  183.         val2 = self.stack_pop()
  184.         val1 = self.stack_pop()
  185.         self.stack.append(1 if val1 < val2 else 0)
  186.        
  187.     def op_cmp_ge(self):
  188.         val2 = self.stack_pop()
  189.         val1 = self.stack_pop()
  190.         self.stack.append(1 if val1 >= val2 else 0)
  191.        
  192.     def op_cmp_le(self):
  193.         val2 = self.stack_pop()
  194.         val1 = self.stack_pop()
  195.         self.stack.append(1 if val1 <= val2 else 0)
  196.        
  197.     def op_cmp_eq(self):
  198.         val2 = self.stack_pop()
  199.         val1 = self.stack_pop()
  200.         self.stack.append(1 if val1 == val2 else 0)
  201.  
  202.  
  203. executor = ZExecutor()        
  204. for action in par.code:
  205.     met = getattr(executor, 'op_%s'%action[0])
  206.     met(*action[1:])
  207. result = executor.stack_pop()
  208. print('\nresult: %d'%result)
Add Comment
Please, Sign In to add comment