void CIdentifierStorage::requestIdentifier(ObjectCallback callback) { checkIdentifier(callback.type); checkIdentifier(callback.name); assert(!callback.localScope.empty()); scheduledRequests.push_back(callback); }
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); }
/** * @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()); } }
/** * @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")); }
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)); }
/** * @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(); } }
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; }
/** * @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; } }
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 {
/// 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; }