1# ************************************************************* 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20# ************************************************************* 21 22 23import sys 24from globals import * 25import srclexer 26 27class MacroParser(object): 28 29 def __init__ (self, buf): 30 self.buffer = buf 31 self.macro = None 32 self.debug = False 33 34 def parse (self): 35 """ 36A macro with arguments must have its open paren immediately following 37its name without any whitespace. 38""" 39 if self.debug: 40 print("-"*68) 41 print("parsing '%s'"%self.buffer) 42 43 i = 0 44 bufSize = len(self.buffer) 45 name, buf = '', '' 46 while i < bufSize: 47 c = self.buffer[i] 48 if c in [' ', "\t"] and len(name) == 0: 49 # This is a simple macro with no arguments. 50 name = buf 51 vars = [] 52 content = self.buffer[i:] 53 self.setMacro(name, vars, content) 54 return 55 elif c == '(' and len(name) == 0: 56 # This one has arguments. 57 name = buf 58 buf = self.buffer[i:] 59 vars, content = self.parseArgs(buf) 60 self.setMacro(name, vars, content) 61 return 62 else: 63 buf += c 64 i += 1 65 66 def parseArgs (self, buffer): 67 """Parse arguments. 68 69The buffer is expected to be formatted like '(a, b, c)' where the first 70character is the open paren. 71""" 72 scope = 0 73 buf = '' 74 vars = [] 75 content = '' 76 bufSize = len(buffer) 77 i = 0 78 while i < bufSize: 79 c = buffer[i] 80 if c == '(': 81 scope += 1 82 elif c == ')': 83 scope -= 1 84 if len(buf) > 0: 85 vars.append(buf) 86 if scope == 0: 87 break 88 elif c == ',': 89 if len(buf) == 0: 90 raise globals.ParseError ('') 91 vars.append(buf) 92 buf = '' 93 elif c in " \t" and scope > 0: 94 pass 95 else: 96 buf += c 97 98 i += 1 99 100 if scope > 0: 101 raise globals.ParseError ('') 102 103 return vars, buffer[i+1:] 104 105 106 def setMacro (self, name, vars, content): 107 if self.debug: 108 print("-"*68) 109 print("name: %s"%name) 110 for var in vars: 111 print("var: %s"%var) 112 if len(vars) == 0: 113 print("no vars") 114 print("content: '%s'"%content) 115 116 if len(content) > 0: 117 self.macro = Macro(name) 118 for i in range(0, len(vars)): 119 self.macro.vars[vars[i]] = i 120 121 # tokinize it using lexer. 122 mclexer = srclexer.SrcLexer(content) 123 mclexer.expandHeaders = False 124 mclexer.inMacroDefine = True 125 mclexer.tokenize() 126 self.macro.tokens = mclexer.getTokens() 127 if self.debug: 128 print(self.macro.tokens) 129 130 if not self.isValidMacro(self.macro): 131 self.macro = None 132 133 if self.debug: 134 if self.macro != None: 135 print("macro registered!") 136 else: 137 print("macro not registered") 138 139 def isValidMacro (self, macro): 140 141 n = len(macro.tokens) 142 if n == 0: 143 return False 144 elif len(macro.name) > 4 and macro.name[1:4] == 'ID_': 145 # We don't want to expand macros like HID_, SID_, WID_, etc. 146 return False 147 return True 148 149 150 def getMacro (self): 151 return self.macro 152