Example #1
0
void CIdentifierStorage::requestIdentifier(ObjectCallback callback)
{
	checkIdentifier(callback.type);
	checkIdentifier(callback.name);

	assert(!callback.localScope.empty());

	scheduledRequests.push_back(callback);
}
Example #2
0
void CIdentifierStorage::requestIdentifier(ObjectCallback callback)
{
	checkIdentifier(callback.type);
	checkIdentifier(callback.name);

	assert(!callback.localScope.empty());

	if (state != FINISHED) // enqueue request if loading is still in progress
		scheduledRequests.push_back(callback);
	else // execute immediately for "late" requests
		resolveIdentifier(callback);
}
Example #3
0
/**
 * @brief Parses in the block context for the given node
 * 
 * The block context parses comments and data identifiers, any other
 * data is invalid in this context.
 * 
 * The block context ends when a closing hash marker is found.
 */
void NepParser::genCtxBlock(Nepeta::Node &node)
{
	size_t stLine = getCurLine(), stCol = getCurCol();
	
	while( notEof() ) {
		char ch = getCurRaw();
		
		// Skip whitespace
		if( isWhite(ch) ) {
			iterCur();
		// Check for data block marker
		} else if( checkIdentifier(ch) || checkHash(ch) ) {
			// Parse the data block.
			// If an end marker is found, this returns false
			if(!genCtxData(node))
				return;
		// Check for comment marker
		} else if( checkComment(ch) ) {
			helpSkipComment();
		// Any other character is invalid, skip to the next line
		} else {
			mScript.addError( Nepeta::ErrIllegalCharacter, std::string(1,ch),
				getCurLine(), getCurCol()
			);
			helpSeekNewline(false);
		}
	}
	
	if(node.getParent()) {
		mScript.addError( Nepeta::ErrPrematureEnd, "",
		stLine, stCol, getCurLine(), getCurCol());
	}
}
Example #4
0
/**
 * @brief Parses in the argument context for the given node.
 */
void NepParser::genCtxArg(Nepeta::Node &data)
{
	while( notEof() ) {
		char ch = getCurRaw();
		
		if( isSpace(ch) ) {
			iterCur();
		} else if( checkIdentifier(ch) ) {
			genArgWord(data);
		} else if( checkString(ch) ) {
			genArgString(data);
		} else if( checkBlock(ch) ) {
			genArgBlock(data);
		} else if( isNewline(ch) || ch == ';' ) {
			iterCur();
			return;
		} else if( ch == '\\' ) {
			iterCur();
			helpSeekNewline(true);
		} else if( ch == '&' ) {
			genArgReference(data);
		} else {
			mScript.addError(Nepeta::ErrIllegalCharacter, std::string(1,ch),
				getCurLine(), getCurCol());
			helpSeekNewline(false);
			break;
		}
	}
}
TEST_F(ParserIdentifierTests, strongIdentifierNameCommentOpenClose)
{
    ASSERT_TRUE( parseDocument(
        "strong identifier name {}") );

    EXPECT_EQ(1U, mDocument->objects().size());
    checkIdentifier(0, 1, 1, "name");
    checkIdentifierCast(0, compil::CastableType::ECast::strong());
}
TEST_F(ParserIdentifierTests, identifierNameBaseOpenClose)
{
    ASSERT_TRUE( parseDocument(
        "identifier<small> name {}") );

    EXPECT_EQ(1U, mDocument->objects().size());
    checkIdentifier(0, 1, 1, "name");
    checkIdentifierCast(0, compil::CastableType::ECast::weak());
    EXPECT_TRUE(checkIdentifierBase(0, "small"));
}
Example #7
0
void CIdentifierStorage::registerObject(std::string scope, std::string type, std::string name, si32 identifier)
{
	ObjectData data;
	data.scope = scope;
	data.id = identifier;

	std::string fullID = type + '.' + name;
	checkIdentifier(fullID);

	registeredObjects.insert(std::make_pair(fullID, data));
}
Example #8
0
/**
 * @brief Generates an identifier.
 * 
 * At the end of a a call to this, the parser cursor is
 * just after the parsed identifier.
 * 
 * @param idStart Desitnation for the beginning of the identifier
 * @param idEnd Destination for the end of the identifier
 */
