1*9f22d7c2SAndrew Rist# ************************************************************* 2*9f22d7c2SAndrew Rist# 3*9f22d7c2SAndrew Rist# Licensed to the Apache Software Foundation (ASF) under one 4*9f22d7c2SAndrew Rist# or more contributor license agreements. See the NOTICE file 5*9f22d7c2SAndrew Rist# distributed with this work for additional information 6*9f22d7c2SAndrew Rist# regarding copyright ownership. The ASF licenses this file 7*9f22d7c2SAndrew Rist# to you under the Apache License, Version 2.0 (the 8*9f22d7c2SAndrew Rist# "License"); you may not use this file except in compliance 9*9f22d7c2SAndrew Rist# with the License. You may obtain a copy of the License at 10*9f22d7c2SAndrew Rist# 11*9f22d7c2SAndrew Rist# http://www.apache.org/licenses/LICENSE-2.0 12*9f22d7c2SAndrew Rist# 13*9f22d7c2SAndrew Rist# Unless required by applicable law or agreed to in writing, 14*9f22d7c2SAndrew Rist# software distributed under the License is distributed on an 15*9f22d7c2SAndrew Rist# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*9f22d7c2SAndrew Rist# KIND, either express or implied. See the License for the 17*9f22d7c2SAndrew Rist# specific language governing permissions and limitations 18*9f22d7c2SAndrew Rist# under the License. 19*9f22d7c2SAndrew Rist# 20*9f22d7c2SAndrew Rist# ************************************************************* 21*9f22d7c2SAndrew Rist 22cdf0e10cSrcweirimport sys, os.path 23cdf0e10cSrcweirfrom globals import * 24cdf0e10cSrcweirimport macroparser 25cdf0e10cSrcweir 26cdf0e10cSrcweirclass EOF(Exception): 27cdf0e10cSrcweir def __init__ (self): 28cdf0e10cSrcweir pass 29cdf0e10cSrcweir 30cdf0e10cSrcweir def str (self): 31cdf0e10cSrcweir return "end of file" 32cdf0e10cSrcweir 33cdf0e10cSrcweirclass BOF(Exception): 34cdf0e10cSrcweir def __init__ (self): 35cdf0e10cSrcweir pass 36cdf0e10cSrcweir 37cdf0e10cSrcweir def str (self): 38cdf0e10cSrcweir return "beginning of file" 39cdf0e10cSrcweir 40cdf0e10cSrcweir 41cdf0e10cSrcweirdef removeHeaderQuotes (orig): 42cdf0e10cSrcweir if len(orig) <= 2: 43cdf0e10cSrcweir return orig 44cdf0e10cSrcweir elif orig[0] == orig[-1] == '"': 45cdf0e10cSrcweir return orig[1:-1] 46cdf0e10cSrcweir elif orig[0] == '<' and orig[-1] == '>': 47cdf0e10cSrcweir return orig[1:-1] 48cdf0e10cSrcweir 49cdf0e10cSrcweir return orig 50cdf0e10cSrcweir 51cdf0e10cSrcweir 52cdf0e10cSrcweirdef dumpTokens (tokens, toError=False): 53cdf0e10cSrcweir 54cdf0e10cSrcweir scope = 0 55cdf0e10cSrcweir indent = " " 56cdf0e10cSrcweir line = '' 57cdf0e10cSrcweir chars = '' 58cdf0e10cSrcweir 59cdf0e10cSrcweir for token in tokens: 60cdf0e10cSrcweir if token in '{<': 61cdf0e10cSrcweir if len(line) > 0: 62cdf0e10cSrcweir chars += indent*scope + line + "\n" 63cdf0e10cSrcweir line = '' 64cdf0e10cSrcweir chars += indent*scope + token + "\n" 65cdf0e10cSrcweir scope += 1 66cdf0e10cSrcweir 67cdf0e10cSrcweir elif token in '}>': 68cdf0e10cSrcweir if len(line) > 0: 69cdf0e10cSrcweir chars += indent*scope + line + "\n" 70cdf0e10cSrcweir line = '' 71cdf0e10cSrcweir scope -= 1 72cdf0e10cSrcweir chars += indent*scope + token 73cdf0e10cSrcweir 74cdf0e10cSrcweir elif token == ';': 75cdf0e10cSrcweir if len(line) > 0: 76cdf0e10cSrcweir chars += indent*scope + line + ";\n" 77cdf0e10cSrcweir line = '' 78cdf0e10cSrcweir else: 79cdf0e10cSrcweir chars += ";\n" 80cdf0e10cSrcweir elif len(token) > 0: 81cdf0e10cSrcweir line += token + ' ' 82cdf0e10cSrcweir 83cdf0e10cSrcweir if len(line) > 0: 84cdf0e10cSrcweir chars += line 85cdf0e10cSrcweir chars += "\n" 86cdf0e10cSrcweir if toError: 87cdf0e10cSrcweir sys.stderr.write(chars) 88cdf0e10cSrcweir else: 89cdf0e10cSrcweir sys.stdout.write(chars) 90cdf0e10cSrcweir 91cdf0e10cSrcweir 92cdf0e10cSrcweirclass HeaderData(object): 93cdf0e10cSrcweir def __init__ (self): 94cdf0e10cSrcweir self.defines = {} 95cdf0e10cSrcweir self.tokens = [] 96cdf0e10cSrcweir 97cdf0e10cSrcweir 98cdf0e10cSrcweirclass SrcLexer(object): 99cdf0e10cSrcweir """Lexicographical analyzer for .src format. 100cdf0e10cSrcweir 101cdf0e10cSrcweirThe role of a lexer is to parse the source file and break it into 102cdf0e10cSrcweirappropriate tokens. Such tokens are later passed to a parser to 103cdf0e10cSrcweirbuild the syntax tree. 104cdf0e10cSrcweir""" 105cdf0e10cSrcweir headerCache = {} 106cdf0e10cSrcweir 107cdf0e10cSrcweir VISIBLE = 0 108cdf0e10cSrcweir INVISIBLE_PRE = 1 109cdf0e10cSrcweir INVISIBLE_POST = 2 110cdf0e10cSrcweir 111cdf0e10cSrcweir def __init__ (self, chars, filepath = None): 112cdf0e10cSrcweir self.filepath = filepath 113cdf0e10cSrcweir self.parentLexer = None 114cdf0e10cSrcweir self.chars = chars 115cdf0e10cSrcweir self.bufsize = len(self.chars) 116cdf0e10cSrcweir 117cdf0e10cSrcweir # TODO: use parameters for this 118cdf0e10cSrcweir # Properties that can be copied. 119cdf0e10cSrcweir self.headerDict = dict () 120cdf0e10cSrcweir self.debug = False 121cdf0e10cSrcweir self.debugMacro = False 122cdf0e10cSrcweir self.includeDirs = list () 123cdf0e10cSrcweir self.expandHeaders = True 124cdf0e10cSrcweir self.inMacroDefine = False 125cdf0e10cSrcweir self.stopOnHeader = False 126cdf0e10cSrcweir 127cdf0e10cSrcweir def copyProperties (self, other): 128cdf0e10cSrcweir """Copy properties from another instance of SrcLexer.""" 129cdf0e10cSrcweir 130cdf0e10cSrcweir # TODO: use parameters for this 131cdf0e10cSrcweir self.headerDict = other.headerDict 132cdf0e10cSrcweir self.debug = other.debug 133cdf0e10cSrcweir self.debugMacro = other.debugMacro 134cdf0e10cSrcweir self.includeDirs = other.includeDirs[:] 135cdf0e10cSrcweir self.expandHeaders = other.expandHeaders 136cdf0e10cSrcweir self.inMacroDefine = other.inMacroDefine 137cdf0e10cSrcweir self.stopOnHeader = other.stopOnHeader 138cdf0e10cSrcweir 139cdf0e10cSrcweir def init (self): 140cdf0e10cSrcweir self.firstNonBlank = '' 141cdf0e10cSrcweir self.token = '' 142cdf0e10cSrcweir self.tokens = [] 143cdf0e10cSrcweir self.defines = {} 144cdf0e10cSrcweir self.visibilityStack = [] 145cdf0e10cSrcweir 146cdf0e10cSrcweir def getTokens (self): 147cdf0e10cSrcweir return self.tokens 148cdf0e10cSrcweir 149cdf0e10cSrcweir def getDefines (self): 150cdf0e10cSrcweir return self.defines 151cdf0e10cSrcweir 152cdf0e10cSrcweir def nextPos (self, i): 153cdf0e10cSrcweir while True: 154cdf0e10cSrcweir i += 1 155cdf0e10cSrcweir try: 156cdf0e10cSrcweir c = self.chars[i] 157cdf0e10cSrcweir except IndexError: 158cdf0e10cSrcweir raise EOF 159cdf0e10cSrcweir 160cdf0e10cSrcweir if ord(c) in [0x0D]: 161cdf0e10cSrcweir continue 162cdf0e10cSrcweir break 163cdf0e10cSrcweir return i 164cdf0e10cSrcweir 165cdf0e10cSrcweir def prevPos (self, i): 166cdf0e10cSrcweir while True: 167cdf0e10cSrcweir i -= 1 168cdf0e10cSrcweir try: 169cdf0e10cSrcweir c = self.chars[i] 170cdf0e10cSrcweir except IndexError: 171cdf0e10cSrcweir raise BOF 172cdf0e10cSrcweir 173cdf0e10cSrcweir if ord(c) in [0x0D]: 174cdf0e10cSrcweir continue 175cdf0e10cSrcweir break 176cdf0e10cSrcweir return i 177cdf0e10cSrcweir 178cdf0e10cSrcweir def isCodeVisible (self): 179cdf0e10cSrcweir if len(self.visibilityStack) == 0: 180cdf0e10cSrcweir return True 181cdf0e10cSrcweir for item in self.visibilityStack: 182cdf0e10cSrcweir if item != SrcLexer.VISIBLE: 183cdf0e10cSrcweir return False 184cdf0e10cSrcweir return True 185cdf0e10cSrcweir 186cdf0e10cSrcweir def tokenize (self): 187cdf0e10cSrcweir self.init() 188cdf0e10cSrcweir 189cdf0e10cSrcweir i = 0 190cdf0e10cSrcweir while True: 191cdf0e10cSrcweir c = self.chars[i] 192cdf0e10cSrcweir 193cdf0e10cSrcweir if self.firstNonBlank == '' and not c in [' ', "\n", "\t"]: 194cdf0e10cSrcweir # Store the first non-blank in a line. 195cdf0e10cSrcweir self.firstNonBlank = c 196cdf0e10cSrcweir elif c == "\n": 197cdf0e10cSrcweir self.firstNonBlank = '' 198cdf0e10cSrcweir 199cdf0e10cSrcweir if c == '#': 200cdf0e10cSrcweir i = self.pound(i) 201cdf0e10cSrcweir elif c == '/': 202cdf0e10cSrcweir i = self.slash(i) 203cdf0e10cSrcweir elif c == "\n": 204cdf0e10cSrcweir i = self.lineBreak(i) 205cdf0e10cSrcweir elif c == '"': 206cdf0e10cSrcweir i = self.doubleQuote(i) 207cdf0e10cSrcweir elif c in [' ', "\t"]: 208cdf0e10cSrcweir i = self.blank(i) 209cdf0e10cSrcweir elif c in ";()[]{}<>,=+-*": 210cdf0e10cSrcweir # Any outstanding single-character token. 211cdf0e10cSrcweir i = self.anyToken(i, c) 212cdf0e10cSrcweir elif self.isCodeVisible(): 213cdf0e10cSrcweir self.token += c 214cdf0e10cSrcweir 215cdf0e10cSrcweir try: 216cdf0e10cSrcweir i = self.nextPos(i) 217cdf0e10cSrcweir except EOF: 218cdf0e10cSrcweir break 219cdf0e10cSrcweir 220cdf0e10cSrcweir if len(self.token): 221cdf0e10cSrcweir self.tokens.append(self.token) 222cdf0e10cSrcweir 223cdf0e10cSrcweir if not self.parentLexer and self.debug: 224cdf0e10cSrcweir progress ("-"*68 + "\n") 225cdf0e10cSrcweir progress ("All defines found in this translation unit:\n") 226cdf0e10cSrcweir keys = self.defines.keys() 227cdf0e10cSrcweir keys.sort() 228cdf0e10cSrcweir for key in keys: 229cdf0e10cSrcweir progress ("@ %s\n"%key) 230cdf0e10cSrcweir 231cdf0e10cSrcweir def dumpTokens (self, toError=False): 232cdf0e10cSrcweir dumpTokens(self.tokens, toError) 233cdf0e10cSrcweir 234cdf0e10cSrcweir 235cdf0e10cSrcweir def maybeAddToken (self): 236cdf0e10cSrcweir if len(self.token) > 0: 237cdf0e10cSrcweir self.tokens.append(self.token) 238cdf0e10cSrcweir self.token = '' 239cdf0e10cSrcweir 240cdf0e10cSrcweir 241cdf0e10cSrcweir #-------------------------------------------------------------------- 242cdf0e10cSrcweir # character handlers 243cdf0e10cSrcweir 244cdf0e10cSrcweir def blank (self, i): 245cdf0e10cSrcweir if not self.isCodeVisible(): 246cdf0e10cSrcweir return i 247cdf0e10cSrcweir 248cdf0e10cSrcweir self.maybeAddToken() 249cdf0e10cSrcweir return i 250cdf0e10cSrcweir 251cdf0e10cSrcweir 252cdf0e10cSrcweir def pound (self, i): 253cdf0e10cSrcweir 254cdf0e10cSrcweir if self.inMacroDefine: 255cdf0e10cSrcweir return i 256cdf0e10cSrcweir 257cdf0e10cSrcweir if not self.firstNonBlank == '#': 258cdf0e10cSrcweir return i 259cdf0e10cSrcweir 260cdf0e10cSrcweir self.maybeAddToken() 261cdf0e10cSrcweir # We are in preprocessing mode. 262cdf0e10cSrcweir 263cdf0e10cSrcweir # Get the macro command name '#<command> .....' 264cdf0e10cSrcweir 265cdf0e10cSrcweir command, define, buf = '', '', '' 266cdf0e10cSrcweir firstNonBlank = False 267cdf0e10cSrcweir while True: 268cdf0e10cSrcweir try: 269cdf0e10cSrcweir i = self.nextPos(i) 270cdf0e10cSrcweir c = self.chars[i] 271cdf0e10cSrcweir if c == '\\' and self.chars[self.nextPos(i)] == "\n": 272cdf0e10cSrcweir i = self.nextPos(i) 273cdf0e10cSrcweir continue 274cdf0e10cSrcweir except EOF: 275cdf0e10cSrcweir break 276cdf0e10cSrcweir 277cdf0e10cSrcweir if c == "\n": 278cdf0e10cSrcweir if len(buf) > 0 and len(command) == 0: 279cdf0e10cSrcweir command = buf 280cdf0e10cSrcweir i = self.prevPos(i) 281cdf0e10cSrcweir break 282cdf0e10cSrcweir elif c in [' ', "\t"]: 283cdf0e10cSrcweir if not firstNonBlank: 284cdf0e10cSrcweir # Ignore any leading blanks after the '#'. 285cdf0e10cSrcweir continue 286cdf0e10cSrcweir 287cdf0e10cSrcweir if len(command) == 0: 288cdf0e10cSrcweir command = buf 289cdf0e10cSrcweir buf = '' 290cdf0e10cSrcweir else: 291cdf0e10cSrcweir buf += ' ' 292cdf0e10cSrcweir elif c == '(': 293cdf0e10cSrcweir if len(buf) > 0 and len(command) == 0: 294cdf0e10cSrcweir command = buf 295cdf0e10cSrcweir buf += c 296cdf0e10cSrcweir else: 297cdf0e10cSrcweir if not firstNonBlank: 298cdf0e10cSrcweir firstNonBlank = True 299cdf0e10cSrcweir buf += c 300cdf0e10cSrcweir 301cdf0e10cSrcweir if command == 'define': 302cdf0e10cSrcweir self.handleMacroDefine(buf) 303cdf0e10cSrcweir elif command == 'include': 304cdf0e10cSrcweir self.handleMacroInclude(buf) 305cdf0e10cSrcweir elif command == 'ifdef': 306cdf0e10cSrcweir defineName = buf.strip() 307cdf0e10cSrcweir if self.defines.has_key(defineName): 308cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.VISIBLE) 309cdf0e10cSrcweir else: 310cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.INVISIBLE_PRE) 311cdf0e10cSrcweir 312cdf0e10cSrcweir elif command == 'ifndef': 313cdf0e10cSrcweir defineName = buf.strip() 314cdf0e10cSrcweir if self.defines.has_key(defineName): 315cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.INVISIBLE_PRE) 316cdf0e10cSrcweir else: 317cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.VISIBLE) 318cdf0e10cSrcweir 319cdf0e10cSrcweir elif command == 'if': 320cdf0e10cSrcweir if self.evalCodeVisibility(buf): 321cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.VISIBLE) 322cdf0e10cSrcweir else: 323cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.INVISIBLE_PRE) 324cdf0e10cSrcweir 325cdf0e10cSrcweir elif command == 'elif': 326cdf0e10cSrcweir if len(self.visibilityStack) == 0: 327cdf0e10cSrcweir raise ParseError ('') 328cdf0e10cSrcweir 329cdf0e10cSrcweir if self.visibilityStack[-1] == SrcLexer.VISIBLE: 330cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST 331cdf0e10cSrcweir elif self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE: 332cdf0e10cSrcweir # Evaluate only if the current visibility is false. 333cdf0e10cSrcweir if self.evalCodeVisibility(buf): 334cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.VISIBLE 335cdf0e10cSrcweir 336cdf0e10cSrcweir elif command == 'else': 337cdf0e10cSrcweir if len(self.visibilityStack) == 0: 338cdf0e10cSrcweir raise ParseError ('') 339cdf0e10cSrcweir 340cdf0e10cSrcweir if self.visibilityStack[-1] == SrcLexer.VISIBLE: 341cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST 342cdf0e10cSrcweir if self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE: 343cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.VISIBLE 344cdf0e10cSrcweir 345cdf0e10cSrcweir elif command == 'endif': 346cdf0e10cSrcweir if len(self.visibilityStack) == 0: 347cdf0e10cSrcweir raise ParseError ('') 348cdf0e10cSrcweir self.visibilityStack.pop() 349cdf0e10cSrcweir 350cdf0e10cSrcweir elif command == 'undef': 351cdf0e10cSrcweir pass 352cdf0e10cSrcweir elif command in ['error', 'pragma']: 353cdf0e10cSrcweir pass 354cdf0e10cSrcweir else: 355cdf0e10cSrcweir print "'%s' '%s'"%(command, buf) 356cdf0e10cSrcweir print self.filepath 357cdf0e10cSrcweir sys.exit(0) 358cdf0e10cSrcweir 359cdf0e10cSrcweir return i 360cdf0e10cSrcweir 361cdf0e10cSrcweir 362cdf0e10cSrcweir def evalCodeVisibility (self, buf): 363cdf0e10cSrcweir try: 364cdf0e10cSrcweir return eval(buf) 365cdf0e10cSrcweir except: 366cdf0e10cSrcweir return True 367cdf0e10cSrcweir 368cdf0e10cSrcweir def handleMacroDefine (self, buf): 369cdf0e10cSrcweir 370cdf0e10cSrcweir mparser = macroparser.MacroParser(buf) 371cdf0e10cSrcweir mparser.debug = self.debugMacro 372cdf0e10cSrcweir mparser.parse() 373cdf0e10cSrcweir macro = mparser.getMacro() 374cdf0e10cSrcweir if macro: 375cdf0e10cSrcweir self.defines[macro.name] = macro 376cdf0e10cSrcweir 377cdf0e10cSrcweir def handleMacroInclude (self, buf): 378cdf0e10cSrcweir 379cdf0e10cSrcweir # Strip excess string if any. 380cdf0e10cSrcweir pos = buf.find(' ') 381cdf0e10cSrcweir if pos >= 0: 382cdf0e10cSrcweir buf = buf[:pos] 383cdf0e10cSrcweir headerSub = removeHeaderQuotes(buf) 384cdf0e10cSrcweir 385cdf0e10cSrcweir if not self.expandHeaders: 386cdf0e10cSrcweir # We don't want to expand headers. Bail out. 387cdf0e10cSrcweir if self.debug: 388cdf0e10cSrcweir progress ("%s ignored\n"%headerSub) 389cdf0e10cSrcweir return 390cdf0e10cSrcweir 391cdf0e10cSrcweir defines = {} 392cdf0e10cSrcweir headerPath = None 393cdf0e10cSrcweir for includeDir in self.includeDirs: 394cdf0e10cSrcweir hpath = includeDir + '/' + headerSub 395cdf0e10cSrcweir if os.path.isfile(hpath) and hpath != self.filepath: 396cdf0e10cSrcweir headerPath = hpath 397cdf0e10cSrcweir break 398cdf0e10cSrcweir 399cdf0e10cSrcweir if not headerPath: 400cdf0e10cSrcweir error("included header file " + headerSub + " not found\n", self.stopOnHeader) 401cdf0e10cSrcweir return 402cdf0e10cSrcweir 403cdf0e10cSrcweir if self.debug: 404cdf0e10cSrcweir progress ("%s found\n"%headerPath) 405cdf0e10cSrcweir 406cdf0e10cSrcweir if headerPath in self.headerDict: 407cdf0e10cSrcweir if self.debug: 408cdf0e10cSrcweir progress ("%s already included\n"%headerPath) 409cdf0e10cSrcweir return 410cdf0e10cSrcweir 411cdf0e10cSrcweir if SrcLexer.headerCache.has_key(headerPath): 412cdf0e10cSrcweir if self.debug: 413cdf0e10cSrcweir progress ("%s in cache\n"%headerPath) 414cdf0e10cSrcweir for key in SrcLexer.headerCache[headerPath].defines.keys(): 415cdf0e10cSrcweir self.defines[key] = SrcLexer.headerCache[headerPath].defines[key] 416cdf0e10cSrcweir return 417cdf0e10cSrcweir 418cdf0e10cSrcweir chars = open(headerPath, 'r').read() 419cdf0e10cSrcweir mclexer = SrcLexer(chars, headerPath) 420cdf0e10cSrcweir mclexer.copyProperties(self) 421cdf0e10cSrcweir mclexer.parentLexer = self 422cdf0e10cSrcweir mclexer.tokenize() 423cdf0e10cSrcweir hdrData = HeaderData() 424cdf0e10cSrcweir hdrData.tokens = mclexer.getTokens() 425cdf0e10cSrcweir headerDefines = mclexer.getDefines() 426cdf0e10cSrcweir for key in headerDefines.keys(): 427cdf0e10cSrcweir defines[key] = headerDefines[key] 428cdf0e10cSrcweir hdrData.defines[key] = headerDefines[key] 429cdf0e10cSrcweir 430cdf0e10cSrcweir self.headerDict[headerPath] = True 431cdf0e10cSrcweir SrcLexer.headerCache[headerPath] = hdrData 432cdf0e10cSrcweir 433cdf0e10cSrcweir # Update the list of headers that have already been expaneded. 434cdf0e10cSrcweir for key in mclexer.headerDict.keys(): 435cdf0e10cSrcweir self.headerDict[key] = True 436cdf0e10cSrcweir 437cdf0e10cSrcweir if self.debug: 438cdf0e10cSrcweir progress ("defines found in header %s:\n"%headerSub) 439cdf0e10cSrcweir for key in defines.keys(): 440cdf0e10cSrcweir progress (" '%s'\n"%key) 441cdf0e10cSrcweir 442cdf0e10cSrcweir for key in defines.keys(): 443cdf0e10cSrcweir self.defines[key] = defines[key] 444cdf0e10cSrcweir 445cdf0e10cSrcweir 446cdf0e10cSrcweir def slash (self, i): 447cdf0e10cSrcweir if not self.isCodeVisible(): 448cdf0e10cSrcweir return i 449cdf0e10cSrcweir 450cdf0e10cSrcweir if i < self.bufsize - 1 and self.chars[i+1] == '/': 451cdf0e10cSrcweir # Parse line comment. 452cdf0e10cSrcweir line = '' 453cdf0e10cSrcweir i += 2 454cdf0e10cSrcweir while i < self.bufsize: 455cdf0e10cSrcweir c = self.chars[i] 456cdf0e10cSrcweir if ord(c) in [0x0A, 0x0D]: 457cdf0e10cSrcweir return i - 1 458cdf0e10cSrcweir line += c 459cdf0e10cSrcweir i += 1 460cdf0e10cSrcweir self.token = '' 461cdf0e10cSrcweir elif i < self.bufsize - 1 and self.chars[i+1] == '*': 462cdf0e10cSrcweir comment = '' 463cdf0e10cSrcweir i += 2 464cdf0e10cSrcweir while i < self.bufsize: 465cdf0e10cSrcweir c = self.chars[i] 466cdf0e10cSrcweir if c == '/' and self.chars[i-1] == '*': 467cdf0e10cSrcweir return i 468cdf0e10cSrcweir comment += c 469cdf0e10cSrcweir i += 1 470cdf0e10cSrcweir else: 471cdf0e10cSrcweir return self.anyToken(i, '/') 472cdf0e10cSrcweir 473cdf0e10cSrcweir return i 474cdf0e10cSrcweir 475cdf0e10cSrcweir 476cdf0e10cSrcweir def lineBreak (self, i): 477cdf0e10cSrcweir if not self.isCodeVisible(): 478cdf0e10cSrcweir return i 479cdf0e10cSrcweir 480cdf0e10cSrcweir self.maybeAddToken() 481cdf0e10cSrcweir 482cdf0e10cSrcweir return i 483cdf0e10cSrcweir 484cdf0e10cSrcweir 485cdf0e10cSrcweir def doubleQuote (self, i): 486cdf0e10cSrcweir if not self.isCodeVisible(): 487cdf0e10cSrcweir return i 488cdf0e10cSrcweir 489cdf0e10cSrcweir literal = '' 490cdf0e10cSrcweir i += 1 491cdf0e10cSrcweir while i < self.bufsize: 492cdf0e10cSrcweir c = self.chars[i] 493cdf0e10cSrcweir if c == '"': 494cdf0e10cSrcweir self.tokens.append('"'+literal+'"') 495cdf0e10cSrcweir break 496cdf0e10cSrcweir literal += c 497cdf0e10cSrcweir i += 1 498cdf0e10cSrcweir 499cdf0e10cSrcweir return i 500cdf0e10cSrcweir 501cdf0e10cSrcweir 502cdf0e10cSrcweir def anyToken (self, i, token): 503cdf0e10cSrcweir if not self.isCodeVisible(): 504cdf0e10cSrcweir return i 505cdf0e10cSrcweir 506cdf0e10cSrcweir self.maybeAddToken() 507cdf0e10cSrcweir self.token = token 508cdf0e10cSrcweir self.maybeAddToken() 509cdf0e10cSrcweir return i 510