Files
gem5/src/mem/slicc/parser.py
Daniel Kouchekinia 984499329d mem-ruby,configs: Add GLC Atomic Latency VIPER Parameter (#110)
Added a GLC atomic latency parameter (glc-atomic-latency) used when
enqueueing response messages regarding atomics directly performed in
the TCC. This latency is added in addition to the L2 response latency
(TCC_latency). This represents the latency of performing an atomic
within the L2.

With this change, the TCC response queue will receive enqueues with
varying latencies as GLC atomic responses will have this added GLC
atomic latency while data responses will not. To accommodate this in
light of the queue having strict FIFO ordering (which would be violated
here), this change also adds an optional parameter bypassStrictFIFO to
the SLICC enqueue function which allows overriding strict FIFO
requirements for individual messages on a case-by-case basis. This
parameter is only being used in the TCC's atomic response enqueue call.

Change-Id: Iabd52cbd2c0cc385c1fb3fe7bcd0cc64bdb40aac
2023-07-23 15:57:06 -05:00

823 lines
24 KiB
Python

# 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] = f"{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, 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], None, p[9])
def p_statement__enqueue_latency_bypass_strict_fifo(self, p):
"statement : ENQUEUE '(' var ',' type ',' expr ',' expr ')' statements"
p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9], p[11])
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])