diff --git a/fsabuilder/morfeuszbuilder/caseconv/__init__.py b/fsabuilder/morfeuszbuilder/segrules/__init__.py index e69de29..e69de29 100644 --- a/fsabuilder/morfeuszbuilder/caseconv/__init__.py +++ b/fsabuilder/morfeuszbuilder/segrules/__init__.py diff --git a/fsabuilder/morfeuszbuilder/segrules/preprocessor.py b/fsabuilder/morfeuszbuilder/segrules/preprocessor.py new file mode 100644 index 0000000..153ba7c --- /dev/null +++ b/fsabuilder/morfeuszbuilder/segrules/preprocessor.py @@ -0,0 +1,101 @@ +''' +Created on 23 sty 2014 + +@author: mlenart +''' +import re +from pyparsing import * + +identifier = Word(alphas, bodyChars=alphanums+'_') +define = Keyword('#define').suppress() + identifier + Optional(Suppress('(') + identifier + Suppress(')')) + restOfLine + LineEnd() + StringEnd() +ifdef = Keyword('#ifdef').suppress() + identifier + LineEnd() + StringEnd() +endif = Keyword('#endif').suppress() + LineEnd() + StringEnd() + +class NonArgDefine(object): + + def __init__(self, name, val): + self.name = name + self.val = val + + def hasArg(self): + return False + +class ArgDefine(object): + + def __init__(self, name, arg, val): + self.name = name + self.arg = arg + self.val = val + + def hasArg(self): + return True + + def __str__(self): + return '%s(%s) %s' % (self.name, self.arg, self.val) + +class PreprocessorException(Exception): + + def __init__(self, msg, line): + pass + +def _tryToSubstituteArgDefine(s, t, defines): + defineName = t[0] + substituteValue = t[1] + if defineName in defines and defines[defineName].hasArg(): + define = defines[defineName] + return re.sub(r'\b%s\b' % define.arg, substituteValue, define.val) + elif defineName in defines: + return '%s ( %s )' % (defines[defineName].val, substituteValue) + else: + return ' '.join(t) + +def _tryToSubstituteNonArgDefine(s, t, defines): + defineName = t[0] + + if defineName in defines and not defines[defineName].hasArg(): + return defines[defineName].val + else: + return defineName + +def _processLine(line, defines): + if line.strip(): + + rule = Forward() + defineInstance = Forward() + localId = identifier.copy() + + rule << OneOrMore(localId ^ defineInstance ^ Word('*|+?')) + defineInstance << localId + Suppress('(') + rule + Suppress(')') + + rule.setParseAction(lambda s, l, t: ' '.join(t)) + defineInstance.setParseAction(lambda s, l, t: _tryToSubstituteArgDefine(s, t, defines)) + localId.setParseAction(lambda s, l, t: _tryToSubstituteNonArgDefine(s, t, defines)) + return rule.parseString(line, parseAll=True)[0] + else: + return line + +def preprocess(inputLines, defs): + defines = {} + ifdefsStack = [] + for lineNum, line in enumerate(inputLines, start=1): + if line.startswith('#define'): + try: + parsedDefine = list(define.parseString(line)) + if len(parsedDefine) == 2: + name, val = parsedDefine + defines[name] = NonArgDefine(name, val) + else: + name, arg, val = parsedDefine + localDefines = defines.copy() + localDefines[arg] = NonArgDefine(arg, arg) + val = _processLine(val, localDefines) + defines[name] = ArgDefine(name, arg, val) + except: + pass + elif line.startswith('#ifdef'): + name = ifdef.parseString(line)[0] + ifdefsStack.append(name) + elif line.startswith('#endif'): + ifdefsStack.pop() + elif len(ifdefsStack) == 0 or all(map(lambda name: name in defs, ifdefsStack)): + yield _processLine(line, defines) diff --git a/fsabuilder/morfeuszbuilder/segrules/test.py b/fsabuilder/morfeuszbuilder/segrules/test.py new file mode 100644 index 0000000..0922af5 --- /dev/null +++ b/fsabuilder/morfeuszbuilder/segrules/test.py @@ -0,0 +1,36 @@ +''' +Created on 24 sty 2014 + +@author: mlenart +''' + +import preprocessor + +if __name__ == '__main__': + text = ''' +dupa +#define asd XXX +#define X(x) a x b +#define Y(x) X(x) c +#define B(x) X(x) +#define Z(x) Y(X(x)) d +#define AB(asd) dupa asd dupa +Y(Z(a) b X(c) Y(d)) +#ifdef extra +asdfasa +#ifdef extra +asdfasdfasdfa +#endif +#ifdef superextra +aaaa asd +#endif +#endif + +#ifdef superextra +asdfasdfada +#endif + +AB(x) +''' + for line in preprocessor.preprocess(text.split('\n'), ['extra', 'superextra']): + print line \ No newline at end of file diff --git a/fsabuilder/morfeuszbuilder/caseconv/CaseFolding.txt b/fsabuilder/morfeuszbuilder/utils/caseconv/CaseFolding.txt index 7c702d5..7c702d5 100644 --- a/fsabuilder/morfeuszbuilder/caseconv/CaseFolding.txt +++ b/fsabuilder/morfeuszbuilder/utils/caseconv/CaseFolding.txt diff --git a/fsabuilder/morfeuszbuilder/caseconv/UnicodeData.txt b/fsabuilder/morfeuszbuilder/utils/caseconv/UnicodeData.txt index 9fffa71..9fffa71 100644 --- a/fsabuilder/morfeuszbuilder/caseconv/UnicodeData.txt +++ b/fsabuilder/morfeuszbuilder/utils/caseconv/UnicodeData.txt diff --git a/fsabuilder/morfeuszbuilder/input/__init__.py b/fsabuilder/morfeuszbuilder/utils/caseconv/__init__.py index e69de29..e69de29 100644 --- a/fsabuilder/morfeuszbuilder/input/__init__.py +++ b/fsabuilder/morfeuszbuilder/utils/caseconv/__init__.py diff --git a/fsabuilder/morfeuszbuilder/caseconv/generate.py b/fsabuilder/morfeuszbuilder/utils/caseconv/generate.py index c3698f5..c3698f5 100644 --- a/fsabuilder/morfeuszbuilder/caseconv/generate.py +++ b/fsabuilder/morfeuszbuilder/utils/caseconv/generate.py