1 2import sys 3from globals import * 4import srclexer 5 6class MacroParser(object): 7 8 def __init__ (self, buf): 9 self.buffer = buf 10 self.macro = None 11 self.debug = False 12 13 def parse (self): 14 """ 15A macro with arguments must have its open paren immediately following 16its name without any whitespace. 17""" 18 if self.debug: 19 print "-"*68 20 print "parsing '%s'"%self.buffer 21 22 i = 0 23 bufSize = len(self.buffer) 24 name, buf = '', '' 25 while i < bufSize: 26 c = self.buffer[i] 27 if c in [' ', "\t"] and len(name) == 0: 28 # This is a simple macro with no arguments. 29 name = buf 30 vars = [] 31 content = self.buffer[i:] 32 self.setMacro(name, vars, content) 33 return 34 elif c == '(' and len(name) == 0: 35 # This one has arguments. 36 name = buf 37 buf = self.buffer[i:] 38 vars, content = self.parseArgs(buf) 39 self.setMacro(name, vars, content) 40 return 41 else: 42 buf += c 43 i += 1 44 45 def parseArgs (self, buffer): 46 """Parse arguments. 47 48The buffer is expected to be formatted like '(a, b, c)' where the first 49character is the open paren. 50""" 51 scope = 0 52 buf = '' 53 vars = [] 54 content = '' 55 bufSize = len(buffer) 56 i = 0 57 while i < bufSize: 58 c = buffer[i] 59 if c == '(': 60 scope += 1 61 elif c == ')': 62 scope -= 1 63 if len(buf) > 0: 64 vars.append(buf) 65 if scope == 0: 66 break 67 elif c == ',': 68 if len(buf) == 0: 69 raise globals.ParseError ('') 70 vars.append(buf) 71 buf = '' 72 elif c in " \t" and scope > 0: 73 pass 74 else: 75 buf += c 76 77 i += 1 78 79 if scope > 0: 80 raise globals.ParseError ('') 81 82 return vars, buffer[i+1:] 83 84 85 def setMacro (self, name, vars, content): 86 if self.debug: 87 print "-"*68 88 print "name: %s"%name 89 for var in vars: 90 print "var: %s"%var 91 if len(vars) == 0: 92 print "no vars" 93 print "content: '%s'"%content 94 95 if len(content) > 0: 96 self.macro = Macro(name) 97 for i in xrange(0, len(vars)): 98 self.macro.vars[vars[i]] = i 99 100 # tokinize it using lexer. 101 mclexer = srclexer.SrcLexer(content) 102 mclexer.expandHeaders = False 103 mclexer.inMacroDefine = True 104 mclexer.tokenize() 105 self.macro.tokens = mclexer.getTokens() 106 if self.debug: 107 print self.macro.tokens 108 109 if not self.isValidMacro(self.macro): 110 self.macro = None 111 112 if self.debug: 113 if self.macro != None: 114 print "macro registered!" 115 else: 116 print "macro not registered" 117 118 def isValidMacro (self, macro): 119 120 n = len(macro.tokens) 121 if n == 0: 122 return False 123 elif len(macro.name) > 4 and macro.name[1:4] == 'ID_': 124 # We don't want to expand macros like HID_, SID_, WID_, etc. 125 return False 126 return True 127 128 129 def getMacro (self): 130 return self.macro 131