In SLICC, in order to define a type a data type for which it should not generate any code, the keyword external_type is used. For those data types for which code should be generated, the keyword structure is used. This patch eliminates the use of keyword external_type for defining structures. structure key word can now have an optional attribute external, which would be used for figuring out whether or not to generate the code for this structure. Also, now structures can have functions as well data members in them.
741 lines
22 KiB
Python
741 lines
22 KiB
Python
# Copyright (c) 2009 The Hewlett-Packard Development Company
|
|
# 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.
|
|
#
|
|
# Authors: Nathan Binkert
|
|
|
|
import os.path
|
|
import re
|
|
import sys
|
|
|
|
from m5.util import code_formatter
|
|
from m5.util.grammar import Grammar, TokenError, ParseError
|
|
|
|
import slicc.ast as ast
|
|
import slicc.util as util
|
|
from slicc.symbols import SymbolTable
|
|
|
|
def read_slicc(sources):
|
|
if not isinstance(sources, (list,tuple)):
|
|
sources = [ sources ]
|
|
|
|
for source in sources:
|
|
for sm_file in file(source, "r"):
|
|
sm_file = sm_file.strip()
|
|
if not sm_file:
|
|
continue
|
|
if sm_file.startswith("#"):
|
|
continue
|
|
yield sm_file
|
|
|
|
class SLICC(Grammar):
|
|
def __init__(self, protocol, **kwargs):
|
|
super(SLICC, self).__init__(**kwargs)
|
|
self.decl_list_vec = []
|
|
self.current_file = None
|
|
self.protocol = protocol
|
|
self.symtab = SymbolTable(self)
|
|
|
|
def codeFormatter(self, *args, **kwargs):
|
|
code = code_formatter(*args, **kwargs)
|
|
code['protocol'] = self.protocol
|
|
return code
|
|
|
|
def parse(self, filename):
|
|
self.current_file = filename
|
|
f = file(filename, 'r')
|
|
text = f.read()
|
|
try:
|
|
decl_list = super(SLICC, self).parse(text)
|
|
except (TokenError, ParseError), e:
|
|
sys.exit("%s: %s:%d" % (e, filename, e.token.lineno))
|
|
self.decl_list_vec.append(decl_list)
|
|
self.current_file = None
|
|
|
|
def _load(self, *filenames):
|
|
filenames = list(filenames)
|
|
while filenames:
|
|
f = filenames.pop(0)
|
|
if isinstance(f, (list, tuple)):
|
|
filenames[0:0] = list(f)
|
|
continue
|
|
|
|
yield f
|
|
if f.endswith(".slicc"):
|
|
dirname,basename = os.path.split(f)
|
|
filenames[0:0] = [ os.path.join(dirname, x) \
|
|
for x in read_slicc(f)]
|
|
else:
|
|
assert f.endswith(".sm")
|
|
self.parse(f)
|
|
|
|
def load(self, *filenames, **kwargs):
|
|
verbose = kwargs.pop("verbose", False)
|
|
if kwargs:
|
|
raise TypeError
|
|
|
|
gen = self._load(*filenames)
|
|
if verbose:
|
|
return gen
|
|
else:
|
|
# Run out the generator if we don't want the verbosity
|
|
for foo in gen:
|
|
pass
|
|
|
|
def findMachines(self):
|
|
for decl_list in self.decl_list_vec:
|
|
decl_list.findMachines()
|
|
|
|
def generate(self):
|
|
for decl_list in self.decl_list_vec:
|
|
decl_list.generate()
|
|
|
|
def writeCodeFiles(self, code_path):
|
|
util.makeDir(code_path)
|
|
self.symtab.writeCodeFiles(code_path)
|
|
|
|
def writeHTMLFiles(self, code_path):
|
|
util.makeDir(code_path)
|
|
self.symtab.writeHTMLFiles(code_path)
|
|
|
|
def files(self):
|
|
f = set([
|
|
'MachineType.cc',
|
|
'MachineType.hh',
|
|
'Types.hh' ])
|
|
|
|
for decl_list in self.decl_list_vec:
|
|
f |= 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 = {
|
|
'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',
|
|
'copy_head' : 'COPY_HEAD',
|
|
'check_allocate' : 'CHECK_ALLOCATE',
|
|
'check_stop_slots' : 'CHECK_STOP_SLOTS',
|
|
'static_cast' : 'STATIC_CAST',
|
|
'if' : 'IF',
|
|
'is_valid' : 'IS_VALID',
|
|
'is_invalid' : 'IS_INVALID',
|
|
'else' : 'ELSE',
|
|
'return' : 'RETURN',
|
|
'THIS' : 'THIS',
|
|
'CHIP' : 'CHIP',
|
|
'void' : 'VOID',
|
|
'new' : 'NEW',
|
|
'OOD' : 'OOD',
|
|
}
|
|
|
|
literals = ':[]{}(),='
|
|
|
|
tokens = [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE',
|
|
'LEFTSHIFT', 'RIGHTSHIFT',
|
|
'NOT', 'AND', 'OR',
|
|
'PLUS', 'DASH', 'STAR', 'SLASH',
|
|
'DOUBLE_COLON', 'SEMI',
|
|
'ASSIGN', 'DOT',
|
|
'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ]
|
|
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_SLASH = r'/'
|
|
t_DOUBLE_COLON = r'::'
|
|
t_SEMI = r';'
|
|
t_ASSIGN = r':='
|
|
t_DOT = r'\.'
|
|
|
|
precedence = (
|
|
('left', 'AND', 'OR'),
|
|
('left', 'EQ', 'NE'),
|
|
('left', 'LT', 'GT', 'LE', 'GE'),
|
|
('left', 'RIGHTSHIFT', 'LEFTSHIFT'),
|
|
('left', 'PLUS', 'DASH'),
|
|
('left', 'STAR', 'SLASH'),
|
|
('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 TokenError("Illegal float", t)
|
|
return t
|
|
|
|
def t_NUMBER(self, t):
|
|
r'[0-9]+'
|
|
try:
|
|
t.value = int(t.value)
|
|
except ValueError:
|
|
raise TokenError("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"
|
|
p[0] = [ p[1] ] + p[2]
|
|
|
|
def p_declsx__none(self, p):
|
|
"declsx : empty"
|
|
p[0] = []
|
|
|
|
def p_decl__machine(self, p):
|
|
"decl : MACHINE '(' ident pairs ')' ':' params '{' 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 pairs ')' idents"
|
|
p[0] = ast.TransitionDeclAST(self, p[3], p[5], p[7], p[8], p[10])
|
|
|
|
def p_decl__trans1(self, p):
|
|
"decl : TRANS '(' idents ',' idents pairs ')' idents"
|
|
p[0] = ast.TransitionDeclAST(self, p[3], p[5], None, p[6], 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])
|
|
|
|
def p_decl__object(self, p):
|
|
"decl : type ident pairs SEMI"
|
|
p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3])
|
|
|
|
def p_decl__func_decl(self, p):
|
|
"""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_decl__func_def(self, p):
|
|
"""decl : 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])
|
|
|
|
# Type fields
|
|
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_method__0(self, p):
|
|
"type_member : type_or_void ident '(' types ')' pairs SEMI"
|
|
p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
|
|
|
|
def p_type_member__1(self, p):
|
|
"type_member : type_or_void ident pairs SEMI"
|
|
p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None)
|
|
|
|
def p_type_member__2(self, p):
|
|
"type_member : type_or_void ident ASSIGN expr SEMI"
|
|
p[0] = ast.TypeFieldMemberAST(self, p[1], p[2],
|
|
ast.PairListAST(self), p[4])
|
|
|
|
# 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])
|
|
|
|
# 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])
|
|
|
|
def p_type_or_void(self, p):
|
|
"""type_or_void : type
|
|
| void"""
|
|
p[0] = p[1]
|
|
|
|
# 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, True)
|
|
|
|
def p_param__pointer_default(self, p):
|
|
"param : type STAR ident '=' STRING"
|
|
p[0] = ast.FormalParamAST(self, p[1], p[3], p[5], True)
|
|
|
|
def p_param__default_number(self, p):
|
|
"param : type ident '=' NUMBER"
|
|
p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
|
|
|
|
def p_param__default_bool(self, p):
|
|
"param : type ident '=' LIT_BOOL"
|
|
p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
|
|
|
|
def p_param__default_string(self, p):
|
|
"param : type ident '=' STRING"
|
|
p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
|
|
|
|
# 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]
|
|
|
|
# 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 pairs ')' statements"
|
|
p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[6], p[8])
|
|
|
|
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__copy_head(self, p):
|
|
"statement : COPY_HEAD '(' var ',' var pairs ')' SEMI"
|
|
p[0] = ast.CopyHeadStatementAST(self, p[3], p[5], p[6])
|
|
|
|
def p_statement__check_allocate(self, p):
|
|
"statement : CHECK_ALLOCATE '(' var ')' SEMI"
|
|
p[0] = ast.CheckAllocateStatementAST(self, p[3])
|
|
|
|
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__static_cast(self, p):
|
|
"aexpr : STATIC_CAST '(' type ',' expr ')'"
|
|
p[0] = ast.StaticCastAST(self, p[3], "ref", p[5])
|
|
|
|
def p_statement__static_cast_ptr(self, p):
|
|
"aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'"
|
|
p[0] = ast.StaticCastAST(self, p[3], p[5], p[7])
|
|
|
|
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__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)
|
|
|
|
# globally access a local chip component and call a method
|
|
def p_expr__local_chip_method(self, p):
|
|
"aexpr : THIS DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
|
|
p[0] = ast.LocalChipMethodAST(self, p[3], p[5], p[8], p[10], p[12])
|
|
|
|
# globally access a local chip component and access a data member
|
|
def p_expr__local_chip_member(self, p):
|
|
"aexpr : THIS DOT var '[' expr ']' DOT var DOT field"
|
|
p[0] = ast.LocalChipMemberAST(self, p[3], p[5], p[8], p[10])
|
|
|
|
# globally access a specified chip component and call a method
|
|
def p_expr__specified_chip_method(self, p):
|
|
"aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
|
|
p[0] = ast.SpecifiedChipMethodAST(self, p[3], p[6], p[8], p[11], p[13],
|
|
p[15])
|
|
|
|
# globally access a specified chip component and access a data member
|
|
def p_expr__specified_chip_member(self, p):
|
|
"aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field"
|
|
p[0] = ast.SpecifiedChipMemberAST(self, p[3], p[6], p[8], p[11], p[13])
|
|
|
|
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], p[3], p[5])
|
|
|
|
def p_expr__member_method_call_lookup(self, p):
|
|
"aexpr : aexpr '[' exprs ']'"
|
|
p[0] = ast.MemberMethodCallExprAST(self, p[1], "lookup", p[3])
|
|
|
|
def p_expr__class_method_call(self, p):
|
|
"aexpr : type DOUBLE_COLON ident '(' exprs ')'"
|
|
p[0] = ast.ClassMethodCallExprAST(self, p[1], 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 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
|
|
| DASH expr %prec UMINUS"""
|
|
p[0] = PrefixOperatorExpr(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])
|
|
|
|
def p_field(self, p):
|
|
"field : ident"
|
|
p[0] = p[1]
|