void NepParser::helpGenIdent(size_t& idStart, size_t& idEnd)
{
	idStart = getCurPos();
	while( true ) {
		char ch = getCur();
		
		if( !checkIdentifier(ch) ) {
			idEnd = getCurPos();
			break;
		}
		
		iterCur();
	}
}
Example #9
0
int executeServerCommand(int msfd, struct url *url, struct config *cfg) {
	/* In base al comando inserito, viene chiamata la rispettiva funzione. */

	// Si controlla l'esistenza dell'identificativo e si cambia directory.
	int returnCode = checkIdentifier(url->identifier, cfg->rootdir);

	if (returnCode != BAD_IDENTIFIER) {
		char* identifierPath = createFullPath(cfg->rootdir, url->identifier);
		char* command = url->command;

		if (strcmp(command, "mkdir") == 0) {
			returnCode = makeDir(identifierPath, url->argument);
		} else if (strcmp(command, "put") == 0) {
			returnCode = putf(msfd, identifierPath, url->argument, url->optionalArgument, "wb");
		} else if (strcmp(command, "puta") == 0) {
			returnCode = putf(msfd, identifierPath, url->argument, url->optionalArgument, "ab");
		} else if (strcmp(command, "move") == 0) {
			returnCode = movefd(identifierPath, url->argument, url->optionalArgument);
		} else if (strcmp(command, "dele") == 0) {
			returnCode = deletefd(identifierPath, url->argument);
		} else if (strcmp(command, "get") == 0) {
			returnCode = getf(msfd, identifierPath, url->argument);
		} else {
			log_err("Unknown_command");
			returnCode = MALFORMED_COMMAND;
		}

		free(identifierPath);
	} else {
		if (strcmp(url->command, "get") == 0) {
			/* Se l'identificativo non è valido, bisogna comunque
			avvertire il client che non sta per ricevere alcun file. */
			sendEntireFile(msfd, NULL);
		} else if (strcmp(url->command, "put") == 0 || strcmp(url->command, "puta") == 0) {
			/* E allo stesso modo devo avvertire il client, nel caso in cui
			lui voglia effettuare un put ma l'identificativo è errato. */
			sendReturnCode(msfd, returnCode);
		}
	}

	log_info("Return code: %d", returnCode);
	return returnCode;
}
Example #10
0
/**
 * @brief Parses in the data context for the given node.
 * 
 * The data context first detects the node identifier and whether
 * the node has any nested nodes, then starts parsing the new node's
 * arguments.
 * 
 * If this node has nested nodes, then the parser enters the
 * block context for the node right after the argument context.
 * 
 * @return false if this node is a closing block marker.
 */
