void cpp_typecheckt::find_constructor( const typet &start_dest_type, exprt &constructor_expr) { constructor_expr.make_nil(); source_locationt source_location=start_dest_type.source_location(); typet dest_type(start_dest_type); follow_symbol(dest_type); if(dest_type.id()!=ID_struct) return; const struct_typet::componentst &components= to_struct_type(dest_type).components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const struct_typet::componentt &component=*it; const typet &type=component.type(); if(type.find(ID_return_type).id()==ID_constructor) { const irept::subt ¶meters= type.find(ID_parameters).get_sub(); namespacet ns(symbol_table); if(parameters.size()==1) { const exprt ¶meter=(exprt &)parameters.front(); const typet &arg_type=parameter.type(); if(arg_type.id()==ID_pointer && type_eq(arg_type.subtype(), dest_type, ns)) { // found! const irep_idt &identifier= component.get(ID_name); if(identifier=="") throw "constructor without identifier"; constructor_expr=exprt(ID_symbol, type); constructor_expr.set(ID_identifier, identifier); constructor_expr.add_source_location()=source_location; return; } } } } }
int FirstFollow::main(){ //구조체 grammer 의sym_temp 객체 생성 grammer sym_temp; int i, j; //First 테이블 초기화 for(i=0;i<9;i++){ for(j=0;j<24;j++){ first[i][j]=0; } } for(i=0;i<9;i++){ // 비단말기호 , i번째 위치의 심볼 sym_temp.select=1; sym_temp.location=i; //첫번째 심볼함수 호출 first_symbol(sym_temp); } //Follow 테이블 초기화 for(i=0;i<9;i++){ for(j=0;j<23;j++){ follow[i][j]=0; } } //follow 의 시작 비단말기호와 $ 단말기호 값을 1로 follow[0][20]=1; //비단말기호 계산 for(i=0;i<9;i++){ //비단말기호 매개변수 follow_symbol(i); } return 0; }
int FirstFollow::follow_symbol(int NonTerminal){ //비단말기호 int i, j, k; //result[10] 변수 0으로 초기화 int result[22]; //구조체 grammer의 grammer_string[10] 선언 grammer grammer_string[10]; //i : 룰의 번호 for(i=0; i<23; i++){ //오른쪽의 심볼들 for(j=0; j<rule_v[i].rule_len; j++){ //오른쪽에 있는 룰 i 번째의 j 가 비단말 기호일 경우 if(rule_v[i].right[j].select == 1){ //오른쪽 i번째 룰 j 번째에 위치한 값이 매개변수로 받아온 비단말기호 값과 다르면 처음으로 돌아감 if(rule_v[i].right[j].location != NonTerminal) continue; //오른쪽 i번째 룰 j 번째에 위치한 값이 매개변수로 받아온 비단말기호 값과 같으면 수행함 //j 가 (오른쪽 i번째 룰 길이-1) 과 다르면 수행 => j 가 오른쪽 맨 끝 심볼이 아닐경우 // 예 // i = 5 라면 // T' -> *FT' (len=3) // j는 0 ~ 2 // j 가 0 1이라면 수행 if(j != rule_v[i].rule_len-1){ //k의 초기값 j+1, k 가 우측 i 번째 룰 길이와 같아질 때까지 증가 //j가 0일때 //k 는 1 k < 3 ; k ++ //grammer_string[0] = rule_v[5].right[1] //grammer_string[1] = rule_v[5].right[2] .. 이런 원리 //j가 1일때 //k 는 2 k < 3; k ++ //grammer_string[0] = rele_v[5].right[2] for(k=j+1; k<rule_v[i].rule_len; k++) //오른쪽 i번째 룰의 k 번째 위치 심볼의 값 - grammer_string[k-(j+1)]에 대입 grammer_string[k-(j+1)]=rule_v[i].right[k]; //첫번째 문자 계산 함수 first_string(grammer_string, rule_v[i].rule_len-(j+1), result); for(k=0; k<21; k++){ //받은 결과 result[k] 가 1이면 if(result[k] == 1) //팔로우 테이블에 [비단말기호 번호][K] 저장 follow[NonTerminal][k]=result[k]; } } //오른쪽 i번째 룰 j 번째에 위치한 값이 매개변수로 받아온 비단말기호 값과 같으면 처음으로 돌아감 if(rule_v[i].left.location == NonTerminal) continue; //result에 입실론이 포함되었거나, j가 우측 마지막 심볼이라면 if(result[21]==1 || j==rule_v[i].rule_len-1){ //왼쪽 i 번째 룰의 비단말기호 다시 호출 follow_symbol(rule_v[i].left.location); for(k=0; k<22; k++) //[왼쪽 i 번째 룰의 비단말기호 값][k] 가 1이면 if(follow[rule_v[i].left.location][k] == 1) //팔로우테이블의 [매개변수 비단말기호 Nonterminal][k] 에 대입 follow[NonTerminal][k]=follow[rule_v[i].left.location][k]; } } } } return 0; }
codet cpp_typecheckt::cpp_constructor( const source_locationt &source_location, const exprt &object, const exprt::operandst &operands) { exprt object_tc=object; typecheck_expr(object_tc); elaborate_class_template(object_tc.type()); typet tmp_type(object_tc.type()); follow_symbol(tmp_type); assert(!is_reference(tmp_type)); if(tmp_type.id()==ID_array) { // We allow only one operand and it must be tagged with '#array_ini'. // Note that the operand is an array that is used for copy-initialization. // In the general case, a program is not allow to use this form of // construct. This way of initializing an array is used internaly only. // The purpose of the tag #arra_ini is to rule out ill-formed // programs. if(!operands.empty() && !operands.front().get_bool("#array_ini")) { error().source_location=source_location; error() << "bad array initializer" << eom; throw 0; } assert(operands.empty() || operands.size()==1); if(operands.empty() && cpp_is_pod(tmp_type)) { codet nil; nil.make_nil(); return nil; } const exprt &size_expr= to_array_type(tmp_type).size(); if(size_expr.id()=="infinity") { // don't initialize codet nil; nil.make_nil(); return nil; } exprt tmp_size=size_expr; make_constant_index(tmp_size); mp_integer s; if(to_integer(tmp_size, s)) { error().source_location=source_location; error() << "array size `" << to_string(size_expr) << "' is not a constant" << eom; throw 0; } /*if(cpp_is_pod(tmp_type)) { code_expressiont new_code; exprt op_tc=operands.front(); typecheck_expr(op_tc); // Override constantness object_tc.type().set("#constant", false); object_tc.set("#lvalue", true); side_effect_exprt assign("assign"); assign.add_source_location()=source_location; assign.copy_to_operands(object_tc, op_tc); typecheck_side_effect_assignment(assign); new_code.expression()=assign; return new_code; } else*/ { codet new_code(ID_block); // for each element of the array, call the default constructor for(mp_integer i=0; i < s; ++i) { exprt::operandst tmp_operands; exprt constant=from_integer(i, index_type()); constant.add_source_location()=source_location; exprt index(ID_index); index.copy_to_operands(object); index.copy_to_operands(constant); index.add_source_location()=source_location; if(!operands.empty()) { exprt operand(ID_index); operand.copy_to_operands(operands.front()); operand.copy_to_operands(constant); operand.add_source_location()=source_location; tmp_operands.push_back(operand); } exprt i_code = cpp_constructor(source_location, index, tmp_operands); if(i_code.is_nil()) { new_code.is_nil(); break; } new_code.move_to_operands(i_code); } return new_code; } } else if(cpp_is_pod(tmp_type)) { code_expressiont new_code; exprt::operandst operands_tc=operands; for(exprt::operandst::iterator it=operands_tc.begin(); it!=operands_tc.end(); it++) { typecheck_expr(*it); add_implicit_dereference(*it); } if(operands_tc.empty()) { // a POD is NOT initialized new_code.make_nil(); } else if(operands_tc.size()==1) { // Override constantness object_tc.type().set(ID_C_constant, false); object_tc.set(ID_C_lvalue, true); side_effect_exprt assign(ID_assign); assign.add_source_location()=source_location; assign.copy_to_operands(object_tc, operands_tc.front()); typecheck_side_effect_assignment(assign); new_code.expression()=assign; } else { error().source_location=source_location; error() << "initialization of POD requires one argument, " "but got " << operands.size() << eom; throw 0; } return new_code; } else if(tmp_type.id()==ID_union) { assert(0); // Todo: union } else if(tmp_type.id()==ID_struct) { exprt::operandst operands_tc=operands; for(exprt::operandst::iterator it=operands_tc.begin(); it!=operands_tc.end(); it++) { typecheck_expr(*it); add_implicit_dereference(*it); } const struct_typet &struct_type= to_struct_type(tmp_type); // set most-derived bits codet block(ID_block); for(std::size_t i=0; i < struct_type.components().size(); i++) { const irept &component=struct_type.components()[i]; if(component.get(ID_base_name)!="@most_derived") continue; exprt member(ID_member, bool_typet()); member.set(ID_component_name, component.get(ID_name)); member.copy_to_operands(object_tc); member.add_source_location()=source_location; member.set(ID_C_lvalue, object_tc.get_bool(ID_C_lvalue)); exprt val=false_exprt(); if(!component.get_bool("from_base")) val=true_exprt(); side_effect_exprt assign(ID_assign); assign.add_source_location()=source_location; assign.move_to_operands(member, val); typecheck_side_effect_assignment(assign); code_expressiont code_exp; code_exp.expression()=assign; block.move_to_operands(code_exp); } // enter struct scope cpp_save_scopet save_scope(cpp_scopes); cpp_scopes.set_scope(struct_type.get(ID_name)); // find name of constructor const struct_typet::componentst &components= struct_type.components(); irep_idt constructor_name; for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &type=it->type(); if(!it->get_bool(ID_from_base) && type.id()==ID_code && type.find(ID_return_type).id()==ID_constructor) { constructor_name=it->get(ID_base_name); break; } } // there is always a constructor for non-PODs assert(constructor_name!=""); irept cpp_name(ID_cpp_name); cpp_name.get_sub().push_back(irept(ID_name)); cpp_name.get_sub().back().set(ID_identifier, constructor_name); cpp_name.get_sub().back().set(ID_C_source_location, source_location); side_effect_expr_function_callt function_call; function_call.add_source_location()=source_location; function_call.function().swap(static_cast<exprt&>(cpp_name)); function_call.arguments().reserve(operands_tc.size()); for(exprt::operandst::iterator it=operands_tc.begin(); it!=operands_tc.end(); it++) function_call.op1().copy_to_operands(*it); typecheck_side_effect_function_call(function_call); assert(function_call.get(ID_statement)==ID_temporary_object); exprt &initializer = static_cast<exprt &>(function_call.add(ID_initializer)); assert(initializer.id()==ID_code && initializer.get(ID_statement)==ID_expression); side_effect_expr_function_callt &func_ini= to_side_effect_expr_function_call(initializer.op0()); exprt &tmp_this=func_ini.arguments().front(); assert(tmp_this.id()==ID_address_of && tmp_this.op0().id()=="new_object"); exprt address_of(ID_address_of, typet(ID_pointer)); address_of.type().subtype()=object_tc.type(); address_of.copy_to_operands(object_tc); tmp_this.swap(address_of); if(block.operands().empty()) return to_code(initializer); else { block.move_to_operands(initializer); return block; } } else assert(false); codet nil; nil.make_nil(); return nil; }