Advertisement
Guest User

Untitled

a guest
May 28th, 2015
368
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.63 KB | None | 0 0
  1. import re
  2. from pyparsing import (Literal, CaselessLiteral, Word, Group, Combine, Optional,
  3.     ZeroOrMore, Forward, nums, alphas, Regex, ParseException)
  4.  
  5. exprStack = []
  6. rasters = dict()
  7.  
  8. def pushFirst(strg, loc, toks):
  9.     exprStack.append(toks[0])
  10.  
  11. def pushUMinus(strg, loc, toks):
  12.     for t in toks:
  13.         if t == '-':
  14.             exprStack.append('unary -')
  15.         else:
  16.             break
  17.  
  18. def rasterPath(rasterName):
  19.     global rasters
  20.     return rasters[rasterName]
  21.  
  22. # Define grammar
  23. bnf = None
  24. def BNF():
  25.     global bnf
  26.     if not bnf:
  27.         point = Literal('.')
  28.         colon = Literal(',')
  29.         e = CaselessLiteral('E')
  30.         pi = CaselessLiteral( "PI" )
  31.         fnumber = Regex(r'[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?')
  32.         ident = Combine('"' + Word(alphas, alphas + nums + '_') + '"')
  33.         func = Word(alphas)
  34.         plus = Literal('+')
  35.         minus = Literal('-')
  36.         mult = Literal('*')
  37.         div = Literal('/')
  38.         mod = Literal('%')
  39.         lpar = Literal('(').suppress()
  40.         rpar = Literal(')').suppress()
  41.         addop = plus | minus
  42.         multop = mult | div | mod
  43.         expop = Literal('^')
  44.  
  45.         expr = Forward()
  46.         atom = ((0, None) * minus + (pi | e | fnumber | ident | func + lpar + expr + rpar | ident).setParseAction(pushFirst) |
  47.                 Group(lpar + expr + rpar)).setParseAction(pushUMinus)
  48.  
  49.         # by defining exponentiation as "atom [ ^ factor ]..." instead of
  50.         # "atom [ ^ atom ]...", we get right-to-left exponents, instead of
  51.         # left-to-righ that is, 2^3^2 = 2^(3^2), not (2^3)^2.
  52.         factor = Forward()
  53.         factor << atom + ZeroOrMore((expop + factor).setParseAction(pushFirst))
  54.  
  55.         term = factor + ZeroOrMore((multop + factor).setParseAction(pushFirst))
  56.         expr << term + ZeroOrMore((addop + term).setParseAction(pushFirst))
  57.         bnf = expr
  58.     return bnf
  59.  
  60. # map operator symbols to corresponding arithmetic operations
  61. opn = {'+': lambda x, y: 'binarymathraster({}, {}, add)'.format(x, y),
  62.        '-': lambda x, y: 'binarymathraster({}, {}, substract)'.format(x, y),
  63.        '*': lambda x, y: 'binarymathraster({}, {}, times)'.format(x, y),
  64.        '/': lambda x, y: 'binarymathraster({}, {}, divide)'.format(x, y),
  65.        '%': lambda x, y: 'binarymathraster({}, {}, mod)'.format(x, y),
  66.        '^': lambda x, y: 'binarymathraster({}, {}, power)'.format(x, y)}
  67.  
  68. fn  = {'sin': lambda x: 'sin({})'.format(x),
  69.        'cos': lambda x: 'cos({})'.format(x),
  70.        'tan': lambda x: 'tan({})'.format(x),
  71.        'asin': lambda x: 'asin({})'.format(x),
  72.        'acos': lambda x: 'acos({})'.format(x),
  73.        'atan': lambda x: 'atan({})'.format(x),
  74.        'log10': lambda x: 'log10({})'.format(x),
  75.        'ln': lambda x: 'ln({})'.format(x),
  76.        'abs': lambda x: 'abs({})'.format(x),
  77.        'sqrt': lambda x: 'sqrt({})'.format(x),
  78.        'ceil': lambda x: 'ceil({})'.format(x),
  79.        'floor': lambda x: 'floor({})'.format(x),
  80.        'sign': lambda x: 'sign({})'.format(x),
  81.        'sinh': lambda x: 'sinh({})'.format(x)}
  82.  
  83. def evaluateStack(s):
  84.     op = s.pop()
  85.     if op == 'unary -':
  86.         return -evaluateStack(s)
  87.     if op in '+-*/^':
  88.         op2 = evaluateStack(s)
  89.         op1 = evaluateStack(s)
  90.         return opn[op](op1, op2)
  91.     elif op == 'PI':
  92.         return math.pi # 3.1415926535
  93.     elif op == 'E':
  94.         return math.e  # 2.718281828
  95.     elif op in fn:
  96.         return fn[op](evaluateStack(s))
  97.     elif re.search('\"(.+?)\"', op):
  98.         return rasterPath(op.strip('"'))
  99.     elif op[0].isalpha():
  100.         raise Exception('invalid identifier "%s"' % op)
  101.     else:
  102.         return float(op)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement