예제 #1
0
void Semantic::traverse(Decl * cur) {
  if (cur->v == Decl::STRUCT_T) {
    newSym(sid, Symbol(cur->ID, cur)); //declared but not defined
    pre = false;
  }
  else if (cur->v == Decl::FUNC_T) {
    newSym(vid.back(), Symbol(cur->ID, cur)); //declared but not defined
    pre = false;
  }
  else if (cur->v == Decl::USE_LIT_T) {
    if (!pre) error("#use directives must all be on the top");
    //check if cur->ID file exists, parse it, cur parent gets this progitem appended
  }
  else if (cur->v == Decl::USE_LIB_T) {
    if (!pre) error("#use directives must all be on the top");
    //check if cur->ID file exists whithin include path, parse it, cur parent gets this progitem appended
  }
}
예제 #2
0
void Semantic::traverse(Defn * cur) {
  if (cur->v == Defn::STRUCT_T) {
    newSym(sid, Symbol(cur->id, cur));
    //check struct types and names pairwise to be distinct
    ArgItem * ptr = cur->args;
    std::set<std::string> ids;
    while (ptr != NULL) {
      valSctType(ptr->arg->type);
      if (ids.find(ptr->arg->ID) != ids.end())
	error("struct field names must be pairwise distinct");
      ptr = ptr->next;
    }
  }
  else if (cur->v == Defn::FUNC_T) {
    //check ret type
    valRetType(cur->type);

    newSym(vid.back(), Symbol(cur->id, cur));
    curF = cur->id;
    pushScope();
    
    //check args types and names
    ArgItem * ptr = cur->args;
    std::set<std::string> ids;
    while (ptr != NULL) {
      valArgType(ptr->arg->type);
      newSym(vid.back(), Symbol(ptr->arg->ID, cur->type));
      if (ids.find(ptr->arg->ID) != ids.end())
	error("argument names must be pairwise distinct");
      ptr = ptr->next;
    }
    pushScope();
    traverse(cur->stmts);
    popScope();
    popScope();
    curF = "";
  }
  else if (cur->v == Defn::TYPEDEF_T) {
    valArgType(cur->type);
    newSym(aid, Symbol(cur->id, cur));
  }
}
예제 #3
0
Table *check(Absyn * program, boolean showSymbolTables)
{
	Table *globalTable;
	Entry *e;
	globalTable = newTable(NULL);

	if (showSymbolTables) {
	  local_debug = TRUE;
	}

	/* generate built-in types */
	builtinType_int  = newPrimitiveType("int",  INT_BYTE_SIZE);
	builtinType_bool = newPrimitiveType("bool", BOOL_BYTE_SIZE);

	Entry *builtinProc_exit =
	    newProcEntry(emptyParamTypes(), newTable(globalTable), NULL);
	Entry *builtinProc_time =
	    newProcEntry(newParamTypes
			 (builtinType_int, TRUE, emptyParamTypes()),
			 newTable(globalTable), NULL);
	Entry *builtinProc_readi =
	    newProcEntry(newParamTypes
			 (builtinType_int, TRUE, emptyParamTypes()),
			 newTable(globalTable), NULL);
	Entry *builtinProc_readc =
	    newProcEntry(newParamTypes
			 (builtinType_int, TRUE, emptyParamTypes()),
			 newTable(globalTable), NULL);
	Entry *builtinProc_printi =
	    newProcEntry(newParamTypes
			 (builtinType_int, FALSE, emptyParamTypes()),
			 newTable(globalTable), NULL);
	Entry *builtinProc_printc =
	    newProcEntry(newParamTypes
			 (builtinType_int, FALSE, emptyParamTypes()),
			 newTable(globalTable), NULL);
	Entry *builtinProc_clearAll =
	    newProcEntry(newParamTypes
			 (builtinType_int, FALSE, emptyParamTypes()),
			 newTable(globalTable), NULL);
	Entry *builtinProc_setPixel =
	    newProcEntry(newParamTypes(builtinType_int, FALSE,
				       newParamTypes(builtinType_int, FALSE,
						     newParamTypes
						     (builtinType_int, FALSE,
						      emptyParamTypes()))),
			 newTable(globalTable), NULL);
	Entry *builtinProc_drawCircle =
	    newProcEntry(newParamTypes(builtinType_int, FALSE,
				       newParamTypes(builtinType_int, FALSE,
						     newParamTypes
						     (builtinType_int, FALSE,
						      newParamTypes
						      (builtinType_int, FALSE,
						       emptyParamTypes())))),
			 newTable(globalTable), NULL);
	Entry *builtinProc_drawLine =
	    newProcEntry(newParamTypes(builtinType_int, FALSE,
				       newParamTypes(builtinType_int, FALSE,
						     newParamTypes
						     (builtinType_int, FALSE,
						      newParamTypes
						      (builtinType_int, FALSE,
						       newParamTypes
						       (builtinType_int, FALSE,
							emptyParamTypes()))))),
			 newTable(globalTable), NULL);

	/* setup global symbol table */
	enter(globalTable, newSym("int"), newTypeEntry(builtinType_int));
	enter(globalTable, newSym("exit"), builtinProc_exit);
	enter(globalTable, newSym("time"), builtinProc_time);
	enter(globalTable, newSym("readi"), builtinProc_readi);
	enter(globalTable, newSym("readc"), builtinProc_readc);
	enter(globalTable, newSym("printi"), builtinProc_printi);
	enter(globalTable, newSym("printc"), builtinProc_printc);
	enter(globalTable, newSym("clearAll"), builtinProc_clearAll);
	enter(globalTable, newSym("setPixel"), builtinProc_setPixel);
	enter(globalTable, newSym("drawCircle"), builtinProc_drawCircle);
	enter(globalTable, newSym("drawLine"), builtinProc_drawLine);

	/* enter all procs into global symtable */
	enter_proc_decs(program, globalTable);

	/* do semantic checks */
	checkNode(program, globalTable);

	/* check if "main()" is present */
	e = lookup(globalTable, newSym("main"));
	if (e == NULL)
		error("procedure 'main' is missing");
	if (e->kind != ENTRY_KIND_PROC)
		error("'main' is not a procedure");
	// check that main has no params
	if (!e->u.procEntry.paramTypes->isEmpty)
		error("procedure 'main' must not have any parameters");

	/* return global symbol table */
	return globalTable;
}
예제 #4
0
void Semantic::traverse(Stmt * cur) {
  if (cur->v == Stmt::LIST_T) {
    pushScope();
    traverse(cur->list);
    popScope();
  }
  else if (cur->v == Stmt::IF_T || cur->v == Stmt::WHILE_T) {
    if (cur->v == Stmt::WHILE_T) loops.push(cur);
    Type t = expType(cur->exp);
    traverse(cur->exp);
    if (t.v == Type::INT_T || t.v == Type::CHAR_T) {
      //warning
      pushScope();
      traverse(cur->left);
      popScope();
    }
    else if (t.v == Type::BOOL_T) {
      pushScope();
      traverse(cur->left);
      popScope();
    }
    else
      error("Condition must be of type bool");
    if (cur->v == Stmt::WHILE_T) loops.pop();
  }
  else if (cur->v == Stmt::FOR_T) {
    loops.push(cur);
    pushScope();
    traverse(cur->left);
    Type t = expType(cur->exp);
    traverse(cur->exp);
    if (t.v == Type::INT_T || t.v == Type::CHAR_T) {
      //warning
      pushScope();
      traverse(cur->stmt);
      popScope();
    }
    else if (t.v == Type::BOOL_T) {
      pushScope();
      traverse(cur->stmt);
      popScope();
    }
    else
      error("Condition must be of type bool");
    if (hasDecl(cur->right))
      error("For loop-end statement must not include declarations");
    traverse(cur->right);
    popScope();
    loops.pop();
  }
  else if (cur->v == Stmt::RETURN_T) {
    //check current function return type and compare it with this
    if (!sameType(expType(cur->exp), *getSym(curF).defn->type))
      error("return expression type differs from function " + curF + " signature");
    if (cur->exp != NULL)
      traverse(cur->exp);
  }
  else if (cur->v == Stmt::ASSERT_T) {
    //check argument type to be of bool
    if (!sameType(expType(cur->exp), Type(Type::BOOL_T)))
      error("assert expression type must be bool");
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::ERROR_T) {
    //call error function with argment string
    if (!sameType(expType(cur->exp), Type(Type::STRING_T)))
      error("error argument must be of type string");
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::ASSIGN_T) {
    //check if lhs and rhs same type, ensure rhs and lhs is not a struct
    Type l = lvalType(cur->lval), r = expType(cur->exp);
    traverse(cur->exp);
    
    if (cur->op == "=") {
      if (!sameType(l, r))
	error("lval and expression have different types");
    }
    else if (cur->op == ">>=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from right shift must be of type int or char");
      if (!sameType(r, Type(Type::INT_T)))
	error("shift ammount must be of type int");
    }
    else if (cur->op == "<<=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from left shift must be of type int or char");
      if (!sameType(r, Type(Type::INT_T)))
	error("shift ammount must be of type int");
    }
    else if (cur->op == "+=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from add assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from add assign must be of type int or char");
    }
    else if (cur->op == "-=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from sub assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from sub assign must be of type int or char");
    }
    else if (cur->op == "*=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from mul assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from mul assign must be of type int or char");
    }
    else if (cur->op == "/=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from div assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from div assign must be of type int or char");
    }
    else if (cur->op == "%=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from mod assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from mod assign must be of type int or char");
    }
    else if (cur->op == "&=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from and assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from and assign must be of type int or char or bool");
    }
    else if (cur->op == "^=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from xor assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from xor assign must be of type int or char or bool");
    }
    else if (cur->op == "|=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from or assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from or assign must be of type int or char or bool");
    }
  }
  else if (cur->v == Stmt::INC_T) {
    //check if lhs is int or char
    Type l = lvalType(cur->lval);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
      error("lval from increment must be of type int or char");
    
  }
  else if (cur->v == Stmt::DEC_T) {
    //check if lhs is int or char
    Type l = lvalType(cur->lval);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
      error("lval from decrement must be of type int or char");
    
  }
  else if (cur->v == Stmt::EXP_T) {
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::DECL_T) {
    //declaring a variable
    newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type));
  }
  else if (cur->v == Stmt::DECLI_T) {
    //declaring and assigning a variable
    newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type));
  }
  else if (cur->v == Stmt::BREAK_T) {
    //check most recent loop
    if (loops.empty())
      error("break statement does not have a loop");
  }
  else if (cur->v == Stmt::CONT_T) {
    if (loops.empty())
      error("continue statement does not have a loop");
  }
}