parser.py revision 10964
113511Sgabeblack@google.com# Copyright (c) 2009 The Hewlett-Packard Development Company
213511Sgabeblack@google.com# All rights reserved.
313511Sgabeblack@google.com#
413511Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without
513511Sgabeblack@google.com# modification, are permitted provided that the following conditions are
613511Sgabeblack@google.com# met: redistributions of source code must retain the above copyright
713511Sgabeblack@google.com# notice, this list of conditions and the following disclaimer;
813511Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright
913511Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the
1013511Sgabeblack@google.com# documentation and/or other materials provided with the distribution;
1113511Sgabeblack@google.com# neither the name of the copyright holders nor the names of its
1213511Sgabeblack@google.com# contributors may be used to endorse or promote products derived from
1313511Sgabeblack@google.com# this software without specific prior written permission.
1413511Sgabeblack@google.com#
1513511Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1613511Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1713511Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1813511Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1913511Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2013511Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2113511Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2213511Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2313511Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2413511Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2513511Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2613511Sgabeblack@google.com#
2713511Sgabeblack@google.com# Authors: Nathan Binkert
2813511Sgabeblack@google.com
2913511Sgabeblack@google.comimport os.path
3013511Sgabeblack@google.comimport re
3113511Sgabeblack@google.comimport sys
3213511Sgabeblack@google.com
3313511Sgabeblack@google.comfrom m5.util import code_formatter
3413511Sgabeblack@google.comfrom m5.util.grammar import Grammar, ParseError
3513511Sgabeblack@google.com
3613511Sgabeblack@google.comimport slicc.ast as ast
3713511Sgabeblack@google.comimport slicc.util as util
3813511Sgabeblack@google.comfrom slicc.symbols import SymbolTable
3913511Sgabeblack@google.com
4013511Sgabeblack@google.comclass SLICC(Grammar):
4113511Sgabeblack@google.com    def __init__(self, filename, base_dir, verbose=False, traceback=False, **kwargs):
4213511Sgabeblack@google.com        self.protocol = None
4313511Sgabeblack@google.com        self.traceback = traceback
4413511Sgabeblack@google.com        self.verbose = verbose
4513511Sgabeblack@google.com        self.symtab = SymbolTable(self)
4613511Sgabeblack@google.com        self.base_dir = base_dir
4713511Sgabeblack@google.com
4813511Sgabeblack@google.com        try:
4913511Sgabeblack@google.com            self.decl_list = self.parse_file(filename, **kwargs)
5013511Sgabeblack@google.com        except ParseError, e:
5113511Sgabeblack@google.com            if not self.traceback:
5213511Sgabeblack@google.com                sys.exit(str(e))
5313511Sgabeblack@google.com            raise
5413511Sgabeblack@google.com
5513511Sgabeblack@google.com    def currentLocation(self):
5613511Sgabeblack@google.com        return util.Location(self.current_source, self.current_line,
5713511Sgabeblack@google.com                             no_warning=not self.verbose)
5813511Sgabeblack@google.com
5913511Sgabeblack@google.com    def codeFormatter(self, *args, **kwargs):
6013511Sgabeblack@google.com        code = code_formatter(*args, **kwargs)
6113511Sgabeblack@google.com        code['protocol'] = self.protocol
6213511Sgabeblack@google.com        return code
6313511Sgabeblack@google.com
6413511Sgabeblack@google.com    def process(self):
6513511Sgabeblack@google.com        self.decl_list.findMachines()
6613511Sgabeblack@google.com        self.decl_list.generate()
6713511Sgabeblack@google.com
6813511Sgabeblack@google.com    def writeCodeFiles(self, code_path, includes):
6913511Sgabeblack@google.com        self.symtab.writeCodeFiles(code_path, includes)
7013511Sgabeblack@google.com
7113511Sgabeblack@google.com    def writeHTMLFiles(self, html_path):
7213511Sgabeblack@google.com        self.symtab.writeHTMLFiles(html_path)
7313511Sgabeblack@google.com
7413511Sgabeblack@google.com    def files(self):
7513511Sgabeblack@google.com        f = set([
7613511Sgabeblack@google.com            'MachineType.cc',
7713511Sgabeblack@google.com            'MachineType.hh',
7813511Sgabeblack@google.com            'Types.hh' ])
7913511Sgabeblack@google.com
8013511Sgabeblack@google.com        f |= self.decl_list.files()
8113511Sgabeblack@google.com
8213511Sgabeblack@google.com        return f
8313511Sgabeblack@google.com
8413511Sgabeblack@google.com    t_ignore = '\t '
8513511Sgabeblack@google.com
8613511Sgabeblack@google.com    # C or C++ comment (ignore)
8713511Sgabeblack@google.com    def t_c_comment(self, t):
8813511Sgabeblack@google.com        r'/\*(.|\n)*?\*/'
8913511Sgabeblack@google.com        t.lexer.lineno += t.value.count('\n')
9013511Sgabeblack@google.com
9113511Sgabeblack@google.com    def t_cpp_comment(self, t):
9213511Sgabeblack@google.com        r'//.*'
9313511Sgabeblack@google.com
9413511Sgabeblack@google.com    # Define a rule so we can track line numbers
9513511Sgabeblack@google.com    def t_newline(self, t):
9613511Sgabeblack@google.com        r'\n+'
9713511Sgabeblack@google.com        t.lexer.lineno += len(t.value)
9813511Sgabeblack@google.com
9913511Sgabeblack@google.com    reserved = {
10013511Sgabeblack@google.com        'protocol' : 'PROTOCOL',
10113511Sgabeblack@google.com        'include' : 'INCLUDE',
10213511Sgabeblack@google.com        'global' : 'GLOBAL',
10313511Sgabeblack@google.com        'machine' : 'MACHINE',
10413511Sgabeblack@google.com        'in_port' : 'IN_PORT',
10513511Sgabeblack@google.com        'out_port' : 'OUT_PORT',
10613511Sgabeblack@google.com        'action' : 'ACTION',
10713511Sgabeblack@google.com        'transition' : 'TRANS',
10813511Sgabeblack@google.com        'structure' : 'STRUCT',
10913511Sgabeblack@google.com        'external_type' : 'EXTERN_TYPE',
11013511Sgabeblack@google.com        'enumeration' : 'ENUM',
11113511Sgabeblack@google.com        'state_declaration' : 'STATE_DECL',
11213511Sgabeblack@google.com        'peek' : 'PEEK',
11313511Sgabeblack@google.com        'stall_and_wait' : 'STALL_AND_WAIT',
11413511Sgabeblack@google.com        'enqueue' : 'ENQUEUE',
11513511Sgabeblack@google.com        'check_allocate' : 'CHECK_ALLOCATE',
11613511Sgabeblack@google.com        'check_stop_slots' : 'CHECK_STOP_SLOTS',
11713511Sgabeblack@google.com        'static_cast' : 'STATIC_CAST',
11813511Sgabeblack@google.com        'if' : 'IF',
11913511Sgabeblack@google.com        'is_valid' : 'IS_VALID',
12013511Sgabeblack@google.com        'is_invalid' : 'IS_INVALID',
12113511Sgabeblack@google.com        'else' : 'ELSE',
12213511Sgabeblack@google.com        'return' : 'RETURN',
12313511Sgabeblack@google.com        'void' : 'VOID',
12413511Sgabeblack@google.com        'new' : 'NEW',
12513511Sgabeblack@google.com        'OOD' : 'OOD',
12613511Sgabeblack@google.com    }
12713511Sgabeblack@google.com
12813511Sgabeblack@google.com    literals = ':[]{}(),='
12913511Sgabeblack@google.com
13013511Sgabeblack@google.com    tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE',
13113511Sgabeblack@google.com               'LEFTSHIFT', 'RIGHTSHIFT',
13213511Sgabeblack@google.com               'NOT', 'AND', 'OR',
13313511Sgabeblack@google.com               'PLUS', 'DASH', 'STAR', 'SLASH',
13413511Sgabeblack@google.com               'INCR', 'DECR',
13513511Sgabeblack@google.com               'DOUBLE_COLON', 'SEMI',
13613511Sgabeblack@google.com               'ASSIGN', 'DOT',
13713511Sgabeblack@google.com               'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ]
13813511Sgabeblack@google.com    tokens += reserved.values()
13913511Sgabeblack@google.com
14013511Sgabeblack@google.com    t_EQ = r'=='
14113511Sgabeblack@google.com    t_NE = r'!='
14213511Sgabeblack@google.com    t_LT = r'<'
14313511Sgabeblack@google.com    t_GT = r'>'
14413511Sgabeblack@google.com    t_LE = r'<='
14513511Sgabeblack@google.com    t_GE = r'>='
14613511Sgabeblack@google.com    t_LEFTSHIFT = r'<<'
14713511Sgabeblack@google.com    t_RIGHTSHIFT = r'>>'
14813511Sgabeblack@google.com    t_NOT = r'!'
14913511Sgabeblack@google.com    t_AND = r'&&'
15013511Sgabeblack@google.com    t_OR = r'\|\|'
15113511Sgabeblack@google.com    t_PLUS = r'\+'
15213511Sgabeblack@google.com    t_DASH = r'-'
15313511Sgabeblack@google.com    t_STAR = r'\*'
15413511Sgabeblack@google.com    t_SLASH = r'/'
15513511Sgabeblack@google.com    t_DOUBLE_COLON = r'::'
15613511Sgabeblack@google.com    t_SEMI = r';'
15713511Sgabeblack@google.com    t_ASSIGN = r':='
15813511Sgabeblack@google.com    t_DOT = r'\.'
15913511Sgabeblack@google.com    t_INCR = r'\+\+'
16013511Sgabeblack@google.com    t_DECR = r'--'
16113511Sgabeblack@google.com
16213511Sgabeblack@google.com    precedence = (
16313511Sgabeblack@google.com        ('left', 'INCR', 'DECR'),
16413511Sgabeblack@google.com        ('left', 'AND', 'OR'),
16513511Sgabeblack@google.com        ('left', 'EQ', 'NE'),
16613511Sgabeblack@google.com        ('left', 'LT', 'GT', 'LE', 'GE'),
16713511Sgabeblack@google.com        ('left', 'RIGHTSHIFT', 'LEFTSHIFT'),
16813511Sgabeblack@google.com        ('left', 'PLUS', 'DASH'),
16913511Sgabeblack@google.com        ('left', 'STAR', 'SLASH'),
17013511Sgabeblack@google.com        ('right', 'NOT', 'UMINUS'),
17113511Sgabeblack@google.com    )
17213511Sgabeblack@google.com
17313511Sgabeblack@google.com    def t_IDENT(self, t):
17413511Sgabeblack@google.com        r'[a-zA-Z_][a-zA-Z_0-9]*'
175        if t.value == 'true':
176            t.type = 'LIT_BOOL'
177            t.value = True
178            return t
179
180        if t.value == 'false':
181            t.type = 'LIT_BOOL'
182            t.value = False
183            return t
184
185        # Check for reserved words
186        t.type = self.reserved.get(t.value, 'IDENT')
187        return t
188
189    def t_FLOATNUMBER(self, t):
190        '[0-9]+[.][0-9]+'
191        try:
192            t.value = float(t.value)
193        except ValueError:
194            raise ParseError("Illegal float", t)
195        return t
196
197    def t_NUMBER(self, t):
198        r'[0-9]+'
199        try:
200            t.value = int(t.value)
201        except ValueError:
202            raise ParseError("Illegal number", t)
203        return t
204
205    def t_STRING1(self, t):
206        r'\"[^"\n]*\"'
207        t.type = 'STRING'
208        t.value = t.value[1:-1]
209        return t
210
211    def t_STRING2(self, t):
212        r"\'[^'\n]*\'"
213        t.type = 'STRING'
214        t.value = t.value[1:-1]
215        return t
216
217    def p_file(self, p):
218        "file : decls"
219        p[0] = p[1]
220
221    def p_empty(self, p):
222        "empty :"
223
224    def p_decls(self, p):
225        "decls : declsx"
226        p[0] = ast.DeclListAST(self, p[1])
227
228    def p_declsx__list(self, p):
229        "declsx : decl declsx"
230        if isinstance(p[1], ast.DeclListAST):
231            decls = p[1].decls
232        elif p[1] is None:
233            decls = []
234        else:
235            decls = [ p[1] ]
236        p[0] = decls + p[2]
237
238    def p_declsx__none(self, p):
239        "declsx : empty"
240        p[0] = []
241
242    def p_decl__protocol(self, p):
243        "decl : PROTOCOL STRING SEMI"
244        if self.protocol:
245            msg = "Protocol can only be set once! Error at %s:%s\n" % \
246                (self.current_source, self.current_line)
247            raise ParseError(msg)
248        self.protocol = p[2]
249        p[0] = None
250
251    def p_decl__include(self, p):
252        "decl : INCLUDE STRING SEMI"
253        dirname = os.path.dirname(self.current_source)
254        if os.path.exists(os.path.join(dirname, p[2])):
255            filename = os.path.join(dirname, p[2])
256        else:
257            filename = os.path.join(self.base_dir, p[2])
258        p[0] = self.parse_file(filename)
259
260    def p_decl__machine0(self, p):
261        "decl : MACHINE '(' idents ')' ':' obj_decls '{' decls '}'"
262        p[0] = ast.MachineAST(self, p[3], [], p[7], p[9])
263
264    def p_decl__machine1(self, p):
265        "decl : MACHINE '(' idents pairs ')' ':' obj_decls '{' decls '}'"
266        p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9])
267
268    def p_decl__action(self, p):
269        "decl : ACTION '(' ident pairs ')' statements"
270        p[0] = ast.ActionDeclAST(self, p[3], p[4], p[6])
271
272    def p_decl__in_port(self, p):
273        "decl : IN_PORT '(' ident ',' type ',' var pairs ')' statements"
274        p[0] = ast.InPortDeclAST(self, p[3], p[5], p[7], p[8], p[10])
275
276    def p_decl__out_port(self, p):
277        "decl : OUT_PORT '(' ident ',' type ',' var pairs ')' SEMI"
278        p[0] = ast.OutPortDeclAST(self, p[3], p[5], p[7], p[8])
279
280    def p_decl__trans0(self, p):
281        "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents"
282        p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], p[7], p[9])
283
284    def p_decl__trans1(self, p):
285        "decl : TRANS '(' idents ',' idents ')' idents"
286        p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], None, p[7])
287
288    def p_decl__trans2(self, p):
289        "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents idents"
290        p[0] = ast.TransitionDeclAST(self, p[9], p[3], p[5], p[7], p[10])
291
292    def p_decl__trans3(self, p):
293        "decl : TRANS '(' idents ',' idents ')' idents idents"
294        p[0] = ast.TransitionDeclAST(self, p[7], p[3], p[5], None, p[8])
295
296    def p_decl__extern0(self, p):
297        "decl : EXTERN_TYPE '(' type pairs ')' SEMI"
298        p[4]["external"] = "yes"
299        p[0] = ast.TypeDeclAST(self, p[3], p[4], [])
300
301    def p_decl__global(self, p):
302        "decl : GLOBAL '(' type pairs ')' '{' type_members '}'"
303        p[4]["global"] = "yes"
304        p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
305
306    def p_decl__struct(self, p):
307        "decl : STRUCT '(' type pairs ')' '{' type_members '}'"
308        p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
309
310    def p_decl__enum(self, p):
311        "decl : ENUM '(' type pairs ')' '{' type_enums   '}'"
312        p[4]["enumeration"] = "yes"
313        p[0] = ast.EnumDeclAST(self, p[3], p[4], p[7])
314
315    def p_decl__state_decl(self, p):
316        "decl : STATE_DECL '(' type pairs ')' '{' type_states   '}'"
317        p[4]["enumeration"] = "yes"
318        p[4]["state_decl"] = "yes"
319        p[0] = ast.StateDeclAST(self, p[3], p[4], p[7])
320
321    # Type fields
322    def p_obj_decls__list(self, p):
323        "obj_decls : obj_decl obj_decls"
324        p[0] = [ p[1] ] + p[2]
325
326    def p_obj_decls__empty(self, p):
327        "obj_decls : empty"
328        p[0] = []
329
330    def p_type_members__list(self, p):
331        "type_members : type_member type_members"
332        p[0] = [ p[1] ] + p[2]
333
334    def p_type_members__empty(self, p):
335        "type_members : empty"
336        p[0] = []
337
338    def p_type_member__0(self, p):
339        """type_member : obj_decl
340                       | func_decl
341                       | func_def"""
342        p[0] = p[1]
343
344    # Member / Variable declarations
345    def p_decl__obj_decl(self, p):
346        "decl : obj_decl"
347        p[0] = p[1]
348
349    def p_obj_decl__0(self, p):
350        "obj_decl : type ident pairs SEMI"
351        p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3], None, False)
352
353    def p_obj_decl__1(self, p):
354        "obj_decl : type STAR ident pairs SEMI"
355        p[0] = ast.ObjDeclAST(self, p[1], p[3], p[4], None, True)
356
357    def p_obj_decl__2(self, p):
358        "obj_decl : type ident ASSIGN expr SEMI"
359        p[0] = ast.ObjDeclAST(self, p[1], p[2], ast.PairListAST(self), p[4],
360                False)
361
362    def p_obj_decl__3(self, p):
363        "obj_decl : type STAR ident ASSIGN expr SEMI"
364        p[0] = ast.ObjDeclAST(self, p[1], p[3], ast.PairListAST(self), p[5],
365                True)
366
367    # Function definition and declaration
368    def p_decl__func_decl(self, p):
369        "decl : func_decl"
370        p[0] = p[1]
371
372    def p_func_decl__0(self, p):
373        """func_decl :  void ident '(' params ')' pairs SEMI
374                | type ident '(' params ')' pairs SEMI"""
375        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
376
377    def p_func_decl__1(self, p):
378        """func_decl :  void ident '(' types ')' pairs SEMI
379                | type ident '(' types ')' pairs SEMI"""
380        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
381
382    def p_decl__func_def(self, p):
383        "decl : func_def"
384        p[0] = p[1]
385
386    def p_func_def__0(self, p):
387        """func_def : void ident '(' params ')' pairs statements
388            | type ident '(' params ')' pairs statements"""
389        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
390
391    # Enum fields
392    def p_type_enums__list(self, p):
393        "type_enums : type_enum type_enums"
394        p[0] = [ p[1] ] + p[2]
395
396    def p_type_enums__empty(self, p):
397        "type_enums : empty"
398        p[0] = []
399
400    def p_type_enum(self, p):
401        "type_enum : ident pairs SEMI"
402        p[0] = ast.TypeFieldEnumAST(self, p[1], p[2])
403
404    # States
405    def p_type_states__list(self, p):
406        "type_states : type_state type_states"
407        p[0] = [ p[1] ] + p[2]
408
409    def p_type_states__empty(self, p):
410        "type_states : empty"
411        p[0] = []
412
413    def p_type_state(self, p):
414        "type_state : ident ',' enumeration pairs SEMI"
415        p[0] = ast.TypeFieldStateAST(self, p[1], p[3], p[4])
416
417    # Formal Param
418    def p_params__many(self, p):
419        "params : param ',' params"
420        p[0] = [ p[1] ] + p[3]
421
422    def p_params__one(self, p):
423        "params : param"
424        p[0] = [ p[1] ]
425
426    def p_params__none(self, p):
427        "params : empty"
428        p[0] = []
429
430    def p_param(self, p):
431        "param : type ident"
432        p[0] = ast.FormalParamAST(self, p[1], p[2])
433
434    def p_param__pointer(self, p):
435        "param : type STAR ident"
436        p[0] = ast.FormalParamAST(self, p[1], p[3], None, True)
437
438    def p_param__pointer_default(self, p):
439        "param : type STAR ident ASSIGN STRING"
440        p[0] = ast.FormalParamAST(self, p[1], p[3], p[5], True)
441
442    def p_param__default_number(self, p):
443        "param : type ident ASSIGN NUMBER"
444        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
445
446    def p_param__default_bool(self, p):
447        "param : type ident ASSIGN LIT_BOOL"
448        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
449
450    def p_param__default_string(self, p):
451        "param : type ident ASSIGN STRING"
452        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
453
454    # Type
455    def p_types__multiple(self, p):
456        "types : type ',' types"
457        p[0] = [ p[1] ] + p[3]
458
459    def p_types__one(self, p):
460        "types : type"
461        p[0] = [ p[1] ]
462
463    def p_types__empty(self, p):
464        "types : empty"
465        p[0] = []
466
467    def p_typestr__multi(self, p):
468        "typestr : typestr DOUBLE_COLON ident"
469        p[0] = '%s::%s' % (p[1], p[3])
470
471    def p_typestr__single(self, p):
472        "typestr : ident"
473        p[0] = p[1]
474
475    def p_type__one(self, p):
476        "type : typestr"
477        p[0] = ast.TypeAST(self, p[1])
478
479    def p_void(self, p):
480        "void : VOID"
481        p[0] = ast.TypeAST(self, p[1])
482
483    # Idents and lists
484    def p_idents__braced(self, p):
485        "idents : '{' identx '}'"
486        p[0] = p[2]
487
488    def p_idents__bare(self, p):
489        "idents : ident"
490        p[0] = [ p[1] ]
491
492    def p_identx__multiple_1(self, p):
493        """identx : ident SEMI identx
494                  | ident ',' identx"""
495        p[0] = [ p[1] ] + p[3]
496
497    def p_identx__multiple_2(self, p):
498        "identx : ident identx"
499        p[0] = [ p[1] ] + p[2]
500
501    def p_identx__single(self, p):
502        "identx : empty"
503        p[0] = [ ]
504
505    def p_ident(self, p):
506        "ident : IDENT"
507        p[0] = p[1]
508
509    def p_ident_or_star(self, p):
510        """ident_or_star : ident
511                         | STAR"""
512        p[0] = p[1]
513
514    # Pair and pair lists
515    def p_pairs__list(self, p):
516        "pairs : ',' pairsx"
517        p[0] = p[2]
518
519    def p_pairs__empty(self, p):
520        "pairs : empty"
521        p[0] = ast.PairListAST(self)
522
523    def p_pairsx__many(self, p):
524        "pairsx : pair ',' pairsx"
525        p[0] = p[3]
526        p[0].addPair(p[1])
527
528    def p_pairsx__one(self, p):
529        "pairsx : pair"
530        p[0] = ast.PairListAST(self)
531        p[0].addPair(p[1])
532
533    def p_pair__assign(self, p):
534        """pair : ident '=' STRING
535                | ident '=' ident
536                | ident '=' NUMBER"""
537        p[0] = ast.PairAST(self, p[1], p[3])
538
539    def p_pair__literal(self, p):
540        "pair : STRING"
541        p[0] = ast.PairAST(self, "short", p[1])
542
543    # Below are the rules for action descriptions
544    def p_statements__inner(self, p):
545        "statements : '{' statements_inner '}'"
546        p[0] = ast.StatementListAST(self, p[2])
547
548    def p_statements__none(self, p):
549        "statements : '{' '}'"
550        p[0] = ast.StatementListAST(self, [])
551
552    def p_statements_inner__many(self, p):
553        "statements_inner : statement statements_inner"
554        p[0] = [ p[1] ] + p[2]
555
556    def p_statements_inner__one(self, p):
557        "statements_inner : statement"
558        p[0] = [ p[1] ]
559
560    def p_exprs__multiple(self, p):
561        "exprs : expr ',' exprs"
562        p[0] = [ p[1] ] + p[3]
563
564    def p_exprs__one(self, p):
565        "exprs : expr"
566        p[0] = [ p[1] ]
567
568    def p_exprs__empty(self, p):
569        "exprs : empty"""
570        p[0] = []
571
572    def p_statement__expression(self, p):
573        "statement : expr SEMI"
574        p[0] = ast.ExprStatementAST(self, p[1])
575
576    def p_statement__assign(self, p):
577        "statement : expr ASSIGN expr SEMI"
578        p[0] = ast.AssignStatementAST(self, p[1], p[3])
579
580    def p_statement__enqueue(self, p):
581        "statement : ENQUEUE '(' var ',' type ')' statements"
582        p[0] = ast.EnqueueStatementAST(self, p[3], p[5], None, p[7])
583
584    def p_statement__enqueue_latency(self, p):
585        "statement : ENQUEUE '(' var ',' type ',' expr ')' statements"
586        p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9])
587
588    def p_statement__stall_and_wait(self, p):
589        "statement : STALL_AND_WAIT '(' var ',' var ')' SEMI"
590        p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5])
591
592    def p_statement__peek(self, p):
593        "statement : PEEK '(' var ',' type pairs ')' statements"
594        p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek")
595
596    def p_statement__check_allocate(self, p):
597        "statement : CHECK_ALLOCATE '(' var ')' SEMI"
598        p[0] = ast.CheckAllocateStatementAST(self, p[3])
599
600    def p_statement__check_stop(self, p):
601        "statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI"
602        p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7])
603
604    def p_statement__return(self, p):
605        "statement : RETURN expr SEMI"
606        p[0] = ast.ReturnStatementAST(self, p[2])
607
608    def p_statement__if(self, p):
609        "statement : if_statement"
610        p[0] = p[1]
611
612    def p_if_statement__if(self, p):
613        "if_statement : IF '(' expr ')' statements"
614        p[0] = ast.IfStatementAST(self, p[3], p[5], None)
615
616    def p_if_statement__if_else(self, p):
617        "if_statement : IF '(' expr ')' statements ELSE statements"
618        p[0] = ast.IfStatementAST(self, p[3], p[5], p[7])
619
620    def p_statement__if_else_if(self, p):
621        "if_statement : IF '(' expr ')' statements ELSE if_statement"
622        p[0] = ast.IfStatementAST(self, p[3], p[5],
623                                  ast.StatementListAST(self, p[7]))
624
625    def p_expr__static_cast(self, p):
626        "aexpr : STATIC_CAST '(' type ',' expr ')'"
627        p[0] = ast.StaticCastAST(self, p[3], "ref", p[5])
628
629    def p_expr__static_cast_ptr(self, p):
630        "aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'"
631        p[0] = ast.StaticCastAST(self, p[3], p[5], p[7])
632
633    def p_expr__var(self, p):
634        "aexpr : var"
635        p[0] = p[1]
636
637    def p_expr__localvar(self, p):
638        "aexpr : type ident"
639        p[0] = ast.LocalVariableAST(self, p[1], p[2])
640
641    def p_expr__literal(self, p):
642        "aexpr : literal"
643        p[0] = p[1]
644
645    def p_expr__enumeration(self, p):
646        "aexpr : enumeration"
647        p[0] = p[1]
648
649    def p_expr__func_call(self, p):
650        "aexpr : ident '(' exprs ')'"
651        p[0] = ast.FuncCallExprAST(self, p[1], p[3])
652
653    def p_expr__new(self, p):
654        "aexpr : NEW type"
655        p[0] = ast.NewExprAST(self, p[2])
656
657    def p_expr__null(self, p):
658        "aexpr : OOD"
659        p[0] = ast.OodAST(self)
660
661    def p_expr__member(self, p):
662        "aexpr : aexpr DOT ident"
663        p[0] = ast.MemberExprAST(self, p[1], p[3])
664
665    def p_expr__member_method_call(self, p):
666        "aexpr : aexpr DOT ident '(' exprs ')'"
667        p[0] = ast.MemberMethodCallExprAST(self, p[1], p[3], p[5])
668
669    def p_expr__member_method_call_lookup(self, p):
670        "aexpr : aexpr '[' exprs ']'"
671        p[0] = ast.MemberMethodCallExprAST(self, p[1], "lookup", p[3])
672
673    def p_expr__class_method_call(self, p):
674        "aexpr : type DOUBLE_COLON ident '(' exprs ')'"
675        p[0] = ast.ClassMethodCallExprAST(self, p[1], p[3], p[5])
676
677    def p_expr__aexpr(self, p):
678        "expr : aexpr"
679        p[0] = p[1]
680
681    def p_expr__binary_op(self, p):
682        """expr : expr STAR  expr
683                | expr SLASH expr
684                | expr PLUS  expr
685                | expr DASH  expr
686                | expr LT    expr
687                | expr GT    expr
688                | expr LE    expr
689                | expr GE    expr
690                | expr EQ    expr
691                | expr NE    expr
692                | expr AND   expr
693                | expr OR    expr
694                | expr RIGHTSHIFT expr
695                | expr LEFTSHIFT  expr"""
696        p[0] = ast.InfixOperatorExprAST(self, p[1], p[2], p[3])
697
698    # FIXME - unary not
699    def p_expr__unary_op(self, p):
700        """expr : NOT expr
701                | INCR expr
702                | DECR expr
703                | DASH expr %prec UMINUS"""
704        p[0] = ast.PrefixOperatorExprAST(self, p[1], p[2])
705
706    def p_expr__parens(self, p):
707        "aexpr : '(' expr ')'"
708        p[0] = p[2]
709
710    def p_expr__is_valid_ptr(self, p):
711        "aexpr : IS_VALID '(' var ')'"
712        p[0] = ast.IsValidPtrExprAST(self, p[3], True)
713
714    def p_expr__is_invalid_ptr(self, p):
715        "aexpr : IS_INVALID '(' var ')'"
716        p[0] = ast.IsValidPtrExprAST(self, p[3], False)
717
718    def p_literal__string(self, p):
719        "literal : STRING"
720        p[0] = ast.LiteralExprAST(self, p[1], "std::string")
721
722    def p_literal__number(self, p):
723        "literal : NUMBER"
724        p[0] = ast.LiteralExprAST(self, p[1], "int")
725
726    def p_literal__float(self, p):
727        "literal : FLOATNUMBER"
728        p[0] = ast.LiteralExprAST(self, p[1], "int")
729
730    def p_literal__bool(self, p):
731        "literal : LIT_BOOL"
732        p[0] = ast.LiteralExprAST(self, p[1], "bool")
733
734    def p_enumeration(self, p):
735        "enumeration : ident ':' ident"
736        p[0] = ast.EnumExprAST(self, ast.TypeAST(self, p[1]), p[3])
737
738    def p_var(self, p):
739        "var : ident"
740        p[0] = ast.VarExprAST(self, p[1])
741