SHARE
TWEET

CyberZX

a guest Nov 5th, 2007 80 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #! /usr/bin/python
  2. import  re
  3. import  sys
  4.        
  5. class ParseError:
  6.     pass
  7.        
  8. class UnknownToken(ParseError):
  9.     def __init__(self, where):
  10.         self.where = where
  11.        
  12.     def show(self):
  13.         print "Unknown token \"", self.where, "\""
  14.        
  15. class SyntaxError(ParseError):
  16.     def __init__(self, msg, where):
  17.         self.msg   = msg
  18.         self.where = where
  19.        
  20.     def show(self):
  21.         print self.msg
  22.        
  23. class Token:
  24.     def __init__(self, Comma = False,
  25.                        Plus = False,
  26.                        Minus= False,
  27.                        Mul= False,
  28.                        Div= False,
  29.                        Circum = False,
  30.                        LParen= False,
  31.                        RParen= False,
  32.                        EOL= False,
  33.                        Number = False,
  34.                        Value = 0.0):
  35.         self.Comma = Comma
  36.         self.Plus  = Plus
  37.         self.Minus = Minus
  38.         self.Mul   = Mul
  39.         self.Div   = Div
  40.         self.LParen= LParen
  41.         self.RParen= RParen
  42.         self.EOL   = EOL
  43.         self.Number= Number
  44.         self.Value = Value
  45.         self.Circum= Circum
  46.                                                      
  47.                        
  48. class Scanner:    
  49.     def __init__(self, string):
  50.         self.string    = filter(lambda x: not x.isspace(), string)
  51.         self.next_sym  = 0
  52.         self.end       = len(self.string)
  53.         self.float_re  = re.compile("^(?P<float>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?).*")
  54.                                
  55.     def getNextToken(self):
  56.         if self.next_sym == self.end:
  57.             return  Token(EOL = True)
  58.        
  59.         c = self.string[self.next_sym]
  60.         self.next_sym += 1
  61.         if c == ',':
  62.             return  Token(Comma = True)
  63.         elif c == '+':            
  64.             return  Token(Plus = True)
  65.         elif c == '-':
  66.             return  Token(Minus = True)
  67.         elif c == '*':
  68.             return  Token(Mul = True)
  69.         elif c == '/':            
  70.             return  Token(Div = True)
  71.         elif c == '^':
  72.             return  Token(Circum = True)
  73.         elif c == '(':
  74.             return  Token(LParen = True)
  75.         elif c == ')':
  76.             return  Token(RParen = True)            
  77.         self.next_sym -= 1
  78.                
  79.         try:
  80.             a = self.float_re.match(self.string[self.next_sym:])
  81.             if a != None:
  82.                 self.next_sym += a.end('float')
  83.                 return  Token(Number = True, Value = float(a.group('float')))
  84.         except  IndexError:
  85.             pass
  86.        
  87.         raise  UnknownToken(self.string[self.next_sym:])
  88.        
  89.     def __iter__(self):
  90.         return self        
  91.    
  92.     def next(self):
  93.         if self.next_sym == self.end:
  94.             raise StopIteration      
  95.         return  self.getNextToken()
  96.        
  97. class Lexer:
  98.     def __init__(self, scanner):
  99.         self.tokens = [x for x in scanner]        
  100.         self.lookahead = 0
  101.          
  102.     def readFirstToken(self):
  103.         return  self.tokens[self.lookahead]
  104.    
  105.     def popToken(self):
  106.         if self.lookahead < len(self.tokens) - 1:
  107.            self.lookahead += 1
  108.            
  109.     def pushToken(self):
  110.         if self.lookahead > 0:
  111.             self.lookahead -= 1
  112.            
  113.            
  114. def expr(lexer):
  115.     t = term(lexer)
  116.     if not t:
  117.         return  False
  118.    
  119.     f = rest_e(lexer)
  120.     return  f(t)
  121.  
  122. def rest_e(lexer):
  123.     tok = lexer.readFirstToken()
  124.     if tok.Minus:
  125.         lexer.popToken()
  126.         t = term(lexer)
  127.         if not t:
  128.             raise   SyntaxError("Bad expression syntax", lexer)
  129.         return  lambda x: rest_e(lexer)(x - t)
  130.     elif tok.Plus:
  131.         lexer.popToken()
  132.         t = term(lexer)    
  133.         if not t:
  134.             raise   SyntaxError("Bad expression syntax", lexer)
  135.         return  lambda x: rest_e(lexer)(x + t)
  136.     else:
  137.         return  lambda x: x
  138.  
  139. def term(lexer):
  140.     t = factor(lexer)
  141.     if not t:
  142.         return  False
  143.    
  144.     f = rest_t(lexer)
  145.     return  f(t)
  146.  
  147. def rest_t(lexer):
  148.     tok = lexer.readFirstToken()
  149.     if tok.Mul:
  150.         lexer.popToken()
  151.         f = factor(lexer)
  152.         if not f:
  153.             raise   SyntaxError("Bad expression syntax", lexer)
  154.         return  lambda x: rest_t(lexer)(x * f)
  155.     elif tok.Div:
  156.         lexer.popToken()
  157.         f = factor(lexer)
  158.         if not f:
  159.             raise   SyntaxError("Bad expression syntax", lexer)
  160.         return  lambda x: rest_t(lexer)(x / f)
  161.     elif tok.Circum:
  162.         lexer.popToken()
  163.         f = factor(lexer)
  164.         if not f:
  165.             raise   SyntaxError("Bad expression syntax", lexer)
  166.         return  lambda x: rest_t(lexer)(x ** f)
  167.     else:
  168.         return  lambda x: x
  169.  
  170. def sign_factor(lexer):
  171.     tok = lexer.readFirstToken()
  172.     if tok.Minus:
  173.         lexer.popToken()
  174.         return  factor(lexer)*-1
  175.     return  False
  176.    
  177.        
  178. def factor(lexer):
  179.     r = sign_factor(lexer)
  180.     if r == False:
  181.         r = parentheses(lexer)
  182.         if  r == False:
  183.             return  number(lexer)
  184.         else:
  185.             return  r            
  186.     else:
  187.         return  r
  188.  
  189. def parentheses(lexer):
  190.     if not lexer.readFirstToken().LParen:
  191.         return  False
  192.    
  193.     lexer.popToken()
  194.     expr_ret = expr(lexer)
  195.     if not expr_ret:
  196.         lexer.pushToken()
  197.         return  False
  198.    
  199.     if not lexer.readFirstToken().RParen:
  200.         raise SyntaxError("""forgot ")"? """, lexer)
  201.    
  202.     lexer.popToken()
  203.     return  expr_ret
  204.  
  205. def number(lexer):
  206.     tok = lexer.readFirstToken()
  207.     if tok.Number:
  208.         lexer.popToken()
  209.         return  tok.Value
  210.     return  False
  211.  
  212. def calc(str):
  213.     return  expr(Lexer(Scanner(str)))
  214.    
  215. if len(sys.argv) < 2:
  216.     print "usage: calc <expression>"
  217. else:
  218.     try:
  219.         print   calc(sys.argv[1])
  220.     except ParseError, error:
  221.         error.show()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top