# ************************************************************* # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # ************************************************************* import sys from globals import * import srclexer class MacroParser(object): def __init__ (self, buf): self.buffer = buf self.macro = None self.debug = False def parse (self): """ A macro with arguments must have its open paren immediately following its name without any whitespace. """ if self.debug: print("-"*68) print("parsing '%s'"%self.buffer) i = 0 bufSize = len(self.buffer) name, buf = '', '' while i < bufSize: c = self.buffer[i] if c in [' ', "\t"] and len(name) == 0: # This is a simple macro with no arguments. name = buf vars = [] content = self.buffer[i:] self.setMacro(name, vars, content) return elif c == '(' and len(name) == 0: # This one has arguments. name = buf buf = self.buffer[i:] vars, content = self.parseArgs(buf) self.setMacro(name, vars, content) return else: buf += c i += 1 def parseArgs (self, buffer): """Parse arguments. The buffer is expected to be formatted like '(a, b, c)' where the first character is the open paren. """ scope = 0 buf = '' vars = [] content = '' bufSize = len(buffer) i = 0 while i < bufSize: c = buffer[i] if c == '(': scope += 1 elif c == ')': scope -= 1 if len(buf) > 0: vars.append(buf) if scope == 0: break elif c == ',': if len(buf) == 0: raise globals.ParseError ('') vars.append(buf) buf = '' elif c in " \t" and scope > 0: pass else: buf += c i += 1 if scope > 0: raise globals.ParseError ('') return vars, buffer[i+1:] def setMacro (self, name, vars, content): if self.debug: print("-"*68) print("name: %s"%name) for var in vars: print("var: %s"%var) if len(vars) == 0: print("no vars") print("content: '%s'"%content) if len(content) > 0: self.macro = Macro(name) for i in range(0, len(vars)): self.macro.vars[vars[i]] = i # tokinize it using lexer. mclexer = srclexer.SrcLexer(content) mclexer.expandHeaders = False mclexer.inMacroDefine = True mclexer.tokenize() self.macro.tokens = mclexer.getTokens() if self.debug: print(self.macro.tokens) if not self.isValidMacro(self.macro): self.macro = None if self.debug: if self.macro != None: print("macro registered!") else: print("macro not registered") def isValidMacro (self, macro): n = len(macro.tokens) if n == 0: return False elif len(macro.name) > 4 and macro.name[1:4] == 'ID_': # We don't want to expand macros like HID_, SID_, WID_, etc. return False return True def getMacro (self): return self.macro