grammar.py revision 13663:9b64aeabf9a5
110037SARM gem5 Developers# Copyright (c) 2006-2011 Nathan Binkert <nate@binkert.org> 210037SARM gem5 Developers# All rights reserved. 310037SARM gem5 Developers# 410037SARM gem5 Developers# Redistribution and use in source and binary forms, with or without 510037SARM gem5 Developers# modification, are permitted provided that the following conditions are 610037SARM gem5 Developers# met: redistributions of source code must retain the above copyright 710037SARM gem5 Developers# notice, this list of conditions and the following disclaimer; 810037SARM gem5 Developers# redistributions in binary form must reproduce the above copyright 910037SARM gem5 Developers# notice, this list of conditions and the following disclaimer in the 1010037SARM gem5 Developers# documentation and/or other materials provided with the distribution; 1110037SARM gem5 Developers# neither the name of the copyright holders nor the names of its 1210037SARM gem5 Developers# contributors may be used to endorse or promote products derived from 1310037SARM gem5 Developers# this software without specific prior written permission. 1410037SARM gem5 Developers# 1510037SARM gem5 Developers# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1610037SARM gem5 Developers# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1710037SARM gem5 Developers# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1810037SARM gem5 Developers# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1910037SARM gem5 Developers# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2010037SARM gem5 Developers# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2110037SARM gem5 Developers# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2210037SARM gem5 Developers# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2310037SARM gem5 Developers# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2410037SARM gem5 Developers# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2510037SARM gem5 Developers# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2610037SARM gem5 Developers 2710037SARM gem5 Developersimport os 2810037SARM gem5 Developers 2910037SARM gem5 Developersimport ply.lex 3010037SARM gem5 Developersimport ply.yacc 3110037SARM gem5 Developers 3210037SARM gem5 Developersclass ParseError(Exception): 3310037SARM gem5 Developers def __init__(self, message, token=None): 3410037SARM gem5 Developers Exception.__init__(self, message) 3510037SARM gem5 Developers self.token = token 3610037SARM gem5 Developers 3710037SARM gem5 Developersclass Grammar(object): 3810037SARM gem5 Developers def setupLexerFactory(self, **kwargs): 3910037SARM gem5 Developers if 'module' in kwargs: 4010037SARM gem5 Developers raise AttributeError("module is an illegal attribute") 4110037SARM gem5 Developers self.lex_kwargs = kwargs 4210037SARM gem5 Developers 4310037SARM gem5 Developers def setupParserFactory(self, **kwargs): 4410037SARM gem5 Developers if 'module' in kwargs: 4510037SARM gem5 Developers raise AttributeError("module is an illegal attribute") 4610037SARM gem5 Developers 4710037SARM gem5 Developers if 'output' in kwargs: 4810037SARM gem5 Developers dir,tab = os.path.split(output) 4910037SARM gem5 Developers if not tab.endswith('.py'): 5010037SARM gem5 Developers raise AttributeError('The output file must end with .py') 5110037SARM gem5 Developers kwargs['outputdir'] = dir 5210037SARM gem5 Developers kwargs['tabmodule'] = tab[:-3] 5310037SARM gem5 Developers 5410037SARM gem5 Developers self.yacc_kwargs = kwargs 5510037SARM gem5 Developers 5610037SARM gem5 Developers def __getattr__(self, attr): 5710037SARM gem5 Developers if attr == 'lexers': 5810037SARM gem5 Developers self.lexers = [] 5910037SARM gem5 Developers return self.lexers 6010037SARM gem5 Developers 6110037SARM gem5 Developers if attr == 'lex_kwargs': 6210037SARM gem5 Developers self.setupLexerFactory() 6310037SARM gem5 Developers return self.lex_kwargs 6410037SARM gem5 Developers 6510037SARM gem5 Developers if attr == 'yacc_kwargs': 6610037SARM gem5 Developers self.setupParserFactory() 6710037SARM gem5 Developers return self.yacc_kwargs 6810037SARM gem5 Developers 6910037SARM gem5 Developers if attr == 'lex': 7010037SARM gem5 Developers self.lex = ply.lex.lex(module=self, **self.lex_kwargs) 7110037SARM gem5 Developers return self.lex 7210037SARM gem5 Developers 7310037SARM gem5 Developers if attr == 'yacc': 7410037SARM gem5 Developers self.yacc = ply.yacc.yacc(module=self, **self.yacc_kwargs) 7510037SARM gem5 Developers return self.yacc 7610037SARM gem5 Developers 7710037SARM gem5 Developers if attr == 'current_lexer': 7810037SARM gem5 Developers if not self.lexers: 7910037SARM gem5 Developers return None 8010037SARM gem5 Developers return self.lexers[-1][0] 8110037SARM gem5 Developers 8210037SARM gem5 Developers if attr == 'current_source': 8310037SARM gem5 Developers if not self.lexers: 8410037SARM gem5 Developers return '<none>' 8510037SARM gem5 Developers return self.lexers[-1][1] 8610037SARM gem5 Developers 8710037SARM gem5 Developers if attr == 'current_line': 8810037SARM gem5 Developers if not self.lexers: 8910037SARM gem5 Developers return -1 9010037SARM gem5 Developers return self.current_lexer.lineno 9110037SARM gem5 Developers 9210037SARM gem5 Developers raise AttributeError( 9310037SARM gem5 Developers "'%s' object has no attribute '%s'" % (type(self), attr)) 9410037SARM gem5 Developers 9510037SARM gem5 Developers def parse_string(self, data, source='<string>', debug=None, tracking=0): 9610037SARM gem5 Developers if not isinstance(data, basestring): 9710037SARM gem5 Developers raise AttributeError( 9810037SARM gem5 Developers "argument must be a string, was '%s'" % type(f)) 9910037SARM gem5 Developers 10010037SARM gem5 Developers import new 10110037SARM gem5 Developers lexer = self.lex.clone() 10210037SARM gem5 Developers lexer.input(data) 10310037SARM gem5 Developers self.lexers.append((lexer, source)) 10410037SARM gem5 Developers dict = { 10510037SARM gem5 Developers 'productions' : self.yacc.productions, 10610037SARM gem5 Developers 'action' : self.yacc.action, 10710037SARM gem5 Developers 'goto' : self.yacc.goto, 10810037SARM gem5 Developers 'errorfunc' : self.yacc.errorfunc, 10910037SARM gem5 Developers } 11010037SARM gem5 Developers parser = new.instance(ply.yacc.LRParser, dict) 11110037SARM gem5 Developers result = parser.parse(lexer=lexer, debug=debug, tracking=tracking) 11210037SARM gem5 Developers self.lexers.pop() 11310037SARM gem5 Developers return result 11410037SARM gem5 Developers 11510037SARM gem5 Developers def parse_file(self, f, **kwargs): 11610037SARM gem5 Developers if isinstance(f, basestring): 11710037SARM gem5 Developers source = f 11810037SARM gem5 Developers f = file(f, 'r') 11910037SARM gem5 Developers elif isinstance(f, file): 12010037SARM gem5 Developers source = f.name 12110037SARM gem5 Developers else: 12210037SARM gem5 Developers raise AttributeError( 12310037SARM gem5 Developers "argument must be either a string or file, was '%s'" % type(f)) 12410037SARM gem5 Developers 12510037SARM gem5 Developers return self.parse_string(f.read(), source, **kwargs) 12610037SARM gem5 Developers 12710037SARM gem5 Developers def p_error(self, t): 12810037SARM gem5 Developers if t: 12910037SARM gem5 Developers msg = "Syntax error at %s:%d:%d\n>>%s<<" % \ 13010037SARM gem5 Developers (self.current_source, t.lineno, t.lexpos + 1, t.value) 13110037SARM gem5 Developers else: 13210037SARM gem5 Developers msg = "Syntax error at end of %s" % (self.current_source, ) 13310037SARM gem5 Developers raise ParseError(msg, t) 13410037SARM gem5 Developers 13510037SARM gem5 Developers def t_error(self, t): 13610037SARM gem5 Developers msg = "Illegal character %s @ %d:%d" % \ 13710037SARM gem5 Developers (`t.value[0]`, t.lineno, t.lexpos) 13810037SARM gem5 Developers raise ParseError(msg, t) 13910037SARM gem5 Developers