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 &parameters=
        type.find(ID_parameters).get_sub();

      namespacet ns(symbol_table);

      if(parameters.size()==1)
      {
        const exprt &parameter=(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;
        }
      }
    }
  }
}
Exemple #2
0
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;
}
Exemple #3
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;
}
Exemple #4
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;
}