bool NepParser::genCtxData(Nepeta::Node &node)
{
	size_t stL=getCurLine(), stC=getCurCol();
	
	// Analyse the hash marker to determine type
	bool isHash = false;
	if(getCurRaw() == '#') {
		iterCur();
		
		char ch = getCur();
		if( checkIdentifier(ch) )	// This is a normal opening block
			isHash = true;
		else if( isWhite(ch) )		// This is a closing block
			return false;
		else {						// This is not valid data
			mScript.addError(Nepeta::ErrIllegalCharacter, 
				std::string(1,ch),getCurLine(),getCurCol()
			);
			helpSeekNewline(false);
			return true;
		}
	}
	
	// Build the identifier and create the data node
	size_t start, end;
	helpGenIdent(start,end);
	Nepeta::Node &data = node.createNode(
		getSubString(start,getCurPos()), Nepeta::NoPos, stL, stC );
	
	// Process the data context
	genCtxArg(data);
	if(isHash)
		genCtxBlock(data);
	
	return true;
}
void Check_PriorDeclaration_Base::checkBaseExpression(const AST_BaseExpression::shared_ptr &stm)
{
    switch (stm->baseExpressionType()) {

    case AST_BaseExpressionType::betStatements:
    {
        const AST_BaseStatement::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_BaseStatement>(stm);
        checkStatement(local);
        break;
    }
    case AST_BaseExpressionType::betIdentifier:
    {
        const AST_Identifier::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_Identifier>(stm);
        checkIdentifier(local);
        break;
    }
    case AST_BaseExpressionType::betExpression:
    {
        const AST_Expression::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_Expression>(stm);
        checkExpression(local);
        break;
    }
    case AST_BaseExpressionType::betBoolExpression:
    {
        const AST_Boolean_Expression::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_Boolean_Expression>(stm);
        checkBoolExpression(local);
        break;
    }
    case AST_BaseExpressionType::betBoolValue:
    {
        const AST_Boolean::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_Boolean>(stm);
        checkBoolValue(local);
        break;
    }
    case AST_BaseExpressionType::betDoubleValue:
    {
        const AST_Double::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_Double>(stm);
        checkDoubleValue(local);
        break;
    }
    case AST_BaseExpressionType::betIntegerValue:
    {
        const AST_Integer::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_Integer>(stm);
        checkIntegerValue(local);
        break;
    }
    case AST_BaseExpressionType::betStringValue:
    {
        const AST_String::shared_ptr& local
                = boost::dynamic_pointer_cast<AST_String>(stm);
        checkStringValue(local);
        break;
    }
    default:
        break;
    }
}
Example #12
0
void Assembler::assemble(std::string code, RAM* mem) {
    Logger::loggerInst->info("Assembly process started...");
    std::vector<std::string> lines = splitString(code,'\n');
    std::map<sint,sint> datablock;
    varbel_names.clear();
    subroutines.clear();

    sint address = 0;

    //first iteration to get all the information about all subroutines and labels
    for(std::string e : lines) {
        Logger::loggerInst->debug(e);
        std::vector<std::string> words = splitString(e,' ');

        //increase addresspointer apropriately
        if(words.size() > 0 && words.at(0) == "call") address += words.size() * 2 - 1; //function call requires two (OP_Code + Argument) + 2 times #parameters + one (function address) memory slots
        else if(words.size() > 0
                && Constants::ASSEMBLY_INST.find(words.at(0)) == Constants::ASSEMBLY_INST.end()
                && Constants::OP_CODES.find(words.at(0)) != Constants::OP_CODES.end()) address += 2; //normal op code requires two memory slots (OP-Code + Argument)

        //current subroutine definition
        bool isFunctionDef = false;
        sint paramcount = -1;
        std::string name = "";
        subroutine s;

        for(unsigned int i = 0; i < words.size(); ++i) {
            std::string w = words.at(i);
            if(w == "function") isFunctionDef = true; //curent line is a function def
            else if(isFunctionDef) {
                if(i == 1) { //first word after "function" is equal to the name of the subroutine
                    if(checkIdentifier(w)) name = w;
                    else {
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    } //error: invalid identifier!!
                    paramcount = 0;
                } else if(i > 1) {
                    ++paramcount;
                    if(checkIdentifier(w)) s.param_names.insert(std::make_pair(w,paramcount)); //map param_name to position of parameter
                    else {
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    } //error: invalid identifier!!
                }
            } else if(w.at(0) == ':') {
                varbel_names.insert(std::make_pair(w.substr(1),address + 2));
            } else break; //current line doesn't contain a function def or label
            Logger::loggerInst->debug(w);
        }

        if(paramcount > -1) { //curent line was a function def
            s.address = address + 2;
            s.param_count = paramcount;
            subroutines.insert(std::make_pair(name,s)); //store all the information about the subroutine for later use
            Logger::loggerInst->debug("Subroutine stored!");
        }
    }

    //second iteration to acctually assemble the code

    int state = 0; //where in the code are we? 0 = main code, 1 = subroutine
    subroutine* curr_s = nullptr; //stores the current subroutine information
    std::string curr_s_name = "";
    bool curr_s_ret = false;
    int globalvarcount = 0; //how many global vars have been defined so far
    // how many local vars have been defined so far (in case of state == 1)
    // start value of 2 is necessary because 0=return-address, 1=previous frame pointer and 2=previous stack pointer
    int localvarcount = 2;
    address = 1; //reset the address counter;
    mem->setValueAt(0,0x2); //set the default entrypoint to one in case it hasn't been set in the code

    for(int i = 0; i < lines.size(); ++i) {
        std::string e = lines.at(i);
        std::vector<std::string> words = splitString(e,' ');
        Logger::loggerInst->debug("Word count: ",words.size());
        if(words.size() > 0) {
            if(words.at(0) == "define") {
                if(state == 0) {
                    if(words.size() > 1 && checkIdentifier(words.at(1))) {
                        varbel_names.insert(std::make_pair(words.at(1),globalvarcount));
                        if(words.size() > 2) {
                            for(int i = 2; i < words.size(); ++i) {
                                datablock.insert(std::make_pair(globalvarcount,isNumeric(words.at(i))));
                                ++globalvarcount;
                            }
                            --globalvarcount;
                        }
                        ++globalvarcount; //global vars are zero basedly indexed since the data pointer points to the first available ram slot
                    } else if(words.size() == 1) {
                        Logger::loggerInst->error("Missing identifier after keyword 'define' on line ", i + 1);
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    } else {
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    }
                } else {
                    if(words.size() > 1 && checkIdentifier(words.at(1))) {
                        ++localvarcount; //local vars are three basedly indexed since the frame pointer points to the return address and the previous frame and stack pointer value follow
                        curr_s->local_var_names.insert(std::make_pair(words.at(1),localvarcount));
                    } else if(words.size() == 1) {
                        Logger::loggerInst->error("Missing identifier after keyword 'define' on line ", i + 1);
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    } else {
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    }
                }
            } else if(words.at(0) == "endfunction") {
                //reset everything to state 0
                if(!curr_s_ret) Logger::loggerInst->warning("Function '" + curr_s_name + "' has no return statement! This will most likely cause dangling pointers!");
                localvarcount = 2;
                curr_s = nullptr;
                curr_s_name = "";
                state = 0;
            } else if(words.at(0) == "function") {
                //init everything necessary for state 1
                state = 1;
                curr_s = &subroutines.at(words.at(1));
                curr_s_name = words.at(1);
                curr_s_ret = false;
            } else if(words.at(0) == "entrypoint") {
                //set the entrypoint address
                mem->setValueAt(0,address + 1);
            /*} else if(words.at(0) == ":") {
                //if identifier is valid, map the preceding address to it
                if(state == 0 && checkIdentifier(words.at(1))) {
                    varbel_names.insert(std::make_pair(words.at(1),address + 1));
                } else break;*/
            } else {
                if(words.at(0).at(0) == '#' || words.at(0).at(0) == ':') {
                    continue; //line is a comment/label -> continue with next line
                } else if(words.at(0) == "call") {
                    if(words.size() > 1) {
                        if(subroutines.find(words.at(1)) != subroutines.end()) {
                            if(words.size() == subroutines.at(words.at(1)).param_count + 2) {
                                //mnemonic with more than two arguments (currently only possible when calling a function)
                                mem->setValueAt(address + 1, Constants::OP_CODES.at(words.at(0))); //store opcode for calling a function
                                mem->setValueAt(address + 2, subroutines.at(words.at(1)).param_count); //store amount of parameters
                                for(int i = 0; i < subroutines.at(words.at(1)).param_count * 2; i += 2) { //store all the parameters
                                    addressCompound adcp = getAddress(words.at(2+i/2),state, curr_s_name);
                                    mem->setValueAt(address + 3 + i, adcp.op_add); //store type of address
                                    mem->setValueAt(address + 4 + i, adcp.address); //store the address maped to the identifier
                                }
                                mem->setValueAt(address + subroutines.at(words.at(1)).param_count * 2 + 3, subroutines.at(words.at(1)).address);
                            } else if (words.size() > subroutines.at(words.at(1)).param_count + 2) {
                                Logger::loggerInst->error("Too many parameters provided for function '" + words.at(1) + "' on line ", i + 1);
                                Logger::loggerInst->info("Assembly process aborted!");
                                emit assemblyDone();
                                return;
                            } else {
                                Logger::loggerInst->error("Not enough parameters provided for function '" + words.at(1) + "' on line ", i + 1);
                                Logger::loggerInst->info("Assembly process aborted!");
                                emit assemblyDone();
                                return;
                            }
                        } else {
                            Logger::loggerInst->error("Undefined function '" + words.at(1) + "' called on line ", i + 1);
                        }
                    } else {
                        Logger::loggerInst->error("Missing function-identifier after mnemonic 'call' on line ", i + 1);
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    }
                } else if(words.size() == 1) {
                    if(words.at(0) == "ret") curr_s_ret = true;
                    //if mnemonic has no arguments, store the apropriate op-code and a null argument
                    if(Constants::OP_CODES.find(words.at(0)) != Constants::OP_CODES.end()) {
                        mem->setValueAt(address + 1, Constants::OP_CODES.at(words.at(0)));
                        mem->setValueAt(address + 2, 0x0);
                    } else {
                        Logger::loggerInst->error("Unrecognized mnemonic on line ", i + 1);
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    }
                } else if(words.size() == 2) {
                    //mnemonic with one argument
                    if(Constants::OP_CODES.find(words.at(0)) != Constants::OP_CODES.end()) {
                        addressCompound adcp = getAddress(words.at(1), state, curr_s_name);
                        if(adcp.valid) {
                            mem->setValueAt(address + 1, Constants::OP_CODES.at(words.at(0)) + adcp.op_add);
                            mem->setValueAt(address + 2, adcp.address);
                            if(words.at(0) == "ldi" && adcp.op_add == Constants::ADR_REG) Logger::loggerInst->warning("Using register-address as argument for indirect load 'LDI', which most likely won't have the expected result, on line ", i + 1);
                        } else {
                            Logger::loggerInst->info("Assembly process aborted!");
                            emit assemblyDone();
                            return;
                        }
                    } else {
                        Logger::loggerInst->error("Unrecognized mnemonic on line ", i + 1);
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    }
                } else if(words.size() == 3) {
                    if(words.at(0) == "mov") {
                        //mnemonic with two arguments (currently MOV is the only instruction with exactly two arguments, therefore the arg vals can just be added together with a shift of eleven)
                        mem->setValueAt(address + 1,Constants::OP_CODES.at(words.at(0)));
                        addressCompound adcp1 = getAddress(words.at(1), state, curr_s_name);
                        addressCompound adcp2 = getAddress(words.at(2), state, curr_s_name);
                        if(adcp1.valid && adcp2.valid) {
                            if(adcp1.op_add == adcp2.op_add && adcp1.address == adcp2.address) Logger::loggerInst->warning("Mov instruction without effect on line ", i + 1);
                            if(adcp1.op_add != Constants::ADR_REG || adcp2.op_add != Constants::ADR_REG) Logger::loggerInst->warning("Non-register-address argument will be treated as register-address anyways for mov instruction on line ", i+1);
                            mem->setValueAt(address + 2, adcp1.address + (adcp2.address << 11));
                        } else {
                            Logger::loggerInst->info("Assembly process aborted!");
                            emit assemblyDone();
                            return;
                        }
                    } else if(words.at(0) == "ld" || words.at(0) == "ldi") {
                        addressCompound adcp = getAddress(words.at(1), state, curr_s_name);
                        addressCompound target_reg = getAddress(words.at(2),state,curr_s_name);
                        if(adcp.valid && target_reg.valid && target_reg.op_add == Constants::ADR_REG) {
                            sint reg_number = 0;
                            while(target_reg.address > 0) {
                                ++reg_number;
                                target_reg.address >>= 1;
                            }
                            mem->setValueAt(address + 1, Constants::OP_CODES.at(words.at(0)) + adcp.op_add + (reg_number << 24));
                            mem->setValueAt(address + 2, adcp.address);
                            if(words.at(0) == "ldi" && adcp.op_add == Constants::ADR_REG) Logger::loggerInst->warning("Using register-address as argument for indirect load 'LDI', which most likely won't have the expected result, on line ", i + 1);
                        } else {
                            Logger::loggerInst->info("Assembly process aborted!");
                            emit assemblyDone();
                            return;
                        }
                    } else {
                        Logger::loggerInst->error("Too many arguments for mnemonic '" + words.at(0) + "' on line ", i + 1);
                        Logger::loggerInst->info("Assembly process aborted!");
                        emit assemblyDone();
                        return;
                    }
                } else {
Example #13
0
/// Check if a character is a legal character in a reference string
bool NepParser::checkReference(char ch)
{	return checkIdentifier(ch) || ch == '/' || ch == '.' || ch == '[' || ch == ']'; }
/*
	This function will generate a string
	
	Input: 
	*expression 					which contain the string(expression)
	
	Output: 
	none
	
	return: 
	Tokenizer 						which pass to the getToken to generate token.
	
	Throw:
	UNDEFINED_IDENTIFIER			if the expression contained undefined identifier
	INVALID_EXPRESSION				if the expression contained invalid expression (not following format)
*/
String *stringCreate(char *expression) {
	int length = strlen(expression);
	String *newString = malloc (sizeof(String));
	char *newRawString = malloc (length+1);
	int tempIndex,stringStartLocation,lengthOfTheIdentifier=0; 
	Token *newToken;
	char name[20];
	Error exception;
	stringCopy(expression, newRawString, 0, length);
	newString->rawString = newRawString;
	newString->startIndex = 0;
	newString->length = strlen(newString->rawString);
	Try
	{
	for(tempIndex=0;tempIndex<=newString->length;tempIndex++)
	{
		
		if (isalpha(newString->rawString[tempIndex])||(newString->rawString[tempIndex])=='.')
		{
				stringStartLocation=tempIndex;
				do
				{
					lengthOfTheIdentifier++;
					tempIndex++;
				}while(isalnum(newString->rawString[tempIndex])||(newString->rawString[tempIndex]=='.'));
				
				stringCopy(newString->rawString,name,stringStartLocation,lengthOfTheIdentifier);
				newToken=(Token*)checkIdentifier(name);
				tempIndex-=lengthOfTheIdentifier+1;
				
				if(newToken==NULL)
				{
					if(name[0]==48||name[0]==98
						||name[0]==100||name[0]==104
						||name[0]==111)
					{
						newString = convertBasedNumberToBase10Number(newString);
						newString->startIndex++;
					}
					else
					{
						newString = getFromListAndUpdate(newString, name);
					}
				}
				else if(newToken!=NULL)
				{
					tempIndex += lengthOfTheIdentifier;
				}
				
				lengthOfTheIdentifier=0;
			
		}
		else
		{
			if(newString->rawString[tempIndex]==48||newString->rawString[tempIndex]==98
				||newString->rawString[tempIndex]==100||newString->rawString[tempIndex]==104
				||newString->rawString[tempIndex]==111)
			{
				newString = convertBasedNumberToBase10Number(newString);

			}
			newString->startIndex++;
		}
	}
	}
	Catch(exception)
	{
		errorMessage.rawString = newString->rawString;
		errorMessage.position = newString->startIndex;
		if(exception == UNDEFINED_IDENTIFIER)
		{
			Throw(UNDEFINED_IDENTIFIER);
		}
		else if(exception == INVALID_EXPRESSION)
		{
			Throw(INVALID_EXPRESSION);
		}
	}
	newString->startIndex=0;
	return newString;
}