Match compiler: Store matchFunctions and matchStrs in the class instead of passing it around

This commit is contained in:
Thomas Jarosch 2013-01-04 03:56:21 +01:00
parent 542c6e82d3
commit 5f09cb2e4d
1 changed files with 37 additions and 32 deletions

View File

@ -5,19 +5,24 @@ import glob
class MatchCompiler: class MatchCompiler:
def __init__(self): def __init__(self):
self._reset()
self._selftests() self._selftests()
def _insertMatchStr(self, matchStrs, look_for): def _reset(self):
self._matchFunctions = []
self._matchStrs = {}
def _insertMatchStr(self, look_for):
prefix = 'matchStr' prefix = 'matchStr'
# Add entry if needed # Add entry if needed
if look_for not in matchStrs: if look_for not in self._matchStrs:
pos = len(matchStrs) + 1 pos = len(self._matchStrs) + 1
matchStrs[look_for] = pos self._matchStrs[look_for] = pos
return prefix + str(matchStrs[look_for]) return prefix + str(self._matchStrs[look_for])
def _compileCmd(self, tok, matchStrs): def _compileCmd(self, tok):
if tok == '%any%': if tok == '%any%':
return 'true' return 'true'
elif tok == '%bool%': elif tok == '%bool%':
@ -31,13 +36,13 @@ class MatchCompiler:
elif tok == '%op%': elif tok == '%op%':
return 'tok->isOp()' return 'tok->isOp()'
elif tok == '%or%': elif tok == '%or%':
return '(tok->str()==' + self._insertMatchStr(matchStrs, '|') + ')/* | */' return '(tok->str()==' + self._insertMatchStr('|') + ')/* | */'
elif tok == '%oror%': elif tok == '%oror%':
return '(tok->str()==' + self._insertMatchStr(matchStrs, '||') + ')/* || */' return '(tok->str()==' + self._insertMatchStr('||') + ')/* || */'
elif tok == '%str%': elif tok == '%str%':
return '(tok->type()==Token::eString)' return '(tok->type()==Token::eString)'
elif tok == '%type%': elif tok == '%type%':
return '(tok->isName() && tok->varId()==0U && tok->str() != ' + self._insertMatchStr(matchStrs, 'delete') + '/* delete */)' return '(tok->isName() && tok->varId()==0U && tok->str() != ' + self._insertMatchStr('delete') + '/* delete */)'
elif tok == '%var%': elif tok == '%var%':
return 'tok->isName()' return 'tok->isName()'
elif tok == '%varid%': elif tok == '%varid%':
@ -45,9 +50,9 @@ class MatchCompiler:
elif (len(tok)>2) and (tok[0]=="%"): elif (len(tok)>2) and (tok[0]=="%"):
print ("unhandled:" + tok) print ("unhandled:" + tok)
return '(tok->str()==' + self._insertMatchStr(matchStrs, tok) + ')/* ' + tok + ' */' return '(tok->str()==' + self._insertMatchStr(tok) + ')/* ' + tok + ' */'
def _compilePattern(self, matchStrs, pattern, nr, varid, isFindMatch=False): def _compilePattern(self, pattern, nr, varid, isFindMatch=False):
ret = '' ret = ''
returnStatement = '' returnStatement = ''
@ -103,7 +108,7 @@ class MatchCompiler:
if not first: if not first:
ret += logicalOp ret += logicalOp
first = False first = False
ret += neg + self._compileCmd(tok2, matchStrs) ret += neg + self._compileCmd(tok2)
if "" in tokens2: if "" in tokens2:
ret += '))\n' ret += '))\n'
@ -115,12 +120,12 @@ class MatchCompiler:
# !!a # !!a
elif tok[0:2] == "!!": elif tok[0:2] == "!!":
ret += ' if (tok && tok->str() == ' + self._insertMatchStr(matchStrs, tok[2:]) + ')/* ' + tok[2:] + ' */\n' ret += ' if (tok && tok->str() == ' + self._insertMatchStr(tok[2:]) + ')/* ' + tok[2:] + ' */\n'
ret += ' ' + returnStatement ret += ' ' + returnStatement
gotoNextToken = ' tok = tok ? tok->next() : NULL;\n' gotoNextToken = ' tok = tok ? tok->next() : NULL;\n'
else: else:
ret += ' if (!tok || !' + self._compileCmd(tok, matchStrs) + ')\n' ret += ' if (!tok || !' + self._compileCmd(tok) + ')\n'
ret += ' ' + returnStatement ret += ' ' + returnStatement
if isFindMatch: if isFindMatch:
@ -131,7 +136,7 @@ class MatchCompiler:
return ret return ret
def _compileFindPattern(self, matchFunctions, matchStrs, pattern, findmatchnr, endToken, varId): def _compileFindPattern(self, pattern, findmatchnr, endToken, varId):
more_args = '' more_args = ''
endCondition = '' endCondition = ''
if endToken: if endToken:
@ -144,7 +149,7 @@ class MatchCompiler:
ret += 'static const Token *findmatch' + str(findmatchnr) + '(const Token *start_tok'+more_args+') {\n' ret += 'static const Token *findmatch' + str(findmatchnr) + '(const Token *start_tok'+more_args+') {\n'
ret += ' for (; start_tok' + endCondition + '; start_tok = start_tok->next()) {\n' ret += ' for (; start_tok' + endCondition + '; start_tok = start_tok->next()) {\n'
ret += self._compilePattern(matchStrs, pattern, -1, varId, True) ret += self._compilePattern(pattern, -1, varId, True)
ret += ' }\n' ret += ' }\n'
ret += ' return NULL;\n}\n' ret += ' return NULL;\n}\n'
@ -204,7 +209,7 @@ class MatchCompiler:
return None return None
def _replaceTokenMatch(self, matchFunctions, matchStrs, line): def _replaceTokenMatch(self, line):
while True: while True:
pos1 = line.find('Token::Match(') pos1 = line.find('Token::Match(')
if pos1 == -1: if pos1 == -1:
@ -233,13 +238,13 @@ class MatchCompiler:
a3 = '' a3 = ''
if arg3: if arg3:
a3 = ',' + arg3 a3 = ',' + arg3
patternNumber = len(matchFunctions) + 1 patternNumber = len(self._matchFunctions) + 1
line = line[:pos1]+'match'+str(patternNumber)+'('+arg1+a3+')'+line[pos1+len(g0):] line = line[:pos1]+'match'+str(patternNumber)+'('+arg1+a3+')'+line[pos1+len(g0):]
matchFunctions.append(self._compilePattern(matchStrs, arg2, patternNumber, arg3)) self._matchFunctions.append(self._compilePattern(arg2, patternNumber, arg3))
return line return line
def _replaceTokenFindMatch(self, matchFunctions, matchStrs, line): def _replaceTokenFindMatch(self, line):
pos1 = 0 pos1 = 0
while True: while True:
is_findmatch = False is_findmatch = False
@ -293,13 +298,13 @@ class MatchCompiler:
a3 += ',' + endToken a3 += ',' + endToken
if varId: if varId:
a3 += ',' + varId a3 += ',' + varId
findMatchNumber = len(matchFunctions) + 1 findMatchNumber = len(self._matchFunctions) + 1
line = line[:pos1]+'findmatch'+str(findMatchNumber)+'('+arg1+a3+')'+line[pos1+len(g0):] line = line[:pos1]+'findmatch'+str(findMatchNumber)+'('+arg1+a3+')'+line[pos1+len(g0):]
matchFunctions.append(self._compileFindPattern(matchFunctions, matchStrs, pattern, findMatchNumber, endToken, varId)) self._matchFunctions.append(self._compileFindPattern(pattern, findMatchNumber, endToken, varId))
return line return line
def _replaceCStrings(self, matchStrs, line): def _replaceCStrings(self, line):
while True: while True:
match = re.search('str\(\) (==|!=) "', line) match = re.search('str\(\) (==|!=) "', line)
if not match: if not match:
@ -314,11 +319,13 @@ class MatchCompiler:
startPos = res[0] startPos = res[0]
endPos = res[1] endPos = res[1]
text = line[startPos+1:endPos-1] text = line[startPos+1:endPos-1]
line = line[:startPos] + self._insertMatchStr(matchStrs, text) + line[endPos:] line = line[:startPos] + self._insertMatchStr(text) + line[endPos:]
return line return line
def convertFile(self, srcname, destname): def convertFile(self, srcname, destname):
self._reset()
fin = open(srcname, "rt") fin = open(srcname, "rt")
srclines = fin.readlines() srclines = fin.readlines()
fin.close() fin.close()
@ -327,31 +334,29 @@ class MatchCompiler:
header += '#include "errorlogger.h"\n' header += '#include "errorlogger.h"\n'
header += '#include <string>\n' header += '#include <string>\n'
header += '#include <cstring>\n' header += '#include <cstring>\n'
matchFunctions = []
code = '' code = ''
matchStrs = {}
for line in srclines: for line in srclines:
# Compile Token::Match and Token::simpleMatch # Compile Token::Match and Token::simpleMatch
line = self._replaceTokenMatch(matchFunctions, matchStrs, line) line = self._replaceTokenMatch(line)
# Compile Token::findsimplematch # Compile Token::findsimplematch
# NOTE: Not enabled for now since the generated code is slower than before. # NOTE: Not enabled for now since the generated code is slower than before.
# line = self._replaceTokenFindMatch(matchFunctions, matchStrs, line) # line = self._replaceTokenFindMatch(line)
# Cache plain C-strings in C++ strings # Cache plain C-strings in C++ strings
line = self._replaceCStrings(matchStrs, line) line = self._replaceCStrings(line)
code += line code += line
# Compute string list # Compute string list
stringList = '' stringList = ''
for match in sorted(matchStrs, key=matchStrs.get): for match in sorted(self._matchStrs, key=self._matchStrs.get):
stringList += 'static const std::string matchStr' + str(matchStrs[match]) + '("' + match + '");\n' stringList += 'static const std::string matchStr' + str(self._matchStrs[match]) + '("' + match + '");\n'
# Compute matchFunctions # Compute matchFunctions
strFunctions = '' strFunctions = ''
for function in matchFunctions: for function in self._matchFunctions:
strFunctions += function strFunctions += function
fout = open(destname, 'wt') fout = open(destname, 'wt')