Package pyraf :: Module cltoken
[hide private]
[frames] | no frames]

Source Code for Module pyraf.cltoken

  1  """cltoken.py: Token definition for CL parser 
  2   
  3  $Id: cltoken.py 1463 2011-06-24 22:58:30Z stsci_embray $ 
  4  """ 
  5  from __future__ import division # confidence high 
  6   
  7  #  Copyright (c) 1998-1999 John Aycock 
  8  # 
  9  #  Permission is hereby granted, free of charge, to any person obtaining 
 10  #  a copy of this software and associated documentation files (the 
 11  #  "Software"), to deal in the Software without restriction, including 
 12  #  without limitation the rights to use, copy, modify, merge, publish, 
 13  #  distribute, sublicense, and/or sell copies of the Software, and to 
 14  #  permit persons to whom the Software is furnished to do so, subject to 
 15  #  the following conditions: 
 16  # 
 17  #  The above copyright notice and this permission notice shall be 
 18  #  included in all copies or substantial portions of the Software. 
 19  # 
 20  #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 21  #  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 22  #  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 23  #  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 24  #  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 25  #  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 26  #  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 27   
 28  # 
 29  #       Token class for IRAF CL parsing 
 30  # 
 31   
 32  import string 
 33  from stsci.tools.irafglobals import INDEF 
 34   
 35  verbose = 0 
 36   
37 -class Token:
38 - def __init__(self, type, attr=None, lineno=None):
39 self.type = type 40 self.attr = attr 41 self.lineno = lineno
42 43 # 44 # Not all these may be needed: 45 # 46 # __cmp__ required for GenericParser, required for 47 # GenericASTMatcher only if your ASTs are 48 # heterogeneous (i.e., AST nodes and tokens) 49 # __repr__ recommended for nice error messages in GenericParser 50 # __getitem__ only if you have heterogeneous ASTs 51 #
52 - def __cmp__(self, o):
53 # raise RuntimeError("Remove comparisons of tokens") 54 return cmp(self.type, o)
55
56 - def __hash__(self):
57 return hash(self.type)
58
59 - def verboseRepr(self):
60 if self.attr: 61 return self.type + '(' + self.attr + ')' 62 else: 63 return self.type
64
65 - def __repr__(self):
66 global verbose 67 if verbose: 68 return self.verboseRepr() 69 else: 70 if self.type in ["STRING", "QSTRING"]: 71 # add quotes to strings 72 # but replace double escapes with single escapes 73 return repr(self.attr).replace('\\\\','\\') 74 else: 75 rv = self.attr 76 if rv is None: rv = self.type 77 return rv
78
79 - def __getitem__(self, i):
80 raise IndexError
81
82 - def __len__(self):
83 return 0
84
85 - def get(self):
86 """Return native representation of this token""" 87 if self.type == "INTEGER": 88 return self.__int__() 89 elif self.type == "FLOAT": 90 return self.__float__() 91 elif self.type in ["STRING","QSTRING"]: 92 return self.attr 93 elif self.type == "BOOL": 94 return self.bool()
95 96 # special conversions 97
98 - def __str__(self):
99 rv = self.attr 100 if rv is None: rv = self.type 101 return rv
102
103 - def __int__(self):
104 if self.type == "INTEGER": 105 return _str2int(self.attr) 106 elif self.type == "INDEF": 107 return int(INDEF) 108 elif self.type == "FLOAT": 109 # allow floats as values if they are exact integers 110 f = self.__float__() 111 i = int(f) 112 if float(i) == f: return i 113 elif self.type in ["STRING", "QSTRING"]: 114 try: 115 if self.attr == "": 116 return int(INDEF) 117 elif self.attr[:1] == ')': 118 # indirection to another parameter 119 return self.attr 120 else: 121 return _str2int(self.attr) 122 except Exception, e: 123 print 'Exception', str(e) 124 pass 125 raise ValueError("Cannot convert " + 126 self.verboseRepr() + " to int")
127
128 - def __float__(self):
129 if self.type == "FLOAT": 130 # convert d exponents to e for Python 131 value = self.attr 132 i = value.find('d') 133 if i>=0: 134 value = value[:i] + 'e' + value[i+1:] 135 else: 136 i = value.find('D') 137 if i>=0: 138 value = value[:i] + 'E' + value[i+1:] 139 return float(value) 140 elif self.type == "INTEGER": 141 # convert to int first because of octal, hex formats 142 return float(_str2int(self.attr)) 143 elif self.type == "SEXAGESIMAL": 144 # convert d:m:s values directly to float 145 flist = self.attr.split(':') 146 flist.reverse() 147 value = float(flist[0]) 148 for v in flist[1:]: 149 value = float(v) + value/60.0 150 return value 151 elif self.type == "INDEF": 152 return float(INDEF) 153 elif self.type in ["STRING", "QSTRING"]: 154 try: 155 if self.attr == "": 156 return float(INDEF) 157 elif self.attr[:1] == ')': 158 # indirection to another parameter 159 return self.attr 160 else: 161 return float(self.attr) 162 except (ValueError, TypeError): 163 pass 164 raise ValueError("Cannot convert " + 165 self.verboseRepr() + " to float")
166
167 - def bool(self):
168 #XXX convert INTEGER to bool too? 169 if self.type == "BOOL": 170 return self.attr 171 elif self.type == "INDEF": 172 return INDEF 173 elif self.type in ["STRING", "QSTRING"]: 174 keyword = self.attr.lower() 175 if keyword in ["yes", "y"]: 176 return "yes" 177 elif keyword in ["no", "n"]: 178 return "no" 179 elif self.attr[:1] == ')': 180 # indirection to another parameter 181 return self.attr 182 elif keyword == "": 183 return INDEF 184 raise ValueError("Cannot convert " + 185 self.verboseRepr() + " to bool")
186
187 -def _str2int(value):
188 # convert integer string to python int 189 # handles IRAF octal, hex values 190 last = value[-1].lower() 191 if last == 'b': 192 # octal 193 return eval('0'+value[:-1]) 194 elif last == 'x': 195 # hexadecimal 196 return eval('0x'+value[:-1]) 197 # remove leading zeros on decimal values 198 i=0 199 for digit in value: 200 if digit != '0': break 201 i = i+1 202 else: 203 # all zeros 204 return 0 205 return int(value[i:])
206