1"""ANTLR3 runtime package"""
2
3# begin[licence]
4#
5# [The "BSD licence"]
6# Copyright (c) 2005-2012 Terence Parr
7# All rights reserved.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17# 3. The name of the author may not be used to endorse or promote products
18#    derived from this software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30#
31# end[licence]
32
33
34import sys
35import argparse
36
37from .streams import ANTLRStringStream, ANTLRFileStream, \
38     ANTLRInputStream, CommonTokenStream
39from .tree import CommonTreeNodeStream
40
41
42class _Main(object):
43    def __init__(self):
44        self.stdin = sys.stdin
45        self.stdout = sys.stdout
46        self.stderr = sys.stderr
47
48
49    def parseArgs(self, argv):
50        argParser = argparse.ArgumentParser()
51        argParser.add_argument("--input")
52        argParser.add_argument("--interactive", "-i", action="store_true")
53        argParser.add_argument("--no-output", action="store_true")
54        argParser.add_argument("--profile", action="store_true")
55        argParser.add_argument("--hotshot", action="store_true")
56        argParser.add_argument("--port", type=int)
57        argParser.add_argument("--debug-socket", action='store_true')
58        argParser.add_argument("file", nargs='?')
59
60        self.setupArgs(argParser)
61
62        return argParser.parse_args(argv[1:])
63
64
65    def setupArgs(self, argParser):
66        pass
67
68
69    def execute(self, argv):
70        args = self.parseArgs(argv)
71
72        self.setUp(args)
73
74        if args.interactive:
75            while True:
76                try:
77                    input_str = input(">>> ")
78                except (EOFError, KeyboardInterrupt):
79                    self.stdout.write("\nBye.\n")
80                    break
81
82                inStream = ANTLRStringStream(input_str)
83                self.parseStream(args, inStream)
84
85        else:
86            if args.input:
87                inStream = ANTLRStringStream(args.input)
88
89            elif args.file and args.file != '-':
90                inStream = ANTLRFileStream(args.file)
91
92            else:
93                inStream = ANTLRInputStream(self.stdin)
94
95            if args.profile:
96                try:
97                    import cProfile as profile
98                except ImportError:
99                    import profile
100
101                profile.runctx(
102                    'self.parseStream(args, inStream)',
103                    globals(),
104                    locals(),
105                    'profile.dat'
106                    )
107
108                import pstats
109                stats = pstats.Stats('profile.dat')
110                stats.strip_dirs()
111                stats.sort_stats('time')
112                stats.print_stats(100)
113
114            elif args.hotshot:
115                import hotshot
116
117                profiler = hotshot.Profile('hotshot.dat')
118                profiler.runctx(
119                    'self.parseStream(args, inStream)',
120                    globals(),
121                    locals()
122                    )
123
124            else:
125                self.parseStream(args, inStream)
126
127
128    def setUp(self, args):
129        pass
130
131
132    def parseStream(self, args, inStream):
133        raise NotImplementedError
134
135
136    def write(self, args, text):
137        if not args.no_output:
138            self.stdout.write(text)
139
140
141    def writeln(self, args, text):
142        self.write(args, text + '\n')
143
144
145class LexerMain(_Main):
146    def __init__(self, lexerClass):
147        super().__init__()
148
149        self.lexerClass = lexerClass
150
151
152    def parseStream(self, args, inStream):
153        lexer = self.lexerClass(inStream)
154        for token in lexer:
155            self.writeln(args, str(token))
156
157
158class ParserMain(_Main):
159    def __init__(self, lexerClassName, parserClass):
160        super().__init__()
161
162        self.lexerClassName = lexerClassName
163        self.lexerClass = None
164        self.parserClass = parserClass
165
166
167    def setupArgs(self, argParser):
168        argParser.add_argument("--lexer", dest="lexerClass",
169                               default=self.lexerClassName)
170        argParser.add_argument("--rule", dest="parserRule")
171
172
173    def setUp(self, args):
174        lexerMod = __import__(args.lexerClass)
175        self.lexerClass = getattr(lexerMod, args.lexerClass)
176
177
178    def parseStream(self, args, inStream):
179        kwargs = {}
180        if args.port is not None:
181            kwargs['port'] = args.port
182        if args.debug_socket:
183            kwargs['debug_socket'] = sys.stderr
184
185        lexer = self.lexerClass(inStream)
186        tokenStream = CommonTokenStream(lexer)
187        parser = self.parserClass(tokenStream, **kwargs)
188        result = getattr(parser, args.parserRule)()
189        if result:
190            if hasattr(result, 'tree') and result.tree:
191                self.writeln(args, result.tree.toStringTree())
192            else:
193                self.writeln(args, repr(result))
194
195
196class WalkerMain(_Main):
197    def __init__(self, walkerClass):
198        super().__init__()
199
200        self.lexerClass = None
201        self.parserClass = None
202        self.walkerClass = walkerClass
203
204
205    def setupArgs(self, argParser):
206        argParser.add_argument("--lexer", dest="lexerClass")
207        argParser.add_argument("--parser", dest="parserClass")
208        argParser.add_argument("--parser-rule", dest="parserRule")
209        argParser.add_argument("--rule", dest="walkerRule")
210
211
212    def setUp(self, args):
213        lexerMod = __import__(args.lexerClass)
214        self.lexerClass = getattr(lexerMod, args.lexerClass)
215        parserMod = __import__(args.parserClass)
216        self.parserClass = getattr(parserMod, args.parserClass)
217
218
219    def parseStream(self, args, inStream):
220        lexer = self.lexerClass(inStream)
221        tokenStream = CommonTokenStream(lexer)
222        parser = self.parserClass(tokenStream)
223        result = getattr(parser, args.parserRule)()
224        if result:
225            assert hasattr(result, 'tree'), "Parser did not return an AST"
226            nodeStream = CommonTreeNodeStream(result.tree)
227            nodeStream.setTokenStream(tokenStream)
228            walker = self.walkerClass(nodeStream)
229            result = getattr(walker, args.walkerRule)()
230            if result:
231                if hasattr(result, 'tree'):
232                    self.writeln(args, result.tree.toStringTree())
233                else:
234                    self.writeln(args, repr(result))
235