235 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
| """ANTLR3 runtime package"""
 | |
| 
 | |
| # begin[licence]
 | |
| #
 | |
| # [The "BSD licence"]
 | |
| # Copyright (c) 2005-2012 Terence Parr
 | |
| # All rights reserved.
 | |
| #
 | |
| # Redistribution and use in source and binary forms, with or without
 | |
| # modification, are permitted provided that the following conditions
 | |
| # are met:
 | |
| # 1. Redistributions of source code must retain the above copyright
 | |
| #    notice, this list of conditions and the following disclaimer.
 | |
| # 2. Redistributions in binary form must reproduce the above copyright
 | |
| #    notice, this list of conditions and the following disclaimer in the
 | |
| #    documentation and/or other materials provided with the distribution.
 | |
| # 3. The name of the author may not be used to endorse or promote products
 | |
| #    derived from this software without specific prior written permission.
 | |
| #
 | |
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 | |
| # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
| # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
| # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
| # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
| # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
| # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
| #
 | |
| # end[licence]
 | |
| 
 | |
| 
 | |
| import sys
 | |
| import argparse
 | |
| 
 | |
| from .streams import ANTLRStringStream, ANTLRFileStream, \
 | |
|      ANTLRInputStream, CommonTokenStream
 | |
| from .tree import CommonTreeNodeStream
 | |
| 
 | |
| 
 | |
| class _Main(object):
 | |
|     def __init__(self):
 | |
|         self.stdin = sys.stdin
 | |
|         self.stdout = sys.stdout
 | |
|         self.stderr = sys.stderr
 | |
| 
 | |
| 
 | |
|     def parseArgs(self, argv):
 | |
|         argParser = argparse.ArgumentParser()
 | |
|         argParser.add_argument("--input")
 | |
|         argParser.add_argument("--interactive", "-i", action="store_true")
 | |
|         argParser.add_argument("--no-output", action="store_true")
 | |
|         argParser.add_argument("--profile", action="store_true")
 | |
|         argParser.add_argument("--hotshot", action="store_true")
 | |
|         argParser.add_argument("--port", type=int)
 | |
|         argParser.add_argument("--debug-socket", action='store_true')
 | |
|         argParser.add_argument("file", nargs='?')
 | |
| 
 | |
|         self.setupArgs(argParser)
 | |
| 
 | |
|         return argParser.parse_args(argv[1:])
 | |
| 
 | |
| 
 | |
|     def setupArgs(self, argParser):
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def execute(self, argv):
 | |
|         args = self.parseArgs(argv)
 | |
| 
 | |
|         self.setUp(args)
 | |
| 
 | |
|         if args.interactive:
 | |
|             while True:
 | |
|                 try:
 | |
|                     input_str = input(">>> ")
 | |
|                 except (EOFError, KeyboardInterrupt):
 | |
|                     self.stdout.write("\nBye.\n")
 | |
|                     break
 | |
| 
 | |
|                 inStream = ANTLRStringStream(input_str)
 | |
|                 self.parseStream(args, inStream)
 | |
| 
 | |
|         else:
 | |
|             if args.input:
 | |
|                 inStream = ANTLRStringStream(args.input)
 | |
| 
 | |
|             elif args.file and args.file != '-':
 | |
|                 inStream = ANTLRFileStream(args.file)
 | |
| 
 | |
|             else:
 | |
|                 inStream = ANTLRInputStream(self.stdin)
 | |
| 
 | |
|             if args.profile:
 | |
|                 try:
 | |
|                     import cProfile as profile
 | |
|                 except ImportError:
 | |
|                     import profile
 | |
| 
 | |
|                 profile.runctx(
 | |
|                     'self.parseStream(args, inStream)',
 | |
|                     globals(),
 | |
|                     locals(),
 | |
|                     'profile.dat'
 | |
|                     )
 | |
| 
 | |
|                 import pstats
 | |
|                 stats = pstats.Stats('profile.dat')
 | |
|                 stats.strip_dirs()
 | |
|                 stats.sort_stats('time')
 | |
|                 stats.print_stats(100)
 | |
| 
 | |
|             elif args.hotshot:
 | |
|                 import hotshot
 | |
| 
 | |
|                 profiler = hotshot.Profile('hotshot.dat')
 | |
|                 profiler.runctx(
 | |
|                     'self.parseStream(args, inStream)',
 | |
|                     globals(),
 | |
|                     locals()
 | |
|                     )
 | |
| 
 | |
|             else:
 | |
|                 self.parseStream(args, inStream)
 | |
