def visit_function(self, func): type_info = self.current.lookup(func[1]) if not type_info: self.current.insert(func[1], func[2 : -1], True) elif type_info[-1]: raise SemanticError('redefinition of {}'.format(func[1])) elif type_info[0] == func[2]: self.current.insert(func[1], func[2 : -1]) self.visit_block(func[-1]) else: raise SemanticError('redefinition of {}'.format(func[1])) sym = SymbolTable(self.current) self.current = sym for p in func[3]: type_info = self.current.lookup(p[1]) if not type_info: self.current.insert(p[1], p[2]) else: raise SemanticError('redefininition of parameter ' + p[1]) self.visit_block(func[-1]) self.current = self.current.outer
def __rule(self, node): # 检查 type 是否是 void if node.type == 'void': self.errors.append(SemanticError('变量' + node.id + '不能定义为void类型')) if node.type == 'int': # 检查是否重定义 if symbol_table_pool.global_var_table.exist(node.id): self.errors.append(SemanticError('变量' + node.id + '重定义'))
def visit_function_declaration(self, var): type_info = self.current.lookup(var[1], check_outer=False) if not type_info: self.current.insert(var[1], var[2:]) elif type_info[0] == var[2]: raise SemanticError('redefinition of {}'.format(var[1])) elif type_info[0] != var[1]: raise SemanticError('conflicting types for {}'.format(var[1]))
def visit_declaration(self, var): type_info = self.current.lookup(var[1], check_outer=False) if not type_info: self.current.insert(var[1], var[2:]) if var[2] == 'void': raise SemanticError('identifier ' + var[1] + ' cannot be void') elif type_info[0] == var[2]: raise SemanticError('redefinition of {}'.format(var[1])) elif type_info[0] != var[1]: raise SemanticError('conflicting types for {}'.format(var[1])) if var[-1]: self.visit_expr(var[-1])
def visit_call(self, func): type_info = self.current.lookup(func[1]) if not type_info: raise SemanticError('undefined reference to {}'.format(func[1])) elif len(type_info[1]) > len(func[2]): raise SemanticError('too few arguments to {}'.format(func[1])) elif len(type_info[1]) < len(func[2]): raise SemanticError('too many arguments to {}'.format(func[1])) for p in func[2]: type_info = self.current.lookup(p[1]) if not type_info: raise SemanticError('undefined reference to ' + p[1])
def __init__(self, cc_object): if "profile" in cc_object: try: self.__profile = raw.entity.MediaDescriptionProto.from_string( str(cc_object["profile"])) except ParseError: raise SemanticError("Error CC value profile " + repr(cc_object["profile"])) else: self.__profile = DEFAULT_PROFILE self.__ice = ("ice" in cc_object) and cc_object["ice"] is True self.__ssrc_required = ( "ssrcRequired" in cc_object) and cc_object["ssrcRequired"] is True self.__bundle = ("bundle" in cc_object) and cc_object["bundle"] is True self.__rtcp_mux = ("rtcpMux" in cc_object) and cc_object["rtcpMux"] is True if "audio" in cc_object: self.__audio_codecs = [ self.__parse_codec(str(str_codec), MediaType.AUDIO) for str_codec in cc_object["audio"] ] if "video" in cc_object: self.__video_codecs = [ self.__parse_codec(str(str_codec), MediaType.VIDEO) for str_codec in cc_object["video"] ]
def __init__(self, sdp): assert type(sdp) is session_description.SessionDescription groups = sdp.raw_sdp.attributes.get("group") if len(groups) >= 1: raise SemanticError("More then one crypto in SDP") self.__sdp = sdp self.__attribute = groups[0] if len(groups) == 1 else None
def __init__(self, attributes): assert type(attributes) is AttributeCollection self.__attributes = attributes mids = self.__attributes.get("mid") if len(mids) > 1: raise SemanticError("More than one mid attribute") self.__attribute = mids[0] if len(mids) == 1 else None
def __init__(self, attributes): assert type(attributes) is AttributeCollection self.__attributes = attributes cryptos = attributes.get("crypto") if len(cryptos) > 1: raise SemanticError("More then one crypto in SDP: " + str(len(cryptos))) self.__attribute = cryptos[0] if len(cryptos) == 1 else None
def __rule(self, node): if node.children[0].type == 'void': self.errors.append( SemanticError('变量' + node.children[1].lexical + '不能定义为void类型')) if node.children[0].type == 'int': if symbol_table_pool.query(node.fun).exist( node.children[1].lexical): self.errors.append( SemanticError('变量' + node.children[1].lexical + '重定义')) else: if node.children[2].type == 'var': symbol_table_pool.query(node.fun).append( LocalVar(node.children[1].lexical, 'int', 4, False)) if node.children[2].type == 'array': symbol_table_pool.query(node.fun).append( LocalVar(node.children[1].lexical, 'array', 4 * node.children[2].length, False))
def __init__(self, attributes): assert type(attributes) is AttributeCollection self.__attributes = attributes directions = self.__attributes.get( ("recvonly", "sendrecv", "inactive", "sendonly")) if len(directions) > 1: raise SemanticError("More than one direction attribute") self.__attribute = directions[0] if len(directions) == 1 else None
def __rule(self, node): # 先判断 type 是否为 void if node.children[0].type == 'void': self.errors.append( SemanticError('参数' + node.children[1].lexical + '不能定义为void类型')) if node.children[0].type == 'int': # 判断是否重定义 if symbol_table_pool.query(node.fun).exist( node.children[1].lexical): self.errors.append( SemanticError('参数' + node.children[1].lexical + '重定义')) else: if node.children[2].type == 'array': symbol_table_pool.query(node.fun).append( LocalVar(node.children[1].lexical, 'address', 4, True)) if node.children[2].type == 'var': symbol_table_pool.query(node.fun).append( LocalVar(node.children[1].lexical, 'int', 4, True))
def __rule(self, node): if symbol_table_pool.query( node.id).get_params_num() != node.children[0].num: self.errors.append( SemanticError('函数体' + node.fun + '调用' + node.id + '的时候,参数数量不匹配')) else: for c in node.children[0].code: node.code.append(c)
def visit_program(self, prog): jt = { 'DECLARE': self.visit_global_declaration, 'DECL_FUNC': self.visit_function_declaration, 'FUNCTION': self.visit_function, 'STRUCT': lambda x: False, 'DECL_STRUCT': lambda x: False } for statement in prog[-1]: if not statement[0] in jt.keys(): raise SemanticError('expected declaration') jt[statement[0]](statement)
def __parse_codec(self, string, media_type): """ Parse string in serdes: encoding-name/clock-rate[/channels] """ assert type(string) is str assert type(media_type) is MediaType g = re.match("^([\w\d\-]+)/(\d+)(?:/(\d+))?$", string) if not g: raise SemanticError("Error codec in Cc: " + repr(string)) return Codec(encoding_name=g.group(1), clock_rate=int(g.group(2)), channels=(int(g.group(3)) if g.group(3) else 1), media_type=media_type)
def __rule(self, node): if not node.children[2].bool: self.errors.append(SemanticError('if-结构中的表达式不是bool表达式')) else: for c in node.children[2].code: node.code.append(c) if_block = get_temp_block_name() else_block = get_temp_block_name() next_block = get_temp_block_name() node.code.append('if ' + node.children[2].name + ' goto ' + if_block) node.code.append(else_block + ':') for c in node.children[7].code: node.code.append(c) node.code.append('goto ' + next_block) node.code.append(if_block + ':') for c in node.children[5].code: node.code.append(c) node.code.append('goto ' + next_block) node.code.append(next_block + ':')
def create_codec_from_attributes(media_type, payload_type, attributes): """ TODO: use imageattr and fmtp to create Codec """ assert type(media_type) is MediaType assert type(payload_type) is int assert type(attributes) is AttributeCollection pt_filter = lambda attr: attr.value.payload_type == payload_type rtpmaps = filter(pt_filter, attributes.get("rtpmap")) fmtps = filter(pt_filter, attributes.get("fmtp")) imageattrs = filter(pt_filter, attributes.get("imageattr")) if len(rtpmaps) > 1 or len(fmtps) > 1 or len(imageattrs) > 1: raise SemanticError("Too many sdp entries for one media " + repr(payload_type)) rtpmap = rtpmaps[0] if len(rtpmaps) == 1 else None fmtp = fmtps[0] if len(fmtps) == 1 else None imageattr = imageattrs[0] if len(imageattrs) == 1 else None # # in case of codec does not have rtpmap entry and its payload type is unknown # if rtpmap is not None: rtp_codec = RtpCodec(Codec(media_type, rtpmap.value.encoding_name, rtpmap.value.clock_rate, rtpmap.value.channels or 1), payload_type) else: known_codecs = [rtp_codec for rtp_codec in KNOWN_RTP_CODECS if rtp_codec.payload_type == payload_type] if len(known_codecs) == 0: # In case of no entry in sdp there should be default value of payload type # in RTPMAP defaults raise UnknownCodecError(payload_type) assert len(known_codecs) == 1 rtp_codec = known_codecs[0] return rtp_codec
def error(self, error_code, token): return SemanticError( error_code=error_code, token=token, message=f'{error_code.value} -> {token}', )
def __rule(self, node): # 检查是否重定义 if symbol_table_pool.fun_table.exist(node.id): self.errors.append(SemanticError('函数名' + node.id + '重定义'))
def type_expr(self, ast, fnName): val = ast while isinstance(val, Expr_Node): val = val.expr() if isinstance(val, BinaryExp_Node): typ = self.type_binaryExpr(val, fnName) ast.setType(typ) val.setType(typ) ##might be redundant, might not be! return typ elif isinstance(val, Boolean_Node): typ = self.type_booleanNode(val, fnName) ast.setType(typ) val.setType(typ) return typ elif isinstance(val, Identifier_Node): typ = self.type_IdentifierNode(val, fnName) ast.setType(typ) val.setType(typ) return typ elif isinstance(val, If_Node): typ = self.type_ifNode(val, fnName) ast.setType(typ) val.setType(typ) return typ elif isinstance(val, Number_Node): typ = self.type_numberNode(val, fnName) ast.setType(typ) val.setType(typ) return typ elif isinstance(val, Negate_Node): typ = self.type_negateNode(val, fnName) ast.setType(typ) val.setType(typ) return typ elif isinstance(val, Negative_Node): typ = self.type_negativeNode(val, fnName) ast.setType(typ) val.setType(typ) return typ ## elif isinstance(val, NestedExpr_Node): ## typ = self.type_nestedNode(val, fnName) ## ast.setType(typ) ## val.setType(typ) ## return typ elif isinstance(val, Actuals_Node): typ = self.type_actualsNode(val, fnName) ast.setType(typ) val.setType(typ) return typ else: print("VAL", val, type(val)) msg = "Something somewhere went wrong." raise SemanticError(msg)
def __rule(self, node): if symbol_table_pool.query(node.fun).get_params_num() != 0: self.errors.append( SemanticError('函数体' + node.fun + '调用' + node.id + '的时候,参数数量不匹配'))
def visit_variable(self, var): type_info = self.current.lookup(var[1]) if not type_info: raise SemanticError('undefined variable {}'.format(var[1]))
def visit_assignment(self, var): type_info = self.current.lookup(var[1][1]) if not type_info: raise SemanticError('undefined variable {}'.format(var[1])) self.visit_expr(var[-1])