1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport unittest
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport imp
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport os
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport errno
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport sys
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport glob
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport re
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport tempfile
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport shutil
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport inspect
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport hashlib
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverfrom distutils.errors import *
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport antlr3
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverdef unlink(path):
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    try:
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        os.unlink(path)
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    except OSError, exc:
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if exc.errno != errno.ENOENT:
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            raise
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass GrammarCompileError(Exception):
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  """Grammar failed to compile."""
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  pass
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# At least on MacOSX tempdir (/tmp) is a symlink. It's sometimes dereferences,
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# sometimes not, breaking the inspect.getmodule() function.
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvertestbasedir = os.path.join(
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    os.path.realpath(tempfile.gettempdir()),
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    'antlr3-test')
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass BrokenTest(unittest.TestCase.failureException):
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def __repr__(self):
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        name, reason = self.args
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return '%s: %s: %s works now' % (
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            (self.__class__.__name__, name, reason))
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverdef broken(reason, *exceptions):
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    '''Indicates a failing (or erroneous) test case fails that should succeed.
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    If the test fails with an exception, list the exception type in args'''
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def wrapper(test_method):
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        def replacement(*args, **kwargs):
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            try:
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                test_method(*args, **kwargs)
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            except exceptions or unittest.TestCase.failureException:
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                pass
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            else:
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                raise BrokenTest(test_method.__name__, reason)
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        replacement.__doc__ = test_method.__doc__
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        replacement.__name__ = 'XXX_' + test_method.__name__
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        replacement.todo = reason
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return replacement
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return wrapper
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
60324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverdependencyCache = {}
61324c4644fee44b9898524c09511bd33c3f12e2dfBen GruvercompileErrorCache = {}
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# setup java CLASSPATH
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverif 'CLASSPATH' not in os.environ:
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    cp = []
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    baseDir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    libDir = os.path.join(baseDir, 'lib')
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    jar = os.path.join(libDir, 'ST-4.0.1.jar')
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if not os.path.isfile(jar):
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        raise DistutilsFileError(
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            "Missing file '%s'. Grap it from a distribution package."
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            % jar,
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            )
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    cp.append(jar)
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    jar = os.path.join(libDir, 'antlr-2.7.7.jar')
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if not os.path.isfile(jar):
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        raise DistutilsFileError(
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            "Missing file '%s'. Grap it from a distribution package."
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            % jar,
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            )
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    cp.append(jar)
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    jar = os.path.join(libDir, 'junit-4.2.jar')
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if not os.path.isfile(jar):
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        raise DistutilsFileError(
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            "Missing file '%s'. Grap it from a distribution package."
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            % jar,
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            )
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    cp.append(jar)
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    cp.append(os.path.join(baseDir, 'runtime', 'Python', 'build'))
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    classpath = '-cp "' + ':'.join([os.path.abspath(p) for p in cp]) + '"'
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverelse:
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    classpath = ''
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass ANTLRTest(unittest.TestCase):
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def __init__(self, *args, **kwargs):
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        unittest.TestCase.__init__(self, *args, **kwargs)
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.moduleName = os.path.splitext(os.path.basename(sys.modules[self.__module__].__file__))[0]
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.className = self.__class__.__name__
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self._baseDir = None
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.lexerModule = None
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.parserModule = None
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.grammarName = None
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.grammarType = None
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def assertListEqual(self, a, b):
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if a == b:
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        import difflib
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        a = [str(l) + '\n' for l in a]
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        b = [str(l) + '\n' for l in b]
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        raise AssertionError(''.join(difflib.unified_diff(a, b)))
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @property
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def baseDir(self):
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if self._baseDir is None:
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            testName = 'unknownTest'
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            for frame in inspect.stack():
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                code = frame[0].f_code
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                codeMod = inspect.getmodule(code)
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if codeMod is None:
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    continue
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                # skip frames not in requested module
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if codeMod is not sys.modules[self.__module__]:
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    continue
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                # skip some unwanted names
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if code.co_name in ('nextToken', '<module>'):
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    continue
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if code.co_name.startswith('test'):
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    testName = code.co_name
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    break
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self._baseDir = os.path.join(
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                testbasedir,
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                self.moduleName, self.className, testName)
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if not os.path.isdir(self._baseDir):
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                os.makedirs(self._baseDir)
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return self._baseDir
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def _invokeantlr(self, dir, file, options, javaOptions=''):
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        cmd = 'cd %s; java %s %s org.antlr.Tool -o . %s %s 2>&1' % (
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            dir, javaOptions, classpath, options, file
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            )
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp = os.popen(cmd)
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        output = ''
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        failed = False
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        for line in fp:
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            output += line
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if line.startswith('error('):
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                failed = True
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        rc = fp.close()
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if rc is not None:
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            failed = True
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if failed:
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            raise GrammarCompileError(
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                "Failed to compile grammar '%s':\n%s\n\n" % (file, cmd)
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                + output
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                )
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def compileGrammar(self, grammarName=None, options='', javaOptions=''):
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarName is None:
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            grammarName = self.moduleName + '.g'
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self._baseDir = os.path.join(
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            testbasedir,
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.moduleName)
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if not os.path.isdir(self._baseDir):
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            os.makedirs(self._baseDir)
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if self.grammarName is None:
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.grammarName = os.path.splitext(grammarName)[0]
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammarPath = os.path.join(os.path.dirname(os.path.abspath(__file__)), grammarName)
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # get type and name from first grammar line
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammar = open(grammarPath, 'r').read()
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        m = re.match(r'\s*((lexer|parser|tree)\s+|)grammar\s+(\S+);', grammar, re.MULTILINE)
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        assert m is not None, grammar
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.grammarType = m.group(2)
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if self.grammarType is None:
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.grammarType = 'combined'
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if self.grammarType is None:
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            assert self.grammarType in ('lexer', 'parser', 'tree', 'combined'), self.grammarType
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # don't try to rebuild grammar, if it already failed
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarName in compileErrorCache:
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        try:
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #     # get dependencies from antlr
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #     if grammarName in dependencyCache:
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         dependencies = dependencyCache[grammarName]
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #     else:
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         dependencies = []
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         cmd = ('cd %s; java %s %s org.antlr.Tool -o . -depend %s 2>&1'
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                % (self.baseDir, javaOptions, classpath, grammarPath))
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         output = ""
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         failed = False
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         fp = os.popen(cmd)
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         for line in fp:
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             output += line
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             if line.startswith('error('):
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 failed = True
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             elif ':' in line:
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 a, b = line.strip().split(':', 1)
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 dependencies.append(
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                     (os.path.join(self.baseDir, a.strip()),
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                      [os.path.join(self.baseDir, b.strip())])
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                     )
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         rc = fp.close()
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         if rc is not None:
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             failed = True
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         if failed:
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             raise GrammarCompileError(
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 "antlr -depend failed with code %s on grammar '%s':\n\n"
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 % (rc, grammarName)
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 + cmd
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 + "\n"
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 + output
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 )
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         # add dependencies to my .stg files
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         templateDir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'tool', 'src', 'main', 'resources', 'org', 'antlr', 'codegen', 'templates', 'Python'))
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         templates = glob.glob(os.path.join(templateDir, '*.stg'))
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         for dst, src in dependencies:
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             src.extend(templates)
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         dependencyCache[grammarName] = dependencies
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #     rebuild = False
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #     for dest, sources in dependencies:
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         if not os.path.isfile(dest):
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             rebuild = True
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             break
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         for source in sources:
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #             if os.path.getmtime(source) > os.path.getmtime(dest):
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 rebuild = True
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #                 break
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #     if rebuild:
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #         self._invokeantlr(self.baseDir, grammarPath, options, javaOptions)
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self._invokeantlr(self.baseDir, grammarPath, options, javaOptions)
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        except:
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            # mark grammar as broken
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            compileErrorCache[grammarName] = True
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            raise
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def lexerClass(self, base):
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        """Optionally build a subclass of generated lexer class"""
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return base
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def parserClass(self, base):
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        """Optionally build a subclass of generated parser class"""
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return base
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def walkerClass(self, base):
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        """Optionally build a subclass of generated walker class"""
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return base
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def __load_module(self, name):
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        modFile, modPathname, modDescription \
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                 = imp.find_module(name, [self.baseDir])
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return imp.load_module(
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            name, modFile, modPathname, modDescription
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            )
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def getLexer(self, *args, **kwargs):
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        """Build lexer instance. Arguments are passed to lexer.__init__()."""
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if self.grammarType == 'lexer':
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.lexerModule = self.__load_module(self.grammarName)
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            cls = getattr(self.lexerModule, self.grammarName)
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        else:
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.lexerModule = self.__load_module(self.grammarName + 'Lexer')
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            cls = getattr(self.lexerModule, self.grammarName + 'Lexer')
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        cls = self.lexerClass(cls)
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        lexer = cls(*args, **kwargs)
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return lexer
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def getParser(self, *args, **kwargs):
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        """Build parser instance. Arguments are passed to parser.__init__()."""
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if self.grammarType == 'parser':
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.lexerModule = self.__load_module(self.grammarName)
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            cls = getattr(self.lexerModule, self.grammarName)
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        else:
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            self.parserModule = self.__load_module(self.grammarName + 'Parser')
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            cls = getattr(self.parserModule, self.grammarName + 'Parser')
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        cls = self.parserClass(cls)
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        parser = cls(*args, **kwargs)
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return parser
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def getWalker(self, *args, **kwargs):
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        """Build walker instance. Arguments are passed to walker.__init__()."""
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self.walkerModule = self.__load_module(self.grammarName + 'Walker')
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        cls = getattr(self.walkerModule, self.grammarName + 'Walker')
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        cls = self.walkerClass(cls)
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        walker = cls(*args, **kwargs)
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return walker
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def writeInlineGrammar(self, grammar):
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # Create a unique ID for this test and use it as the grammar name,
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # to avoid class name reuse. This kinda sucks. Need to find a way so
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # tests can use the same grammar name without messing up the namespace.
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # Well, first I should figure out what the exact problem is...
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        id = hashlib.md5(self.baseDir).hexdigest()[-8:]
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammar = grammar.replace('$TP', 'TP' + id)
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammar = grammar.replace('$T', 'T' + id)
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # get type and name from first grammar line
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        m = re.match(r'\s*((lexer|parser|tree)\s+|)grammar\s+(\S+);', grammar, re.MULTILINE)
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        assert m is not None, grammar
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammarType = m.group(2)
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarType is None:
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            grammarType = 'combined'
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammarName = m.group(3)
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        assert grammarType in ('lexer', 'parser', 'tree', 'combined'), grammarType
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammarPath = os.path.join(self.baseDir, grammarName + '.g')
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # dump temp grammar file
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp = open(grammarPath, 'w')
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp.write(grammar)
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp.close()
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return grammarName, grammarPath, grammarType
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def writeFile(self, name, contents):
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        testDir = os.path.dirname(os.path.abspath(__file__))
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        path = os.path.join(self.baseDir, name)
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp = open(path, 'w')
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp.write(contents)
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        fp.close()
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return path
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def compileInlineGrammar(self, grammar, options='', javaOptions='',
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                             returnModule=False):
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # write grammar file
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammarName, grammarPath, grammarType = self.writeInlineGrammar(grammar)
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        # compile it
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        self._invokeantlr(
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            os.path.dirname(grammarPath),
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            os.path.basename(grammarPath),
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            options,
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            javaOptions
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            )
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarType == 'combined':
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            lexerMod = self.__load_module(grammarName + 'Lexer')
411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            parserMod = self.__load_module(grammarName + 'Parser')
412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if returnModule:
413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return lexerMod, parserMod
414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            lexerCls = getattr(lexerMod, grammarName + 'Lexer')
416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            lexerCls = self.lexerClass(lexerCls)
417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            parserCls = getattr(parserMod, grammarName + 'Parser')
418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            parserCls = self.parserClass(parserCls)
419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return lexerCls, parserCls
421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarType == 'lexer':
423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            lexerMod = self.__load_module(grammarName)
424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if returnModule:
425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return lexerMod
426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            lexerCls = getattr(lexerMod, grammarName)
428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            lexerCls = self.lexerClass(lexerCls)
429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return lexerCls
431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarType == 'parser':
433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            parserMod = self.__load_module(grammarName)
434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if returnModule:
435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return parserMod
436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            parserCls = getattr(parserMod, grammarName)
438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            parserCls = self.parserClass(parserCls)
439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return parserCls
441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if grammarType == 'tree':
443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            walkerMod = self.__load_module(grammarName)
444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if returnModule:
445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return walkerMod
446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            walkerCls = getattr(walkerMod, grammarName)
448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            walkerCls = self.walkerClass(walkerCls)
449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return walkerCls
451