| # Copyright (c) 2020 ARM Limited |
| # All rights reserved. |
| # |
| # The license below extends only to copyright in the software and shall |
| # not be construed as granting a license to any other intellectual |
| # property including but not limited to intellectual property relating |
| # to a hardware implementation of the functionality of the software |
| # licensed hereunder. You may use the software subject to the license |
| # terms below provided that you ensure that this notice is replicated |
| # unmodified and in its entirety in all distributions of the software, |
| # modified or unmodified, in source code or in binary form. |
| # |
| # Copyright (c) 2009 The Hewlett-Packard Development Company |
| # Copyright (c) 2017 Google Inc. |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer; |
| # 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; |
| # neither the name of the copyright holders nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "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 COPYRIGHT |
| # OWNER OR CONTRIBUTORS 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. |
| |
| import os.path |
| import re |
| import sys |
| |
| from m5.util import code_formatter |
| from m5.util.grammar import Grammar, ParseError |
| |
| import slicc.ast as ast |
| import slicc.util as util |
| from slicc.symbols import SymbolTable |
| |
| class SLICC(Grammar): |
| def __init__(self, filename, base_dir, verbose=False, traceback=False, **kwargs): |
| self.protocol = None |
| self.traceback = traceback |
| self.verbose = verbose |
| self.symtab = SymbolTable(self) |
| self.base_dir = base_dir |
| |
| try: |
| self.decl_list = self.parse_file(filename, **kwargs) |
| except ParseError as e: |
| if not self.traceback: |
| sys.exit(str(e)) |
| raise |
| |
| def currentLocation(self): |
| return util.Location(self.current_source, self.current_line, |
| no_warning=not self.verbose) |
| |
| def codeFormatter(self, *args, **kwargs): |
| code = code_formatter(*args, **kwargs) |
| code['protocol'] = self.protocol |
| return code |
| |
| def process(self): |
| self.decl_list.generate() |
| |
| def writeCodeFiles(self, code_path, includes): |
| self.symtab.writeCodeFiles(code_path, includes) |
| |
| def writeHTMLFiles(self, html_path): |
| self.symtab.writeHTMLFiles(html_path) |
| |
| def files(self): |
| f = set(['Types.hh']) |
| |
| f |= self.decl_list.files() |
| |
| return f |
| |
| t_ignore = '\t ' |
| |
| # C or C++ comment (ignore) |
| def t_c_comment(self, t): |
| r'/\*(.|\n)*?\*/' |
| t.lexer.lineno += t.value.count('\n') |
| |
| def t_cpp_comment(self, t): |
| r'//.*' |
| |
| # Define a rule so we can track line numbers |
| def t_newline(self, t): |
| r'\n+' |
| t.lexer.lineno += len(t.value) |
| |
| reserved = { |
| 'protocol' : 'PROTOCOL', |
| 'include' : 'INCLUDE', |
| 'global' : 'GLOBAL', |
| 'machine' : 'MACHINE', |
| 'in_port' : 'IN_PORT', |
| 'out_port' : 'OUT_PORT', |
| 'action' : 'ACTION', |
| 'transition' : 'TRANS', |
| 'structure' : 'STRUCT', |
| 'external_type' : 'EXTERN_TYPE', |
| 'enumeration' : 'ENUM', |
| 'state_declaration' : 'STATE_DECL', |
| 'peek' : 'PEEK', |
| 'stall_and_wait' : 'STALL_AND_WAIT', |
| 'enqueue' : 'ENQUEUE', |
| 'check_allocate' : 'CHECK_ALLOCATE', |
| 'check_next_cycle' : 'CHECK_NEXT_CYCLE', |
| 'check_stop_slots' : 'CHECK_STOP_SLOTS', |
| 'check_on_cache_probe' : 'CHECK_PROBE', |
| 'static_cast' : 'STATIC_CAST', |
| 'if' : 'IF', |
| 'is_valid' : 'IS_VALID', |
| 'is_invalid' : 'IS_INVALID', |
| 'else' : 'ELSE', |
| 'return' : 'RETURN', |
| 'void' : 'VOID', |
| 'new' : 'NEW', |
| 'OOD' : 'OOD', |
| 'defer_enqueueing' : 'DEFER_ENQUEUEING', |
| } |
| |
| literals = ':[]{}(),=' |
| |
| tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE', |
| 'LEFTSHIFT', 'RIGHTSHIFT', |
| 'NOT', 'AND', 'OR', |
| 'PLUS', 'DASH', 'STAR', 'SLASH', 'MOD', |
| 'INCR', 'DECR', |
| 'DOUBLE_COLON', 'SEMI', |
| 'ASSIGN', 'DOT', |
| 'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING', |
| 'AMP', 'CONST' ] |
| tokens += reserved.values() |
| |
| t_EQ = r'==' |
| t_NE = r'!=' |
| t_LT = r'<' |
| t_GT = r'>' |
| t_LE = r'<=' |
| t_GE = r'>=' |
| t_LEFTSHIFT = r'<<' |
| t_RIGHTSHIFT = r'>>' |
| t_NOT = r'!' |
| t_AND = r'&&' |
| t_OR = r'\|\|' |
| t_PLUS = r'\+' |
| t_DASH = r'-' |
| t_STAR = r'\*' |
| t_AMP = r'&' |
| t_CONST = r'const' |
| t_SLASH = r'/' |
| t_MOD = r'%' |
| t_DOUBLE_COLON = r'::' |
| t_SEMI = r';' |
| t_ASSIGN = r':=' |
| t_DOT = r'\.' |
| t_INCR = r'\+\+' |
| t_DECR = r'--' |
| |
| precedence = ( |
| ('left', 'INCR', 'DECR'), |
| ('left', 'OR'), |
| ('left', 'AND'), |
| ('left', 'EQ', 'NE'), |
| ('left', 'LT', 'GT', 'LE', 'GE'), |
| ('left', 'RIGHTSHIFT', 'LEFTSHIFT'), |
| ('left', 'PLUS', 'DASH'), |
| ('left', 'STAR', 'SLASH', 'MOD'), |
| ('right', 'NOT', 'UMINUS'), |
| ) |
| |
| def t_IDENT(self, t): |
| r'[a-zA-Z_][a-zA-Z_0-9]*' |
| if t.value == 'true': |
| t.type = 'LIT_BOOL' |
| t.value = True |
| return t |
| |
| if t.value == 'false': |
| t.type = 'LIT_BOOL' |
| t.value = False |
| return t |
| |
| # Check for reserved words |
| t.type = self.reserved.get(t.value, 'IDENT') |
| return t |
| |
| def t_FLOATNUMBER(self, t): |
| '[0-9]+[.][0-9]+' |
| try: |
| t.value = float(t.value) |
| except ValueError: |
| raise ParseError("Illegal float", t) |
| return t |
| |
| def t_NUMBER(self, t): |
| r'[0-9]+' |
| try: |
| t.value = int(t.value) |
| except ValueError: |
| raise ParseError("Illegal number", t) |
| return t |
| |
| def t_STRING1(self, t): |
| r'\"[^"\n]*\"' |
| t.type = 'STRING' |
| t.value = t.value[1:-1] |
| return t |
| |
| def t_STRING2(self, t): |
| r"\'[^'\n]*\'" |
| t.type = 'STRING' |
| t.value = t.value[1:-1] |
| return t |
| |
| def p_file(self, p): |
| "file : decls" |
| p[0] = p[1] |
| |
| def p_empty(self, p): |
| "empty :" |
| |
| def p_decls(self, p): |
| "decls : declsx" |
| p[0] = ast.DeclListAST(self, p[1]) |
| |
| def p_declsx__list(self, p): |
| "declsx : decl declsx" |
| if isinstance(p[1], ast.DeclListAST): |
| decls = p[1].decls |
| elif p[1] is None: |
| decls = [] |
| else: |
| decls = [ p[1] ] |
| p[0] = decls + p[2] |
| |
| def p_declsx__none(self, p): |
| "declsx : empty" |
| p[0] = [] |
| |
| def p_decl__protocol(self, p): |
| "decl : PROTOCOL STRING SEMI" |
| if self.protocol: |
| msg = "Protocol can only be set once! Error at %s:%s\n" % \ |
| (self.current_source, self.current_line) |
| raise ParseError(msg) |
| self.protocol = p[2] |
| p[0] = None |
| |
| def p_decl__include(self, p): |
| "decl : INCLUDE STRING SEMI" |
| dirname = os.path.dirname(self.current_source) |
| if os.path.exists(os.path.join(dirname, p[2])): |
| filename = os.path.join(dirname, p[2]) |
| else: |
| filename = os.path.join(self.base_dir, p[2]) |
| p[0] = self.parse_file(filename) |
| |
| def p_decl__machine0(self, p): |
| "decl : MACHINE '(' enumeration ')' ':' obj_decls '{' decls '}'" |
| p[0] = ast.MachineAST(self, p[3], [], p[7], p[9]) |
| |
| def p_decl__machine1(self, p): |
| "decl : MACHINE '(' enumeration pairs ')' ':' obj_decls '{' decls '}'" |
| p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9]) |
| |
| def p_decl__action(self, p): |
| "decl : ACTION '(' ident pairs ')' statements" |
| p[0] = ast.ActionDeclAST(self, p[3], p[4], p[6]) |
| |
| def p_decl__in_port(self, p): |
| "decl : IN_PORT '(' ident ',' type ',' var pairs ')' statements" |
| p[0] = ast.InPortDeclAST(self, p[3], p[5], p[7], p[8], p[10]) |
| |
| def p_decl__out_port(self, p): |
| "decl : OUT_PORT '(' ident ',' type ',' var pairs ')' SEMI" |
| p[0] = ast.OutPortDeclAST(self, p[3], p[5], p[7], p[8]) |
| |
| def p_decl__trans0(self, p): |
| "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents" |
| p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], p[7], p[9]) |
| |
| def p_decl__trans1(self, p): |
| "decl : TRANS '(' idents ',' idents ')' idents" |
| p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], None, p[7]) |
| |
| def p_decl__trans2(self, p): |
| "decl : TRANS '(' idents ',' idents ',' ident_or_star ')' idents idents" |
| p[0] = ast.TransitionDeclAST(self, p[9], p[3], p[5], p[7], p[10]) |
| |
| def p_decl__trans3(self, p): |
| "decl : TRANS '(' idents ',' idents ')' idents idents" |
| p[0] = ast.TransitionDeclAST(self, p[7], p[3], p[5], None, p[8]) |
| |
| def p_decl__extern0(self, p): |
| "decl : EXTERN_TYPE '(' type pairs ')' SEMI" |
| p[4]["external"] = "yes" |
| p[0] = ast.TypeDeclAST(self, p[3], p[4], []) |
| |
| def p_decl__global(self, p): |
| "decl : GLOBAL '(' type pairs ')' '{' type_members '}'" |
| p[4]["global"] = "yes" |
| p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7]) |
| |
| def p_decl__struct(self, p): |
| "decl : STRUCT '(' type pairs ')' '{' type_members '}'" |
| p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7]) |
| |
| def p_decl__enum(self, p): |
| "decl : ENUM '(' type pairs ')' '{' type_enums '}'" |
| p[4]["enumeration"] = "yes" |
| p[0] = ast.EnumDeclAST(self, p[3], p[4], p[7]) |
| |
| def p_decl__state_decl(self, p): |
| "decl : STATE_DECL '(' type pairs ')' '{' type_states '}'" |
| p[4]["enumeration"] = "yes" |
| p[4]["state_decl"] = "yes" |
| p[0] = ast.StateDeclAST(self, p[3], p[4], p[7]) |
| |
| # Type fields |
| def p_obj_decls__list(self, p): |
| "obj_decls : obj_decl obj_decls" |
| p[0] = [ p[1] ] + p[2] |
| |
| def p_obj_decls__empty(self, p): |
| "obj_decls : empty" |
| p[0] = [] |
| |
| def p_type_members__list(self, p): |
| "type_members : type_member type_members" |
| p[0] = [ p[1] ] + p[2] |
| |
| def p_type_members__empty(self, p): |
| "type_members : empty" |
| p[0] = [] |
| |
| def p_type_member__0(self, p): |
| """type_member : obj_decl |
| | func_decl |
| | func_def""" |
| p[0] = p[1] |
| |
| # Member / Variable declarations |
| def p_decl__obj_decl(self, p): |
| "decl : obj_decl" |
| p[0] = p[1] |
| |
| def p_obj_decl__0(self, p): |
| "obj_decl : type ident pairs SEMI" |
| p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3], None, False) |
| |
| def p_obj_decl__1(self, p): |
| "obj_decl : type STAR ident pairs SEMI" |
| p[0] = ast.ObjDeclAST(self, p[1], p[3], p[4], None, True) |
| |
| def p_obj_decl__2(self, p): |
| "obj_decl : type ident ASSIGN expr SEMI" |
| p[0] = ast.ObjDeclAST(self, p[1], p[2], ast.PairListAST(self), p[4], |
| False) |
| |
| def p_obj_decl__3(self, p): |
| "obj_decl : type STAR ident ASSIGN expr SEMI" |
| p[0] = ast.ObjDeclAST(self, p[1], p[3], ast.PairListAST(self), p[5], |
| True) |
| |
| # Function definition and declaration |
| def p_decl__func_decl(self, p): |
| "decl : func_decl" |
| p[0] = p[1] |
| |
| def p_func_decl__0(self, p): |
| """func_decl : void ident '(' params ')' pairs SEMI |
| | type ident '(' params ')' pairs SEMI""" |
| p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None) |
| |
| def p_func_decl__1(self, p): |
| """func_decl : void ident '(' types ')' pairs SEMI |
| | type ident '(' types ')' pairs SEMI""" |
| p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None) |
| |
| def p_decl__func_def(self, p): |
| "decl : func_def" |
| p[0] = p[1] |
| |
| def p_func_def__0(self, p): |
| """func_def : void ident '(' params ')' pairs statements |
| | type ident '(' params ')' pairs statements""" |
| p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7]) |
| |
| # Enum fields |
| def p_type_enums__list(self, p): |
| "type_enums : type_enum type_enums" |
| p[0] = [ p[1] ] + p[2] |
| |
| def p_type_enums__empty(self, p): |
| "type_enums : empty" |
| p[0] = [] |
| |
| def p_type_enum(self, p): |
| "type_enum : ident pairs SEMI" |
| p[0] = ast.TypeFieldEnumAST(self, p[1], p[2]) |
| |
| # States |
| def p_type_states__list(self, p): |
| "type_states : type_state type_states" |
| p[0] = [ p[1] ] + p[2] |
| |
| def p_type_states__empty(self, p): |
| "type_states : empty" |
| p[0] = [] |
| |
| def p_type_state(self, p): |
| "type_state : ident ',' enumeration pairs SEMI" |
| p[0] = ast.TypeFieldStateAST(self, p[1], p[3], p[4]) |
| |
| # Formal Param |
| def p_params__many(self, p): |
| "params : param ',' params" |
| p[0] = [ p[1] ] + p[3] |
| |
| def p_params__one(self, p): |
| "params : param" |
| p[0] = [ p[1] ] |
| |
| def p_params__none(self, p): |
| "params : empty" |
| p[0] = [] |
| |
| def p_param(self, p): |
| "param : type ident" |
| p[0] = ast.FormalParamAST(self, p[1], p[2]) |
| |
| def p_param__pointer(self, p): |
| "param : type STAR ident" |
| p[0] = ast.FormalParamAST(self, p[1], p[3], None, "PTR") |
| |
| def p_param__ref(self, p): |
| "param : type AMP ident" |
| p[0] = ast.FormalParamAST(self, p[1], p[3], None, "REF") |
| |
| def p_param__const_ref(self, p): |
| "param : CONST type AMP ident" |
| p[0] = ast.FormalParamAST(self, p[1], p[3], None, "CONST_REF") |
| |
| def p_param__pointer_default(self, p): |
| "param : type STAR ident ASSIGN STRING" |
| p[0] = ast.FormalParamAST(self, p[1], p[3], p[5], "PTR") |
| |
| def p_param__default_number(self, p): |
| "param : type ident ASSIGN NUMBER" |
| p[0] = ast.FormalParamAST(self, p[1], p[2], p[4]) |
| |
| def p_param__default_bool(self, p): |
| "param : type ident ASSIGN LIT_BOOL" |
| p[0] = ast.FormalParamAST(self, p[1], p[2], p[4]) |
| |
| def p_param__default_string(self, p): |
| "param : type ident ASSIGN STRING" |
| p[0] = ast.FormalParamAST(self, p[1], p[2], p[4]) |
| |
| # Type |
| def p_types__multiple(self, p): |
| "types : type ',' types" |
| p[0] = [ p[1] ] + p[3] |
| |
| def p_types__one(self, p): |
| "types : type" |
| p[0] = [ p[1] ] |
| |
| def p_types__empty(self, p): |
| "types : empty" |
| p[0] = [] |
| |
| def p_typestr__multi(self, p): |
| "typestr : typestr DOUBLE_COLON ident" |
| p[0] = '%s::%s' % (p[1], p[3]) |
| |
| def p_typestr__single(self, p): |
| "typestr : ident" |
| p[0] = p[1] |
| |
| def p_type__one(self, p): |
| "type : typestr" |
| p[0] = ast.TypeAST(self, p[1]) |
| |
| def p_void(self, p): |
| "void : VOID" |
| p[0] = ast.TypeAST(self, p[1]) |
| |
| # Idents and lists |
| def p_idents__braced(self, p): |
| "idents : '{' identx '}'" |
| p[0] = p[2] |
| |
| def p_idents__bare(self, p): |
| "idents : ident" |
| p[0] = [ p[1] ] |
| |
| def p_identx__multiple_1(self, p): |
| """identx : ident SEMI identx |
| | ident ',' identx""" |
| p[0] = [ p[1] ] + p[3] |
| |
| def p_identx__multiple_2(self, p): |
| "identx : ident identx" |
| p[0] = [ p[1] ] + p[2] |
| |
| def p_identx__single(self, p): |
| "identx : empty" |
| p[0] = [ ] |
| |
| def p_ident(self, p): |
| "ident : IDENT" |
| p[0] = p[1] |
| |
| def p_ident_or_star(self, p): |
| """ident_or_star : ident |
| | STAR""" |
| p[0] = p[1] |
| |
| # Pair and pair lists |
| def p_pairs__list(self, p): |
| "pairs : ',' pairsx" |
| p[0] = p[2] |
| |
| def p_pairs__empty(self, p): |
| "pairs : empty" |
| p[0] = ast.PairListAST(self) |
| |
| def p_pairsx__many(self, p): |
| "pairsx : pair ',' pairsx" |
| p[0] = p[3] |
| p[0].addPair(p[1]) |
| |
| def p_pairsx__one(self, p): |
| "pairsx : pair" |
| p[0] = ast.PairListAST(self) |
| p[0].addPair(p[1]) |
| |
| def p_pair__assign(self, p): |
| """pair : ident '=' STRING |
| | ident '=' ident |
| | ident '=' NUMBER""" |
| p[0] = ast.PairAST(self, p[1], p[3]) |
| |
| def p_pair__literal(self, p): |
| "pair : STRING" |
| p[0] = ast.PairAST(self, "short", p[1]) |
| |
| # Below are the rules for action descriptions |
| def p_statements__inner(self, p): |
| "statements : '{' statements_inner '}'" |
| p[0] = ast.StatementListAST(self, p[2]) |
| |
| def p_statements__none(self, p): |
| "statements : '{' '}'" |
| p[0] = ast.StatementListAST(self, []) |
| |
| def p_statements_inner__many(self, p): |
| "statements_inner : statement statements_inner" |
| p[0] = [ p[1] ] + p[2] |
| |
| def p_statements_inner__one(self, p): |
| "statements_inner : statement" |
| p[0] = [ p[1] ] |
| |
| def p_exprs__multiple(self, p): |
| "exprs : expr ',' exprs" |
| p[0] = [ p[1] ] + p[3] |
| |
| def p_exprs__one(self, p): |
| "exprs : expr" |
| p[0] = [ p[1] ] |
| |
| def p_exprs__empty(self, p): |
| "exprs : empty""" |
| p[0] = [] |
| |
| def p_statement__expression(self, p): |
| "statement : expr SEMI" |
| p[0] = ast.ExprStatementAST(self, p[1]) |
| |
| def p_statement__assign(self, p): |
| "statement : expr ASSIGN expr SEMI" |
| p[0] = ast.AssignStatementAST(self, p[1], p[3]) |
| |
| def p_statement__enqueue(self, p): |
| "statement : ENQUEUE '(' var ',' type ')' statements" |
| p[0] = ast.EnqueueStatementAST(self, p[3], p[5], None, p[7]) |
| |
| def p_statement__enqueue_latency(self, p): |
| "statement : ENQUEUE '(' var ',' type ',' expr ')' statements" |
| p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9]) |
| |
| def p_statement__defer_enqueueing(self, p): |
| "statement : DEFER_ENQUEUEING '(' var ',' type ')' statements" |
| p[0] = ast.DeferEnqueueingStatementAST(self, p[3], p[5], p[7]) |
| |
| def p_statement__stall_and_wait(self, p): |
| "statement : STALL_AND_WAIT '(' var ',' var ')' SEMI" |
| p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5]) |
| |
| def p_statement__peek(self, p): |
| "statement : PEEK '(' var ',' type pairs ')' statements" |
| p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek") |
| |
| def p_statement__check_allocate(self, p): |
| "statement : CHECK_ALLOCATE '(' var ')' SEMI" |
| p[0] = ast.CheckAllocateStatementAST(self, p[3]) |
| |
| def p_statement__check_next_cycle(self, p): |
| "statement : CHECK_NEXT_CYCLE '(' ')' SEMI" |
| p[0] = ast.CheckNextCycleAST(self) |
| |
| def p_statement__check_stop(self, p): |
| "statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI" |
| p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7]) |
| |
| def p_statement__check_probe(self, p): |
| "statement : CHECK_PROBE '(' var ',' var ')' SEMI" |
| p[0] = ast.CheckProbeStatementAST(self, p[3], p[5]) |
| |
| def p_statement__return(self, p): |
| "statement : RETURN expr SEMI" |
| p[0] = ast.ReturnStatementAST(self, p[2]) |
| |
| def p_statement__if(self, p): |
| "statement : if_statement" |
| p[0] = p[1] |
| |
| def p_if_statement__if(self, p): |
| "if_statement : IF '(' expr ')' statements" |
| p[0] = ast.IfStatementAST(self, p[3], p[5], None) |
| |
| def p_if_statement__if_else(self, p): |
| "if_statement : IF '(' expr ')' statements ELSE statements" |
| p[0] = ast.IfStatementAST(self, p[3], p[5], p[7]) |
| |
| def p_statement__if_else_if(self, p): |
| "if_statement : IF '(' expr ')' statements ELSE if_statement" |
| p[0] = ast.IfStatementAST(self, p[3], p[5], |
| ast.StatementListAST(self, p[7])) |
| |
| def p_expr__static_cast(self, p): |
| "aexpr : STATIC_CAST '(' type ',' expr ')'" |
| p[0] = ast.StaticCastAST(self, p[3], "ref", p[5]) |
| |
| def p_expr__static_cast_ptr(self, p): |
| "aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'" |
| p[0] = ast.StaticCastAST(self, p[3], p[5], p[7]) |
| |
| def p_expr__var(self, p): |
| "aexpr : var" |
| p[0] = p[1] |
| |
| def p_expr__localvar(self, p): |
| "aexpr : type ident" |
| p[0] = ast.LocalVariableAST(self, p[1], p[2]) |
| |
| def p_expr__literal(self, p): |
| "aexpr : literal" |
| p[0] = p[1] |
| |
| def p_expr__enumeration(self, p): |
| "aexpr : enumeration" |
| p[0] = p[1] |
| |
| def p_expr__func_call(self, p): |
| "aexpr : ident '(' exprs ')'" |
| p[0] = ast.FuncCallExprAST(self, p[1], p[3]) |
| |
| def p_expr__new(self, p): |
| "aexpr : NEW type" |
| p[0] = ast.NewExprAST(self, p[2]) |
| |
| def p_expr__null(self, p): |
| "aexpr : OOD" |
| p[0] = ast.OodAST(self) |
| |
| def p_expr__member(self, p): |
| "aexpr : aexpr DOT ident" |
| p[0] = ast.MemberExprAST(self, p[1], p[3]) |
| |
| def p_expr__member_method_call(self, p): |
| "aexpr : aexpr DOT ident '(' exprs ')'" |
| p[0] = ast.MemberMethodCallExprAST(self, p[1], |
| ast.FuncCallExprAST(self, p[3], p[5])) |
| |
| def p_expr__member_method_call_lookup(self, p): |
| "aexpr : aexpr '[' exprs ']'" |
| p[0] = ast.MemberMethodCallExprAST(self, p[1], |
| ast.FuncCallExprAST(self, "lookup", p[3])) |
| |
| def p_expr__class_method_call(self, p): |
| "aexpr : type DOUBLE_COLON ident '(' exprs ')'" |
| p[0] = ast.ClassMethodCallExprAST(self, p[1], |
| ast.FuncCallExprAST(self, p[3], p[5])) |
| |
| def p_expr__aexpr(self, p): |
| "expr : aexpr" |
| p[0] = p[1] |
| |
| def p_expr__binary_op(self, p): |
| """expr : expr STAR expr |
| | expr SLASH expr |
| | expr MOD expr |
| | expr PLUS expr |
| | expr DASH expr |
| | expr LT expr |
| | expr GT expr |
| | expr LE expr |
| | expr GE expr |
| | expr EQ expr |
| | expr NE expr |
| | expr AND expr |
| | expr OR expr |
| | expr RIGHTSHIFT expr |
| | expr LEFTSHIFT expr""" |
| p[0] = ast.InfixOperatorExprAST(self, p[1], p[2], p[3]) |
| |
| # FIXME - unary not |
| def p_expr__unary_op(self, p): |
| """expr : NOT expr |
| | INCR expr |
| | DECR expr |
| | DASH expr %prec UMINUS""" |
| p[0] = ast.PrefixOperatorExprAST(self, p[1], p[2]) |
| |
| def p_expr__parens(self, p): |
| "aexpr : '(' expr ')'" |
| p[0] = p[2] |
| |
| def p_expr__is_valid_ptr(self, p): |
| "aexpr : IS_VALID '(' var ')'" |
| p[0] = ast.IsValidPtrExprAST(self, p[3], True) |
| |
| def p_expr__is_invalid_ptr(self, p): |
| "aexpr : IS_INVALID '(' var ')'" |
| p[0] = ast.IsValidPtrExprAST(self, p[3], False) |
| |
| def p_literal__string(self, p): |
| "literal : STRING" |
| p[0] = ast.LiteralExprAST(self, p[1], "std::string") |
| |
| def p_literal__number(self, p): |
| "literal : NUMBER" |
| p[0] = ast.LiteralExprAST(self, p[1], "int") |
| |
| def p_literal__float(self, p): |
| "literal : FLOATNUMBER" |
| p[0] = ast.LiteralExprAST(self, p[1], "int") |
| |
| def p_literal__bool(self, p): |
| "literal : LIT_BOOL" |
| p[0] = ast.LiteralExprAST(self, p[1], "bool") |
| |
| def p_enumeration(self, p): |
| "enumeration : ident ':' ident" |
| p[0] = ast.EnumExprAST(self, ast.TypeAST(self, p[1]), p[3]) |
| |
| def p_var(self, p): |
| "var : ident" |
| p[0] = ast.VarExprAST(self, p[1]) |