def p_expression_binop(self, p): '''expression : expression PLUS expression | expression MINUS expression | expression STAR expression | expression DIVIDE expression''' t = None if p[2] == '+': t = Token('PLUS', '+') elif p[2] == '-': t = Token('MINUS', '-') elif p[2] == '*': t = Token('MUL', '*') elif p[2] == '/': t = Token('DIV', '/') p[0] = BinOp(p[1], p[3], t) check_direct_access(p[1]) check_direct_access(p[3]) if p[1].dtype != p[3].dtype or\ p[1].dtype[1] != 0 or\ p[1].dtype[0] == 'void': print_op_error(p[2], p[1].dtype, p[3].dtype) p[0].dtype = p[1].dtype
def p_logical_expression_binop(self, p): '''logical_expression : expression LT expression | expression LE expression | expression GT expression | expression GE expression | expression EQ expression | expression NE expression | logical_expression BOOL_AND logical_expression | logical_expression BOOL_OR logical_expression''' t = None if p[2] == '<': t = Token('LT', p[2]) elif p[2] == '<=': t = Token('LE', p[2]) elif p[2] == '>': t = Token('GT', p[2]) elif p[2] == '>=': t = Token('GE', p[2]) elif p[2] == '==': t = Token('EQ', p[2]) elif p[2] == '!=': t = Token('NE', p[2]) elif p[2] == '&&': t = Token('AND', p[2]) elif p[2] == '||': t = Token('OR', p[2]) p[0] = BinOp(p[1], p[3], t)
def p_expression_binop(self, p): '''expression : expression PLUS expression | expression MINUS expression | expression STAR expression | expression DIVIDE expression''' t = None if p[2] == '+': t = Token('PLUS', '+') elif p[2] == '-': t = Token('MINUS', '-') elif p[2] == '*': t = Token('MUL', '*') elif p[2] == '/': t = Token('DIV', '/') p[0] = BinOp(p[1], p[3], t)
def p_logical_expression_not(self, p): '''logical_expression : BOOL_NOT logical_expression''' t = Token('NOT', '!') p[0] = UnaryOp(p[2], t) if p[2].dtype != ('bool', 0): print('invalid usage of operator logical NOT.') sys.exit(0) p[0].dtype = ('bool', 0)
def p_body(p): """ body : | declarations | declarations decl_annotations """ if len(p) == 1: # empty metadata p[0] = Token(fields=list(), annotations=list()) if len(p) == 2: p[0] = Token(fields=p[1], annotations=list()) elif len(p) == 3: for anno in p[2]: if anno.name not in Annotation.STRUCT: print( "\nLine %d: Error, '%s' is not a " "valid struct annotation" % (anno.lineno, anno.name)), raise SyntaxError p[0] = Token(fields=p[1], annotations=p[2])
def p_assignment_id(self, p): '''assignment : id EQUALS expression''' # check if expression has only const leaves if not p[3].const_leaves: t = Token('ASGN', '=') p[0] = BinOp(p[1], p[3], t) else: print('Syntax error at %s =\n' % (p[1].token.value)) sys.exit(0)
def split_expr(self, expr_ast): if isinstance(expr_ast, BinOp): tl = self.split_expr(expr_ast.left_child) tr = self.split_expr(expr_ast.right_child) if expr_ast.token.type == 'ASGN': self.temp_body.append(BinOp(tl, tr, expr_ast.token)) return None temp_var = Var('t' + str(self.temp_count + self.temp_start)) self.temp_count += 1 self.temp_body.append( BinOp(temp_var, BinOp(tl, tr, expr_ast.token), Token('ASGN', '='))) return temp_var elif isinstance(expr_ast, UnaryOp): if expr_ast.token.type in ('NOT', 'UMINUS'): t = self.split_expr(expr_ast.child) temp_var = Var('t' + str(self.temp_count + self.temp_start)) self.temp_count += 1 self.temp_body.append( BinOp(temp_var, UnaryOp(t, expr_ast.token), Token('ASGN', '='))) return temp_var else: t = self.split_expr(expr_ast.child) return UnaryOp(t, expr_ast.token) elif isinstance(expr_ast, FunctionCall): t_params = [self.split_expr(x) for x in expr_ast.actual_params] # temp_var = Var('t' + str(self.temp_count + self.temp_start)) # self.temp_count += 1 # self.temp_body.append(BinOp(temp_var, FunctionCall(expr_ast.id, t_params), Token('ASGN', '='))) # return temp_var return FunctionCall(expr_ast.id, t_params) else: return expr_ast
def p_lhs(self, p): '''lhs : STAR lhs''' t = Token('DEREF', p[1]) p[0] = UnaryOp(p[2], t) dtype = p[2].dtype if dtype[1] <= 0: print('invalid usage of pointer.') sys.exit(0) p[0].dtype = (dtype[0], dtype[1] - 1)
def p_exression_deref(self, p): '''expression : STAR expression''' t = Token('DEREF', p[1]) p[0] = UnaryOp(p[2], t) dtype = p[2].dtype if dtype[1] <= 0: print('invalid usage of pointer.') sys.exit(0) p[0].dtype = (dtype[0], dtype[1] - 1)
def p_assignment_lhs(self, p): '''assignment : lhs EQUALS expression''' t = Token('ASGN', '=') p[0] = BinOp(p[1], p[3], t) check_direct_access(p[1]) check_direct_access(p[3]) if p[1].dtype != p[3].dtype: print_op_error(p[2], p[1].dtype, p[3].dtype) p[0].dtype = p[1].dtype
def p_addr(self, p): '''addr : AND id''' if p[2].entry['type'] == 'function': print('invalid usage of function %s.' % (p[2].value)) sys.exit(0) t = Token('ADDR', p[1]) p[0] = UnaryOp(p[2], t) dtype = p[2].entry['type'] p[0].dtype = (dtype[0], dtype[1] + 1)
def p_expression_uminus(self, p): '''expression : MINUS expression %prec UMINUS''' t = Token('UMINUS', '-') p[0] = UnaryOp(p[2], t) check_direct_access(p[2]) dtype = p[2].dtype if dtype[0] == 'void' or dtype[1] != 0: print( 'invalid use of operator unary minus on expression of type: ', dtype) sys.exit(0) p[0].dtype = dtype
def p_logical_expression_binop(self, p): '''logical_expression : expression LT expression | expression LE expression | expression GT expression | expression GE expression | expression EQ expression | expression NE expression | logical_expression BOOL_AND logical_expression | logical_expression BOOL_OR logical_expression''' t = None if p[2] == '<': t = Token('LT', p[2]) elif p[2] == '<=': t = Token('LE', p[2]) elif p[2] == '>': t = Token('GT', p[2]) elif p[2] == '>=': t = Token('GE', p[2]) elif p[2] == '==': t = Token('EQ', p[2]) elif p[2] == '!=': t = Token('NE', p[2]) elif p[2] == '&&': t = Token('AND', p[2]) elif p[2] == '||': t = Token('OR', p[2]) p[0] = BinOp(p[1], p[3], t) check_direct_access(p[1]) check_direct_access(p[3]) if p[1].dtype != p[3].dtype or\ p[1].dtype[1] != 0 or\ p[1].dtype[0] == 'void': print_op_error(p[2], p[1].dtype, p[3].dtype) p[0].dtype = ('bool', 0)
def p_declaration_inline_aggregate_field(p): """ declaration : opt_field_annotations opt_qualifiers user_defined \ opt_attribute opt_ident \ '{' declarations '}' \ opt_qualifiers opt_attribute \ opt_variables semicolons """ if p[3] not in ["struct", "union"]: print( "\nLine %d: Syntax error at token '%s', must be struct or " "union" % (p.lineno(3), p[3])), raise SyntaxError if p[5] == "": name = p[3] else: name = "%s %s" % (p[3], p[5]) vars = p[11] if len(vars) == 0: # using '}' as its lineno vars.append(Token(name="", lineno=p.lineno(8))) p[0] = create_fields(p[2] + Inner(name, p[7]) + p[9], p[1], vars)
def p_body_annotations_only(p): """ body : decl_annotations """ p[0] = Token(fields=list(), annotations=p[1])
def p_int(self, p): '''int : INTEGER''' t = Token('CONST', p[1]) p[0] = Const(t)
def p_addr(self, p): '''addr : AND deref_addr | AND id''' t = Token('ADDR', p[1]) p[0] = UnaryOp(p[2], t)
def p_deref(self, p): '''deref : STAR deref_addr | STAR id''' t = Token('DEREF', p[1]) p[0] = UnaryOp(p[2], t)
def p_expression_uminus(self, p): '''expression : MINUS expression %prec UMINUS''' t = Token('UMINUS', '-') p[0] = UnaryOp(p[2], t)
def p_assignment_deref(self, p): '''assignment : deref EQUALS expression''' t = Token('ASGN', '=') p[0] = BinOp(p[1], p[3], t) self.file.write(str(p[0]) + '\n')
def p_assignment_deref(self, p): '''assignment : deref EQUALS expression''' t = Token('ASGN', '=') p[0] = BinOp(p[1], p[3], t)
def p_id(self, p): '''id : ID''' t = Token('VAR', p[1]) p[0] = Var(t)
def p_variable_scalar(p): """ variable : IDENT """ p[0] = Token(name=p[1], lineno=p.lineno(1))
def p_variable_array(p): """ variable : IDENT dimensions """ p[0] = Token(name=p[1], size=p[2], lineno=p.lineno(1))
def p_logical_expression_not(self, p): '''logical_expression : BOOL_NOT logical_expression''' t = Token('NOT', '!') p[0] = UnaryOp(p[2], t)