| # Copyright (c) 2020,2021 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 code_formatter import code_formatter |
| from 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", |
| "wakeup_port": "WAKEUP_PORT", |
| "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__wakeup_port(self, p): |
| "statement : WAKEUP_PORT '(' var ',' var ')' SEMI" |
| p[0] = ast.WakeupPortStatementAST(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 '(' expr ')'" |
| p[0] = ast.IsValidPtrExprAST(self, p[3], True) |
| |
| def p_expr__is_invalid_ptr(self, p): |
| "aexpr : IS_INVALID '(' expr ')'" |
| 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]) |