19f22d7c2SAndrew Rist# ************************************************************* 29f22d7c2SAndrew Rist# 39f22d7c2SAndrew Rist# Licensed to the Apache Software Foundation (ASF) under one 49f22d7c2SAndrew Rist# or more contributor license agreements. See the NOTICE file 59f22d7c2SAndrew Rist# distributed with this work for additional information 69f22d7c2SAndrew Rist# regarding copyright ownership. The ASF licenses this file 79f22d7c2SAndrew Rist# to you under the Apache License, Version 2.0 (the 89f22d7c2SAndrew Rist# "License"); you may not use this file except in compliance 99f22d7c2SAndrew Rist# with the License. You may obtain a copy of the License at 109f22d7c2SAndrew Rist# 119f22d7c2SAndrew Rist# http://www.apache.org/licenses/LICENSE-2.0 129f22d7c2SAndrew Rist# 139f22d7c2SAndrew Rist# Unless required by applicable law or agreed to in writing, 149f22d7c2SAndrew Rist# software distributed under the License is distributed on an 159f22d7c2SAndrew Rist# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169f22d7c2SAndrew Rist# KIND, either express or implied. See the License for the 179f22d7c2SAndrew Rist# specific language governing permissions and limitations 189f22d7c2SAndrew Rist# under the License. 199f22d7c2SAndrew Rist# 209f22d7c2SAndrew Rist# ************************************************************* 219f22d7c2SAndrew 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 = '' 58ae54856bSPedro Giffuni 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 101ae54856bSPedro GiffuniThe 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 185ae54856bSPedro Giffuni 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") 22677de67d5SPedro Giffuni keys = sorted(self.defines.keys()) 227cdf0e10cSrcweir for key in keys: 228cdf0e10cSrcweir progress ("@ %s\n"%key) 229cdf0e10cSrcweir 230cdf0e10cSrcweir def dumpTokens (self, toError=False): 231cdf0e10cSrcweir dumpTokens(self.tokens, toError) 232cdf0e10cSrcweir 233cdf0e10cSrcweir 234cdf0e10cSrcweir def maybeAddToken (self): 235cdf0e10cSrcweir if len(self.token) > 0: 236cdf0e10cSrcweir self.tokens.append(self.token) 237cdf0e10cSrcweir self.token = '' 238cdf0e10cSrcweir 239cdf0e10cSrcweir 240cdf0e10cSrcweir #-------------------------------------------------------------------- 241cdf0e10cSrcweir # character handlers 242cdf0e10cSrcweir 243cdf0e10cSrcweir def blank (self, i): 244cdf0e10cSrcweir if not self.isCodeVisible(): 245cdf0e10cSrcweir return i 246cdf0e10cSrcweir 247cdf0e10cSrcweir self.maybeAddToken() 248cdf0e10cSrcweir return i 249cdf0e10cSrcweir 250cdf0e10cSrcweir 251cdf0e10cSrcweir def pound (self, i): 252cdf0e10cSrcweir 253cdf0e10cSrcweir if self.inMacroDefine: 254cdf0e10cSrcweir return i 255cdf0e10cSrcweir 256cdf0e10cSrcweir if not self.firstNonBlank == '#': 257cdf0e10cSrcweir return i 258cdf0e10cSrcweir 259cdf0e10cSrcweir self.maybeAddToken() 260cdf0e10cSrcweir # We are in preprocessing mode. 261cdf0e10cSrcweir 262cdf0e10cSrcweir # Get the macro command name '#<command> .....' 263cdf0e10cSrcweir 264cdf0e10cSrcweir command, define, buf = '', '', '' 265cdf0e10cSrcweir firstNonBlank = False 266cdf0e10cSrcweir while True: 267cdf0e10cSrcweir try: 268cdf0e10cSrcweir i = self.nextPos(i) 269cdf0e10cSrcweir c = self.chars[i] 270cdf0e10cSrcweir if c == '\\' and self.chars[self.nextPos(i)] == "\n": 271cdf0e10cSrcweir i = self.nextPos(i) 272cdf0e10cSrcweir continue 273cdf0e10cSrcweir except EOF: 274cdf0e10cSrcweir break 275cdf0e10cSrcweir 276cdf0e10cSrcweir if c == "\n": 277cdf0e10cSrcweir if len(buf) > 0 and len(command) == 0: 278cdf0e10cSrcweir command = buf 279cdf0e10cSrcweir i = self.prevPos(i) 280cdf0e10cSrcweir break 281cdf0e10cSrcweir elif c in [' ', "\t"]: 282cdf0e10cSrcweir if not firstNonBlank: 283cdf0e10cSrcweir # Ignore any leading blanks after the '#'. 284cdf0e10cSrcweir continue 285cdf0e10cSrcweir 286cdf0e10cSrcweir if len(command) == 0: 287cdf0e10cSrcweir command = buf 288cdf0e10cSrcweir buf = '' 289cdf0e10cSrcweir else: 290cdf0e10cSrcweir buf += ' ' 291cdf0e10cSrcweir elif c == '(': 292cdf0e10cSrcweir if len(buf) > 0 and len(command) == 0: 293cdf0e10cSrcweir command = buf 294cdf0e10cSrcweir buf += c 295cdf0e10cSrcweir else: 296cdf0e10cSrcweir if not firstNonBlank: 297cdf0e10cSrcweir firstNonBlank = True 298cdf0e10cSrcweir buf += c 299cdf0e10cSrcweir 300cdf0e10cSrcweir if command == 'define': 301cdf0e10cSrcweir self.handleMacroDefine(buf) 302cdf0e10cSrcweir elif command == 'include': 303cdf0e10cSrcweir self.handleMacroInclude(buf) 304cdf0e10cSrcweir elif command == 'ifdef': 305cdf0e10cSrcweir defineName = buf.strip() 306*7d9fa7c3SPedro Giffuni if defineName in self.defines: 307cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.VISIBLE) 308cdf0e10cSrcweir else: 309cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.INVISIBLE_PRE) 310cdf0e10cSrcweir 311cdf0e10cSrcweir elif command == 'ifndef': 312cdf0e10cSrcweir defineName = buf.strip() 313*7d9fa7c3SPedro Giffuni if defineName in self.defines: 314cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.INVISIBLE_PRE) 315cdf0e10cSrcweir else: 316cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.VISIBLE) 317cdf0e10cSrcweir 318cdf0e10cSrcweir elif command == 'if': 319cdf0e10cSrcweir if self.evalCodeVisibility(buf): 320cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.VISIBLE) 321cdf0e10cSrcweir else: 322cdf0e10cSrcweir self.visibilityStack.append(SrcLexer.INVISIBLE_PRE) 323cdf0e10cSrcweir 324cdf0e10cSrcweir elif command == 'elif': 325cdf0e10cSrcweir if len(self.visibilityStack) == 0: 326cdf0e10cSrcweir raise ParseError ('') 327cdf0e10cSrcweir 328cdf0e10cSrcweir if self.visibilityStack[-1] == SrcLexer.VISIBLE: 329cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST 330cdf0e10cSrcweir elif self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE: 331cdf0e10cSrcweir # Evaluate only if the current visibility is false. 332cdf0e10cSrcweir if self.evalCodeVisibility(buf): 333cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.VISIBLE 334cdf0e10cSrcweir 335cdf0e10cSrcweir elif command == 'else': 336cdf0e10cSrcweir if len(self.visibilityStack) == 0: 337cdf0e10cSrcweir raise ParseError ('') 338cdf0e10cSrcweir 339cdf0e10cSrcweir if self.visibilityStack[-1] == SrcLexer.VISIBLE: 340cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST 341cdf0e10cSrcweir if self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE: 342cdf0e10cSrcweir self.visibilityStack[-1] = SrcLexer.VISIBLE 343cdf0e10cSrcweir 344cdf0e10cSrcweir elif command == 'endif': 345cdf0e10cSrcweir if len(self.visibilityStack) == 0: 346cdf0e10cSrcweir raise ParseError ('') 347cdf0e10cSrcweir self.visibilityStack.pop() 348cdf0e10cSrcweir 349cdf0e10cSrcweir elif command == 'undef': 350cdf0e10cSrcweir pass 351cdf0e10cSrcweir elif command in ['error', 'pragma']: 352cdf0e10cSrcweir pass 353cdf0e10cSrcweir else: 354*7d9fa7c3SPedro Giffuni print("'%s' '%s'"%(command, buf)) 355*7d9fa7c3SPedro Giffuni print(self.filepath) 356cdf0e10cSrcweir sys.exit(0) 357cdf0e10cSrcweir 358cdf0e10cSrcweir return i 359cdf0e10cSrcweir 360cdf0e10cSrcweir 361cdf0e10cSrcweir def evalCodeVisibility (self, buf): 362cdf0e10cSrcweir try: 363cdf0e10cSrcweir return eval(buf) 364cdf0e10cSrcweir except: 365cdf0e10cSrcweir return True 366ae54856bSPedro Giffuni 367cdf0e10cSrcweir def handleMacroDefine (self, buf): 368cdf0e10cSrcweir 369cdf0e10cSrcweir mparser = macroparser.MacroParser(buf) 370cdf0e10cSrcweir mparser.debug = self.debugMacro 371cdf0e10cSrcweir mparser.parse() 372cdf0e10cSrcweir macro = mparser.getMacro() 373cdf0e10cSrcweir if macro: 374cdf0e10cSrcweir self.defines[macro.name] = macro 375cdf0e10cSrcweir 376cdf0e10cSrcweir def handleMacroInclude (self, buf): 377cdf0e10cSrcweir 378cdf0e10cSrcweir # Strip excess string if any. 379cdf0e10cSrcweir pos = buf.find(' ') 380cdf0e10cSrcweir if pos >= 0: 381cdf0e10cSrcweir buf = buf[:pos] 382cdf0e10cSrcweir headerSub = removeHeaderQuotes(buf) 383cdf0e10cSrcweir 384cdf0e10cSrcweir if not self.expandHeaders: 385cdf0e10cSrcweir # We don't want to expand headers. Bail out. 386cdf0e10cSrcweir if self.debug: 387cdf0e10cSrcweir progress ("%s ignored\n"%headerSub) 388cdf0e10cSrcweir return 389cdf0e10cSrcweir 390cdf0e10cSrcweir defines = {} 391cdf0e10cSrcweir headerPath = None 392cdf0e10cSrcweir for includeDir in self.includeDirs: 393cdf0e10cSrcweir hpath = includeDir + '/' + headerSub 394cdf0e10cSrcweir if os.path.isfile(hpath) and hpath != self.filepath: 395cdf0e10cSrcweir headerPath = hpath 396cdf0e10cSrcweir break 397cdf0e10cSrcweir 398cdf0e10cSrcweir if not headerPath: 399cdf0e10cSrcweir error("included header file " + headerSub + " not found\n", self.stopOnHeader) 400cdf0e10cSrcweir return 401ae54856bSPedro Giffuni 402cdf0e10cSrcweir if self.debug: 403cdf0e10cSrcweir progress ("%s found\n"%headerPath) 404cdf0e10cSrcweir 405cdf0e10cSrcweir if headerPath in self.headerDict: 406cdf0e10cSrcweir if self.debug: 407cdf0e10cSrcweir progress ("%s already included\n"%headerPath) 408cdf0e10cSrcweir return 409cdf0e10cSrcweir 410*7d9fa7c3SPedro Giffuni if headerPath in SrcLexer.headerCache: 411cdf0e10cSrcweir if self.debug: 412cdf0e10cSrcweir progress ("%s in cache\n"%headerPath) 413*7d9fa7c3SPedro Giffuni for key in list(SrcLexer.headerCache[headerPath].defines.keys()): 414cdf0e10cSrcweir self.defines[key] = SrcLexer.headerCache[headerPath].defines[key] 415cdf0e10cSrcweir return 416cdf0e10cSrcweir 417cdf0e10cSrcweir chars = open(headerPath, 'r').read() 418cdf0e10cSrcweir mclexer = SrcLexer(chars, headerPath) 419cdf0e10cSrcweir mclexer.copyProperties(self) 420cdf0e10cSrcweir mclexer.parentLexer = self 421cdf0e10cSrcweir mclexer.tokenize() 422cdf0e10cSrcweir hdrData = HeaderData() 423cdf0e10cSrcweir hdrData.tokens = mclexer.getTokens() 424cdf0e10cSrcweir headerDefines = mclexer.getDefines() 425*7d9fa7c3SPedro Giffuni for key in list(headerDefines.keys()): 426cdf0e10cSrcweir defines[key] = headerDefines[key] 427cdf0e10cSrcweir hdrData.defines[key] = headerDefines[key] 428cdf0e10cSrcweir 429cdf0e10cSrcweir self.headerDict[headerPath] = True 430cdf0e10cSrcweir SrcLexer.headerCache[headerPath] = hdrData 431cdf0e10cSrcweir 432cdf0e10cSrcweir # Update the list of headers that have already been expaneded. 433*7d9fa7c3SPedro Giffuni for key in list(mclexer.headerDict.keys()): 434cdf0e10cSrcweir self.headerDict[key] = True 435cdf0e10cSrcweir 436cdf0e10cSrcweir if self.debug: 437cdf0e10cSrcweir progress ("defines found in header %s:\n"%headerSub) 438*7d9fa7c3SPedro Giffuni for key in list(defines.keys()): 439cdf0e10cSrcweir progress (" '%s'\n"%key) 440cdf0e10cSrcweir 441*7d9fa7c3SPedro Giffuni for key in list(defines.keys()): 442cdf0e10cSrcweir self.defines[key] = defines[key] 443cdf0e10cSrcweir 444cdf0e10cSrcweir 445cdf0e10cSrcweir def slash (self, i): 446cdf0e10cSrcweir if not self.isCodeVisible(): 447cdf0e10cSrcweir return i 448cdf0e10cSrcweir 449cdf0e10cSrcweir if i < self.bufsize - 1 and self.chars[i+1] == '/': 450cdf0e10cSrcweir # Parse line comment. 451cdf0e10cSrcweir line = '' 452cdf0e10cSrcweir i += 2 453cdf0e10cSrcweir while i < self.bufsize: 454cdf0e10cSrcweir c = self.chars[i] 455cdf0e10cSrcweir if ord(c) in [0x0A, 0x0D]: 456cdf0e10cSrcweir return i - 1 457cdf0e10cSrcweir line += c 458cdf0e10cSrcweir i += 1 459cdf0e10cSrcweir self.token = '' 460cdf0e10cSrcweir elif i < self.bufsize - 1 and self.chars[i+1] == '*': 461cdf0e10cSrcweir comment = '' 462cdf0e10cSrcweir i += 2 463cdf0e10cSrcweir while i < self.bufsize: 464cdf0e10cSrcweir c = self.chars[i] 465cdf0e10cSrcweir if c == '/' and self.chars[i-1] == '*': 466cdf0e10cSrcweir return i 467cdf0e10cSrcweir comment += c 468cdf0e10cSrcweir i += 1 469cdf0e10cSrcweir else: 470cdf0e10cSrcweir return self.anyToken(i, '/') 471cdf0e10cSrcweir 472cdf0e10cSrcweir return i 473cdf0e10cSrcweir 474cdf0e10cSrcweir 475cdf0e10cSrcweir def lineBreak (self, i): 476cdf0e10cSrcweir if not self.isCodeVisible(): 477cdf0e10cSrcweir return i 478cdf0e10cSrcweir 479cdf0e10cSrcweir self.maybeAddToken() 480cdf0e10cSrcweir 481cdf0e10cSrcweir return i 482cdf0e10cSrcweir 483cdf0e10cSrcweir 484cdf0e10cSrcweir def doubleQuote (self, i): 485cdf0e10cSrcweir if not self.isCodeVisible(): 486cdf0e10cSrcweir return i 487cdf0e10cSrcweir 488cdf0e10cSrcweir literal = '' 489cdf0e10cSrcweir i += 1 490cdf0e10cSrcweir while i < self.bufsize: 491cdf0e10cSrcweir c = self.chars[i] 492cdf0e10cSrcweir if c == '"': 493cdf0e10cSrcweir self.tokens.append('"'+literal+'"') 494cdf0e10cSrcweir break 495cdf0e10cSrcweir literal += c 496cdf0e10cSrcweir i += 1 497cdf0e10cSrcweir 498cdf0e10cSrcweir return i 499cdf0e10cSrcweir 500cdf0e10cSrcweir 501cdf0e10cSrcweir def anyToken (self, i, token): 502cdf0e10cSrcweir if not self.isCodeVisible(): 503cdf0e10cSrcweir return i 504cdf0e10cSrcweir 505cdf0e10cSrcweir self.maybeAddToken() 506cdf0e10cSrcweir self.token = token 507cdf0e10cSrcweir self.maybeAddToken() 508cdf0e10cSrcweir return i 509