parser.py revision 7055:4e24742201d7
1# Copyright (c) 2009 The Hewlett-Packard Development Company
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution;
11# neither the name of the copyright holders nor the names of its
12# contributors may be used to endorse or promote products derived from
13# this software without specific prior written permission.
14#
15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27# Authors: Nathan Binkert
28
29import os.path
30import re
31import sys
32
33from m5.util import code_formatter
34from m5.util.grammar import Grammar, TokenError, ParseError
35
36import slicc.ast as ast
37import slicc.util as util
38from slicc.symbols import SymbolTable
39
40def read_slicc(sources):
41    if not isinstance(sources, (list,tuple)):
42        sources = [ sources ]
43
44    for source in sources:
45        for sm_file in file(source, "r"):
46            sm_file = sm_file.strip()
47            if not sm_file:
48                continue
49            if sm_file.startswith("#"):
50                continue
51            yield sm_file
52
53class SLICC(Grammar):
54    def __init__(self, protocol, **kwargs):
55        super(SLICC, self).__init__(**kwargs)
56        self.decl_list_vec = []
57        self.current_file = None
58        self.protocol = protocol
59        self.symtab = SymbolTable(self)
60
61    def codeFormatter(self, *args, **kwargs):
62        code = code_formatter(*args, **kwargs)
63        code['protocol'] = self.protocol
64        return code
65
66    def parse(self, filename):
67        self.current_file = filename
68        f = file(filename, 'r')
69        text = f.read()
70        try:
71            decl_list = super(SLICC, self).parse(text)
72        except (TokenError, ParseError), e:
73            sys.exit("%s: %s:%d" % (e, filename, e.token.lineno))
74        self.decl_list_vec.append(decl_list)
75        self.current_file = None
76
77    def _load(self, *filenames):
78        filenames = list(filenames)
79        while filenames:
80            f = filenames.pop(0)
81            if isinstance(f, (list, tuple)):
82                filenames[0:0] = list(f)
83                continue
84
85            yield f
86            if f.endswith(".slicc"):
87                dirname,basename = os.path.split(f)
88                filenames[0:0] = [ os.path.join(dirname, x) \
89                                   for x in read_slicc(f)]
90            else:
91                assert f.endswith(".sm")
92                self.parse(f)
93
94    def load(self, *filenames, **kwargs):
95        verbose = kwargs.pop("verbose", False)
96        if kwargs:
97            raise TypeError
98
99        gen = self._load(*filenames)
100        if verbose:
101            return gen
102        else:
103            # Run out the generator if we don't want the verbosity
104            for foo in gen:
105                pass
106
107    def findMachines(self):
108        for decl_list in self.decl_list_vec:
109            decl_list.findMachines()
110
111    def generate(self):
112        for decl_list in self.decl_list_vec:
113            decl_list.generate()
114
115    def writeCodeFiles(self, code_path):
116        util.makeDir(code_path)
117        self.symtab.writeCodeFiles(code_path)
118
119    def writeHTMLFiles(self, code_path):
120        util.makeDir(code_path)
121        self.symtab.writeHTMLFiles(code_path)
122
123    def files(self):
124        f = set([
125            'MachineType.cc',
126            'MachineType.hh',
127            'Types.hh' ])
128
129        for decl_list in self.decl_list_vec:
130            f |= decl_list.files()
131
132        return f
133
134    t_ignore = '\t '
135
136    # C or C++ comment (ignore)
137    def t_c_comment(self, t):
138        r'/\*(.|\n)*?\*/'
139        t.lexer.lineno += t.value.count('\n')
140
141    def t_cpp_comment(self, t):
142        r'//.*'
143
144    # Define a rule so we can track line numbers
145    def t_newline(self, t):
146        r'\n+'
147        t.lexer.lineno += len(t.value)
148
149    reserved = {
150        'global' : 'GLOBAL',
151        'machine' : 'MACHINE',
152        'in_port' : 'IN_PORT',
153        'out_port' : 'OUT_PORT',
154        'action' : 'ACTION',
155        'transition' : 'TRANS',
156        'structure' : 'STRUCT',
157        'external_type' : 'EXTERN_TYPE',
158        'enumeration' : 'ENUM',
159        'peek' : 'PEEK',
160        'enqueue' : 'ENQUEUE',
161        'copy_head' : 'COPY_HEAD',
162        'check_allocate' : 'CHECK_ALLOCATE',
163        'check_stop_slots' : 'CHECK_STOP_SLOTS',
164        'static_cast' : 'STATIC_CAST',
165        'if' : 'IF',
166        'else' : 'ELSE',
167        'return' : 'RETURN',
168        'THIS' : 'THIS',
169        'CHIP' : 'CHIP',
170        'void' : 'VOID',
171        'new' : 'NEW',
172    }
173
174    literals = ':[]{}(),='
175
176    tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE',
177               'LEFTSHIFT', 'RIGHTSHIFT',
178               'NOT', 'AND', 'OR',
179               'PLUS', 'DASH', 'STAR', 'SLASH',
180               'DOUBLE_COLON', 'SEMI',
181               'ASSIGN', 'DOT',
182               'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ]
183    tokens += reserved.values()
184
185    t_EQ = r'=='
186    t_NE = r'!='
187    t_LT = r'<'
188    t_GT = r'>'
189    t_LE = r'<='
190    t_GE = r'>='
191    t_LEFTSHIFT = r'<<'
192    t_RIGHTSHIFT = r'>>'
193    t_NOT = r'!'
194    t_AND = r'&&'
195    t_OR = r'\|\|'
196    t_PLUS = r'\+'
197    t_DASH = r'-'
198    t_STAR = r'\*'
199    t_SLASH = r'/'
200    t_DOUBLE_COLON = r'::'
201    t_SEMI = r';'
202    t_ASSIGN = r':='
203    t_DOT = r'\.'
204
205    precedence = (
206        ('left', 'AND', 'OR'),
207        ('left', 'EQ', 'NE'),
208        ('left', 'LT', 'GT', 'LE', 'GE'),
209        ('left', 'RIGHTSHIFT', 'LEFTSHIFT'),
210        ('left', 'PLUS', 'DASH'),
211        ('left', 'STAR', 'SLASH'),
212        ('right', 'NOT', 'UMINUS'),
213    )
214
215    def t_IDENT(self, t):
216        r'[a-zA-Z_][a-zA-Z_0-9]*'
217        if t.value == 'true':
218            t.type = 'LIT_BOOL'
219            t.value = True
220            return t
221
222        if t.value == 'false':
223            t.type = 'LIT_BOOL'
224            t.value = False
225            return t
226
227        # Check for reserved words
228        t.type = self.reserved.get(t.value, 'IDENT')
229        return t
230
231    def t_FLOATNUMBER(self, t):
232        '[0-9]+[.][0-9]+'
233        try:
234            t.value = float(t.value)
235        except ValueError:
236            raise TokenError("Illegal float", t)
237        return t
238
239    def t_NUMBER(self, t):
240        r'[0-9]+'
241        try:
242            t.value = int(t.value)
243        except ValueError:
244            raise TokenError("Illegal number", t)
245        return t
246
247    def t_STRING1(self, t):
248        r'\"[^"\n]*\"'
249        t.type = 'STRING'
250        t.value = t.value[1:-1]
251        return t
252
253    def t_STRING2(self, t):
254        r"\'[^'\n]*\'"
255        t.type = 'STRING'
256        t.value = t.value[1:-1]
257        return t
258
259    def p_file(self, p):
260        "file : decls"
261        p[0] = p[1]
262
263    def p_empty(self, p):
264        "empty :"
265
266    def p_decls(self, p):
267        "decls : declsx"
268        p[0] = ast.DeclListAST(self, p[1])
269
270    def p_declsx__list(self, p):
271        "declsx : decl declsx"
272        p[0] = [ p[1] ] + p[2]
273
274    def p_declsx__none(self, p):
275        "declsx : empty"
276        p[0] = []
277
278    def p_decl__machine(self, p):
279        "decl : MACHINE '(' ident pairs ')' ':' params '{' decls '}'"
280        p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9])
281
282    def p_decl__action(self, p):
283        "decl : ACTION '(' ident pairs ')' statements"
284        p[0] = ast.ActionDeclAST(self, p[3], p[4], p[6])
285
286    def p_decl__in_port(self, p):
287        "decl : IN_PORT '(' ident ',' type ',' var pairs ')' statements"
288        p[0] = ast.InPortDeclAST(self, p[3], p[5], p[7], p[8], p[10])
289
290    def p_decl__out_port(self, p):
291        "decl : OUT_PORT '(' ident ',' type ',' var pairs ')' SEMI"
292        p[0] = ast.OutPortDeclAST(self, p[3], p[5], p[7], p[8])
293
294    def p_decl__trans0(self, p):
295        "decl : TRANS '(' idents ',' idents ',' ident pairs ')' idents"
296        p[0] = ast.TransitionDeclAST(self, p[3], p[5], p[7], p[8], p[10])
297
298    def p_decl__trans1(self, p):
299        "decl : TRANS '(' idents ',' idents           pairs ')' idents"
300        p[0] = ast.TransitionDeclAST(self, p[3], p[5], None, p[6], p[8])
301
302    def p_decl__extern0(self, p):
303        "decl : EXTERN_TYPE '(' type pairs ')' SEMI"
304        p[4]["external"] = "yes"
305        p[0] = ast.TypeDeclAST(self, p[3], p[4], [])
306
307    def p_decl__extern1(self, p):
308        "decl : EXTERN_TYPE '(' type pairs ')' '{' type_methods '}'"
309        p[4]["external"] = "yes"
310        p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
311
312    def p_decl__global(self, p):
313        "decl : GLOBAL '(' type pairs ')' '{' type_members '}'"
314        p[4]["global"] = "yes"
315        p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
316
317    def p_decl__struct(self, p):
318        "decl : STRUCT '(' type pairs ')' '{' type_members '}'"
319        p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
320
321    def p_decl__enum(self, p):
322        "decl : ENUM '(' type pairs ')' '{' type_enums   '}'"
323        p[4]["enumeration"] = "yes"
324        p[0] = ast.EnumDeclAST(self, p[3], p[4], p[7])
325
326    def p_decl__object(self, p):
327        "decl : type ident pairs SEMI"
328        p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3])
329
330    def p_decl__func_decl(self, p):
331        """decl : void ident '(' params ')' pairs SEMI
332                | type ident '(' params ')' pairs SEMI"""
333        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
334
335    def p_decl__func_def(self, p):
336        """decl : void ident '(' params ')' pairs statements
337                | type ident '(' params ')' pairs statements"""
338        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
339
340    # Type fields
341    def p_type_members__list(self, p):
342        "type_members : type_member type_members"
343        p[0] = [ p[1] ] + p[2]
344
345    def p_type_members__empty(self, p):
346        "type_members : empty"
347        p[0] = []
348
349    def p_type_member__1(self, p):
350        "type_member : type ident pairs SEMI"
351        p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None)
352
353    def p_type_member__2(self, p):
354        "type_member : type ident ASSIGN expr SEMI"
355        p[0] = ast.TypeFieldMemberAST(self, p[1], p[2],
356                                      ast.PairListAST(self), p[4])
357
358    # Methods
359    def p_type_methods__list(self, p):
360        "type_methods : type_method type_methods"
361        p[0] = [ p[1] ] + p[2]
362
363    def p_type_methods(self, p):
364        "type_methods : empty"
365        p[0] = []
366
367    def p_type_method(self, p):
368        "type_method : type_or_void ident '(' types ')' pairs SEMI"
369        p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
370
371    # Enum fields
372    def p_type_enums__list(self, p):
373        "type_enums : type_enum type_enums"
374        p[0] = [ p[1] ] + p[2]
375
376    def p_type_enums__empty(self, p):
377        "type_enums : empty"
378        p[0] = []
379
380    def p_type_enum(self, p):
381        "type_enum : ident pairs SEMI"
382        p[0] = ast.TypeFieldEnumAST(self, p[1], p[2])
383
384    # Type
385    def p_types__multiple(self, p):
386        "types : type ',' types"
387        p[0] = [ p[1] ] + p[3]
388
389    def p_types__one(self, p):
390        "types : type"
391        p[0] = [ p[1] ]
392
393    def p_types__empty(self, p):
394        "types : empty"
395        p[0] = []
396
397    def p_typestr__multi(self, p):
398        "typestr : typestr DOUBLE_COLON ident"
399        p[0] = '%s::%s' % (p[1], p[3])
400
401    def p_typestr__single(self, p):
402        "typestr : ident"
403        p[0] = p[1]
404
405    def p_type__one(self, p):
406        "type : typestr"
407        p[0] = ast.TypeAST(self, p[1])
408
409    def p_void(self, p):
410        "void : VOID"
411        p[0] = ast.TypeAST(self, p[1])
412
413    def p_type_or_void(self, p):
414        """type_or_void : type
415                        | void"""
416        p[0] = p[1]
417
418    # Formal Param
419    def p_params__many(self, p):
420        "params : param ',' params"
421        p[0] = [ p[1] ] + p[3]
422
423    def p_params__one(self, p):
424        "params : param"
425        p[0] = [ p[1] ]
426
427    def p_params__none(self, p):
428        "params : empty"
429        p[0] = []
430
431    def p_param(self, p):
432        "param : type ident"
433        p[0] = ast.FormalParamAST(self, p[1], p[2])
434
435    def p_param__pointer(self, p):
436        "param : type STAR ident"
437        p[0] = ast.FormalParamAST(self, p[1], p[3], None, True)
438
439    def p_param__pointer_default(self, p):
440        "param : type STAR ident '=' STRING"
441        p[0] = ast.FormalParamAST(self, p[1], p[3], p[5], True)
442
443    def p_param__default_number(self, p):
444        "param : type ident '=' NUMBER"
445        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
446
447    def p_param__default_bool(self, p):
448        "param : type ident '=' LIT_BOOL"
449        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
450
451    def p_param__default_string(self, p):
452        "param : type ident '=' STRING"
453        p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
454
455    # Idents and lists
456    def p_idents__braced(self, p):
457        "idents : '{' identx '}'"
458        p[0] = p[2]
459
460    def p_idents__bare(self, p):
461        "idents : ident"
462        p[0] = [ p[1] ]
463
464    def p_identx__multiple_1(self, p):
465        """identx : ident SEMI identx
466                  | ident ',' identx"""
467        p[0] = [ p[1] ] + p[3]
468
469    def p_identx__multiple_2(self, p):
470        "identx : ident identx"
471        p[0] = [ p[1] ] + p[2]
472
473    def p_identx__single(self, p):
474        "identx : empty"
475        p[0] = [ ]
476
477    def p_ident(self, p):
478        "ident : IDENT"
479        p[0] = p[1]
480
481    # Pair and pair lists
482    def p_pairs__list(self, p):
483        "pairs : ',' pairsx"
484        p[0] = p[2]
485
486    def p_pairs__empty(self, p):
487        "pairs : empty"
488        p[0] = ast.PairListAST(self)
489
490    def p_pairsx__many(self, p):
491        "pairsx : pair ',' pairsx"
492        p[0] = p[3]
493        p[0].addPair(p[1])
494
495    def p_pairsx__one(self, p):
496        "pairsx : pair"
497        p[0] = ast.PairListAST(self)
498        p[0].addPair(p[1])
499
500    def p_pair__assign(self, p):
501        """pair : ident '=' STRING
502                | ident '=' ident"""
503        p[0] = ast.PairAST(self, p[1], p[3])
504
505    def p_pair__literal(self, p):
506        "pair : STRING"
507        p[0] = ast.PairAST(self, "short", p[1])
508
509    # Below are the rules for action descriptions
510    def p_statements__inner(self, p):
511        "statements : '{' statements_inner '}'"
512        p[0] = ast.StatementListAST(self, p[2])
513
514    def p_statements__none(self, p):
515        "statements : '{' '}'"
516        p[0] = ast.StatementListAST(self, [])
517
518    def p_statements_inner__many(self, p):
519        "statements_inner : statement statements_inner"
520        p[0] = [ p[1] ] + p[2]
521
522    def p_statements_inner__one(self, p):
523        "statements_inner : statement"
524        p[0] = [ p[1] ]
525
526    def p_exprs__multiple(self, p):
527        "exprs : expr ',' exprs"
528        p[0] = [ p[1] ] + p[3]
529
530    def p_exprs__one(self, p):
531        "exprs : expr"
532        p[0] = [ p[1] ]
533
534    def p_exprs__empty(self, p):
535        "exprs : empty"""
536        p[0] = []
537
538    def p_statement__expression(self, p):
539        "statement : expr SEMI"
540        p[0] = ast.ExprStatementAST(self, p[1])
541
542    def p_statement__assign(self, p):
543        "statement : expr ASSIGN expr SEMI"
544        p[0] = ast.AssignStatementAST(self, p[1], p[3])
545
546    def p_statement__enqueue(self, p):
547        "statement : ENQUEUE '(' var ',' type pairs ')' statements"
548        p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[6], p[8])
549
550    def p_statement__peek(self, p):
551        "statement : PEEK '(' var ',' type pairs ')' statements"
552        p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek")
553
554    def p_statement__copy_head(self, p):
555        "statement : COPY_HEAD '(' var ',' var pairs ')' SEMI"
556        p[0] = ast.CopyHeadStatementAST(self, p[3], p[5], p[6])
557
558    def p_statement__check_allocate(self, p):
559        "statement : CHECK_ALLOCATE '(' var ')' SEMI"
560        p[0] = ast.CheckAllocateStatementAST(self, p[3])
561
562    def p_statement__check_stop(self, p):
563        "statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI"
564        p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7])
565
566    def p_statement__static_cast(self, p):
567        "aexpr : STATIC_CAST '(' type ',' expr ')'"
568        p[0] = ast.StaticCastAST(self, p[3], p[5])
569
570    def p_statement__return(self, p):
571        "statement : RETURN expr SEMI"
572        p[0] = ast.ReturnStatementAST(self, p[2])
573
574    def p_statement__if(self, p):
575        "statement : if_statement"
576        p[0] = p[1]
577
578    def p_if_statement__if(self, p):
579        "if_statement : IF '(' expr ')' statements"
580        p[0] = ast.IfStatementAST(self, p[3], p[5], None)
581
582    def p_if_statement__if_else(self, p):
583        "if_statement : IF '(' expr ')' statements ELSE statements"
584        p[0] = ast.IfStatementAST(self, p[3], p[5], p[7])
585
586    def p_statement__if_else_if(self, p):
587        "if_statement : IF '(' expr ')' statements ELSE if_statement"
588        p[0] = ast.IfStatementAST(self, p[3], p[5],
589                                  ast.StatementListAST(self, p[7]))
590
591    def p_expr__var(self, p):
592        "aexpr : var"
593        p[0] = p[1]
594
595    def p_expr__literal(self, p):
596        "aexpr : literal"
597        p[0] = p[1]
598
599    def p_expr__enumeration(self, p):
600        "aexpr : enumeration"
601        p[0] = p[1]
602
603    def p_expr__func_call(self, p):
604        "aexpr : ident '(' exprs ')'"
605        p[0] = ast.FuncCallExprAST(self, p[1], p[3])
606
607    def p_expr__new(self, p):
608        "aexpr : NEW type"
609        p[0] = ast.NewExprAST(self, p[2])
610
611    # globally access a local chip component and call a method
612    def p_expr__local_chip_method(self, p):
613        "aexpr : THIS DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
614        p[0] = ast.LocalChipMethodAST(self, p[3], p[5], p[8], p[10], p[12])
615
616    # globally access a local chip component and access a data member
617    def p_expr__local_chip_member(self, p):
618        "aexpr : THIS DOT var '[' expr ']' DOT var DOT field"
619        p[0] = ast.LocalChipMemberAST(self, p[3], p[5], p[8], p[10])
620
621    # globally access a specified chip component and call a method
622    def p_expr__specified_chip_method(self, p):
623        "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
624        p[0] = ast.SpecifiedChipMethodAST(self, p[3], p[6], p[8], p[11], p[13],
625                                          p[15])
626
627    # globally access a specified chip component and access a data member
628    def p_expr__specified_chip_member(self, p):
629        "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field"
630        p[0] = ast.SpecifiedChipMemberAST(self, p[3], p[6], p[8], p[11], p[13])
631
632    def p_expr__member(self, p):
633        "aexpr : aexpr DOT ident"
634        p[0] = ast.MemberExprAST(self, p[1], p[3])
635
636    def p_expr__member_method_call(self, p):
637        "aexpr : aexpr DOT ident '(' exprs ')'"
638        p[0] = ast.MemberMethodCallExprAST(self, p[1], p[3], p[5])
639
640    def p_expr__member_method_call_lookup(self, p):
641        "aexpr : aexpr '[' exprs ']'"
642        p[0] = ast.MemberMethodCallExprAST(self, p[1], "lookup", p[3])
643
644    def p_expr__class_method_call(self, p):
645        "aexpr : type DOUBLE_COLON ident '(' exprs ')'"
646        p[0] = ast.ClassMethodCallExprAST(self, p[1], p[3], p[5])
647
648    def p_expr__aexpr(self, p):
649        "expr : aexpr"
650        p[0] = p[1]
651
652    def p_expr__binary_op(self, p):
653        """expr : expr STAR  expr
654                | expr SLASH expr
655                | expr PLUS  expr
656                | expr DASH  expr
657                | expr LT    expr
658                | expr GT    expr
659                | expr LE    expr
660                | expr GE    expr
661                | expr EQ    expr
662                | expr NE    expr
663                | expr AND   expr
664                | expr OR    expr
665                | expr RIGHTSHIFT expr
666                | expr LEFTSHIFT  expr"""
667        p[0] = ast.InfixOperatorExprAST(self, p[1], p[2], p[3])
668
669    # FIXME - unary not
670    def p_expr__unary_op(self, p):
671        """expr : NOT expr
672                | DASH expr %prec UMINUS"""
673        p[0] = PrefixOperatorExpr(p[1], p[2])
674
675    def p_expr__parens(self, p):
676        "aexpr : '(' expr ')'"
677        p[0] = p[2]
678
679    def p_literal__string(self, p):
680        "literal : STRING"
681        p[0] = ast.LiteralExprAST(self, p[1], "std::string")
682
683    def p_literal__number(self, p):
684        "literal : NUMBER"
685        p[0] = ast.LiteralExprAST(self, p[1], "int")
686
687    def p_literal__float(self, p):
688        "literal : FLOATNUMBER"
689        p[0] = ast.LiteralExprAST(self, p[1], "int")
690
691    def p_literal__bool(self, p):
692        "literal : LIT_BOOL"
693        p[0] = ast.LiteralExprAST(self, p[1], "bool")
694
695    def p_enumeration(self, p):
696        "enumeration : ident ':' ident"
697        p[0] = ast.EnumExprAST(self, ast.TypeAST(self, p[1]), p[3])
698
699    def p_var(self, p):
700        "var : ident"
701        p[0] = ast.VarExprAST(self, p[1])
702
703    def p_field(self, p):
704        "field : ident"
705        p[0] = p[1]
706