| 
 | |
| 
 | |
|     def setUp(self, args):
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def parseStream(self, args, inStream):
 | |
|         raise NotImplementedError
 | |
| 
 | |
| 
 | |
|     def write(self, args, text):
 | |
|         if not args.no_output:
 | |
|             self.stdout.write(text)
 | |
| 
 | |
| 
 | |
|     def writeln(self, args, text):
 | |
|         self.write(args, text + '\n')
 | |
| 
 | |
| 
 | |
| class LexerMain(_Main):
 | |
|     def __init__(self, lexerClass):
 | |
|         super().__init__()
 | |
| 
 | |
|         self.lexerClass = lexerClass
 | |
| 
 | |
| 
 | |
|     def parseStream(self, args, inStream):
 | |
|         lexer = self.lexerClass(inStream)
 | |
|         for token in lexer:
 | |
|             self.writeln(args, str(token))
 | |
| 
 | |
| 
 | |
| class ParserMain(_Main):
 | |
|     def __init__(self, lexerClassName, parserClass):
 | |
|         super().__init__()
 | |
| 
 | |
|         self.lexerClassName = lexerClassName
 | |
|         self.lexerClass = None
 | |
|         self.parserClass = parserClass
 | |
| 
 | |
| 
 | |
|     def setupArgs(self, argParser):
 | |
|         argParser.add_argument("--lexer", dest="lexerClass",
 | |
|                                default=self.lexerClassName)
 | |
|         argParser.add_argument("--rule", dest="parserRule")
 | |
| 
 | |
| 
 | |
|     def setUp(self, args):
 | |
|         lexerMod = __import__(args.lexerClass)
 | |
|         self.lexerClass = getattr(lexerMod, args.lexerClass)
 | |
| 
 | |
| 
 | |
|     def parseStream(self, args, inStream):
 | |
|         kwargs = {}
 | |
|         if args.port is not None:
 | |
|             kwargs['port'] = args.port
 | |
|         if args.debug_socket:
 | |
|             kwargs['debug_socket'] = sys.stderr
 | |
| 
 | |
|         lexer = self.lexerClass(inStream)
 | |
|         tokenStream = CommonTokenStream(lexer)
 | |
|         parser = self.parserClass(tokenStream, **kwargs)
 | |
|         result = getattr(parser, args.parserRule)()
 | |
|         if result:
 | |
|             if hasattr(result, 'tree') and result.tree:
 | |
|                 self.writeln(args, result.tree.toStringTree())
 | |
|             else:
 | |
|                 self.writeln(args, repr(result))
 | |
| 
 | |
| 
 | |
| class WalkerMain(_Main):
 | |
|     def __init__(self, walkerClass):
 | |
|         super().__init__()
 | |
| 
 | |
|         self.lexerClass = None
 | |
|         self.parserClass = None
 | |
|         self.walkerClass = walkerClass
 | |
| 
 | |
| 
 | |
|     def setupArgs(self, argParser):
 | |
|         argParser.add_argument("--lexer", dest="lexerClass")
 | |
|         argParser.add_argument("--parser", dest="parserClass")
 | |
|         argParser.add_argument("--parser-rule", dest="parserRule")
 | |
|         argParser.add_argument("--rule", dest="walkerRule")
 | |
| 
 | |
| 
 | |
|     def setUp(self, args):
 | |
|         lexerMod = __import__(args.lexerClass)
 | |
|         self.lexerClass = getattr(lexerMod, args.lexerClass)
 | |
|         parserMod = __import__(args.parserClass)
 | |
|         self.parserClass = getattr(parserMod, args.parserClass)
 | |
| 
 | |
| 
 | |
|     def parseStream(self, args, inStream):
 | |
|         lexer = self.lexerClass(inStream)
 | |
|         tokenStream = CommonTokenStream(lexer)
 | |
|         parser = self.parserClass(tokenStream)
 | |
|         result = getattr(parser, args.parserRule)()
 | |
|         if result:
 | |
|             assert hasattr(result, 'tree'), "Parser did not return an AST"
 | |
|             nodeStream = CommonTreeNodeStream(result.tree)
 | |
|             nodeStream.setTokenStream(tokenStream)
 | |
|             walker = self.walkerClass(nodeStream)
 | |
|             result = getattr(walker, args.walkerRule)()
 | |
|             if result:
 | |
|                 if hasattr(result, 'tree'):
 | |
|                     self.writeln(args, result.tree.toStringTree())
 | |
|                 else:
 | |
|                     self.writeln(args, repr(result))
 |