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