/** * Parses the keyword "namespace" from the given token stack */ int CodeParser::parseKeyword_NameSpace( Scope* scope, TokenStack* stack ) { const char* name; Token* t; // validate incoming scope if( scope->getScopeType() != NAMESPACE_SCOPE ) { SYNTAX_ERROR( "Namespaces cannot be defined in this scope", stack->last() ); return -1; } // the next token must be the identifier if( !( name = state->getIdentifierName( stack, "namespace" ) ) ) { return -1; } // create the name space NameSpace* ns = new NameSpace( name, scope ); // add the name space to the state if( !state->addNameSpace( ns ) ) { printf( "Namespace '%s' already exists\n", name ); return -4; } // the next element must be a code block if( !stack->hasNext() || !( t = stack->peek() ) || ( t->getType() != tok::CODE_BLOCK ) ) { SYNTAX_ERROR( "unexpected token", t ); return -5; } // process the code block return parse( ns, ((ComplexToken*)t)->getChildren() ); }
RobotInterface::Robot& RobotInterface::XMLReader::Private::readRobotFile(const std::string &fileName) { filename = fileName; #ifdef WIN32 std::replace(filename.begin(), filename.end(), '/', '\\'); #endif curr_filename = fileName; #ifdef WIN32 path = filename.substr(0, filename.rfind("\\")); #else // WIN32 path = filename.substr(0, filename.rfind("/")); #endif //WIN32 yDebug() << "Reading file" << filename.c_str(); TiXmlDocument *doc = new TiXmlDocument(filename.c_str()); if (!doc->LoadFile()) { SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc(); } if (!doc->RootElement()) { SYNTAX_ERROR(doc->Row()) << "No root element."; } for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) { if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) { if(dtd.parse(childNode->ToUnknown(), curr_filename)) { break; } } } if (!dtd.valid()) { SYNTAX_WARNING(doc->Row()) << "No DTD found. Assuming version robotInterfaceV1.0"; dtd.setDefault(); dtd.type = RobotInterfaceDTD::DocTypeRobot; } if(dtd.type != RobotInterfaceDTD::DocTypeRobot) { SYNTAX_WARNING(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeRobot) << ". Found" << DocTypeToString(dtd.type); } if(dtd.majorVersion != 1 || dtd.minorVersion != 0) { SYNTAX_WARNING(doc->Row()) << "Only robotInterface DTD version 1.0 is supported"; } readRobotTag(doc->RootElement()); delete doc; // yDebug() << robot; return robot; }
/** * Parses the keyword "class" from the given token stack */ int CodeParser::parseKeyword_Class( Scope* scope, TokenStack* stack ) { Class* classdef; const char* name; Token* t; // validate incoming scope if( scope->getScopeType() != NAMESPACE_SCOPE ) { SYNTAX_ERROR( "Classes cannot be defined in this scope", stack->last() ); return -1; } // the next token must be the identifier if( !( name = state->getIdentifierName( stack, "class" ) ) ) { return -2; } // get the name space NameSpace* ns = (NameSpace*)scope; printf( "class '%s' in namespace '%s' modifiers = %s\n", name, ns->getName(), toBinary( modifiers ) ); // TODO check for inheritance! multiple inheritance? // - class MyChild extends MyParent { ... } // - class StrobeLamp extends Lamp, Strobe { ... } // create the class classdef = new Class( name, ns->getName(), ns, modifiers ); this->modifiers = 0; // add the name space to the state if( !ns->addClass( classdef ) ) { char* error = new char[256]; sprintf( error, "Class '%s' already exists in namespace '%s'\n", name, ns->getName() ); SYNTAX_ERROR( error, stack->last() ); delete error; return -4; } // the next element must be a code block if( !stack->hasNext() || !( t = stack->peek() ) || ( t->getType() != tok::CODE_BLOCK ) ) { SYNTAX_ERROR( "unexpected token", t ); return -5; } // process the code block int errorCode = parse( classdef, ((ComplexToken*)t)->getChildren() ); // register the class state->addClass( classdef ); // reset the class-level counters state->resetCounters(); return errorCode; }
RobotInterface::Robot& RobotInterface::XMLReader::Private::readRobotTag(TiXmlElement *robotElem) { if (robotElem->ValueStr().compare("robot") != 0) { SYNTAX_ERROR(robotElem->Row()) << "Root element should be \"robot\". Found" << robotElem->ValueStr(); } if (robotElem->QueryStringAttribute("name", &robot.name()) != TIXML_SUCCESS) { SYNTAX_ERROR(robotElem->Row()) << "\"robot\" element should contain the \"name\" attribute"; } #if TINYXML_UNSIGNED_INT_BUG if (robotElem->QueryUnsignedAttribute("build", &robot.build()) != TIXML_SUCCESS) { // No build attribute. Assuming build="0" SYNTAX_WARNING(robotElem->Row()) << "\"robot\" element should contain the \"build\" attribute [unsigned int]. Assuming 0"; } #else int tmp; if (robotElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) { // No build attribute. Assuming build="0" SYNTAX_WARNING(robotElem->Row()) << "\"robot\" element should contain the \"build\" attribute [unsigned int]. Assuming 0"; tmp = 0; } robot.build() = (unsigned)tmp; #endif if (robotElem->QueryStringAttribute("portprefix", &robot.portprefix()) != TIXML_SUCCESS) { SYNTAX_WARNING(robotElem->Row()) << "\"robot\" element should contain the \"portprefix\" attribute. Using \"name\" attribute"; robot.portprefix() = robot.name(); } // yDebug() << "Found robot [" << robot.name() << "] build [" << robot.build() << "] portprefix [" << robot.portprefix() << "]"; for (TiXmlElement* childElem = robotElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { if (childElem->ValueStr().compare("device") == 0 || childElem->ValueStr().compare("devices") == 0) { DeviceList childDevices = readDevices(childElem); for (DeviceList::const_iterator it = childDevices.begin(); it != childDevices.end(); ++it) { robot.devices().push_back(*it); } } else { ParamList childParams = readParams(childElem); for (ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) { robot.params().push_back(*it); } } } return robot; }
/** * Parses the text contained within the given token stack */ int CodeParser::parseKeyword( Scope* scope, TokenStack* stack, const char* keyword ) { int errorCode = 0; // TODO delete, do-while, for, foreach // TODO if-else, try-catch, throw, while // handle the keyword switch( state->lookupKeyword( keyword ) ) { case KW_ABSTRACT: errorCode = updateModifiers( ABSTRACT, stack ); break; case KW_CLASS: errorCode = parseKeyword_Class( scope, stack ); break; case KW_FINAL: errorCode = updateModifiers( FINAL, stack ); break; case KW_IMPORT: errorCode = parseKeyword_Import( scope, stack ); break; case KW_NAMESPACE: errorCode = parseKeyword_NameSpace( scope, stack ); break; case KW_NEW: errorCode = parseKeyword_New( scope, stack ); break; case KW_PACKAGED: errorCode = updateModifiers( PACKAGE, stack ); break; case KW_PRIVATE: errorCode = updateModifiers( PRIVATE, stack ); break; case KW_PROTECTED: errorCode = updateModifiers( PROTECTED, stack ); break; case KW_PUBLIC: errorCode = updateModifiers( PUBLIC, stack ); break; case KW_RETURN: errorCode = parseKeyword_Return( scope, stack ); break; case KW_STATIC: errorCode = updateModifiers( STATIC, stack ); break; case KW_VIRTUAL: errorCode = updateModifiers( VIRTUAL, stack ); break; default: char *message = new char[256]; sprintf( message, "Keyword '%s' was not handled", keyword ); SYNTAX_ERROR( message, stack->last() ); delete message; errorCode = -1; } // success return errorCode; }
extern cv_t c_eval(obj_t cont, obj_t values) { assert(is_cont4(cont)); obj_t expr = cont4_arg(cont); EVAL_LOG("expr=%O", expr); COULD_RETRY(); if (is_self_evaluating(expr)) return cv(cont_cont(cont), CONS(expr, values)); else if (is_symbol(expr)) { obj_t env = cont_env(cont); obj_t val = env_lookup(env, expr); return cv(cont_cont(cont), CONS(val, values)); #if !OLD_ENV } else if (is_env_ref(expr)) { return cv(cont_cont(cont), CONS(env_ref_lookup(cont_env(cont), expr), values)); #endif } else if (is_application(expr)) { obj_t operator = application_operator(expr); obj_t env = cont_env(cont); obj_t second = make_cont4(c_eval_operator, cont_cont(cont), env, expr); obj_t first = make_cont4(c_eval, second, env, operator); return cv(first, values); } SYNTAX_ERROR(expr, expr, "must be expression"); }
RobotInterface::ParamList RobotInterface::XMLReader::Private::readParams(TiXmlElement* paramsElem) { const std::string &valueStr = paramsElem->ValueStr(); if (valueStr.compare("param") != 0 && valueStr.compare("group") != 0 && valueStr.compare("paramlist") != 0 && valueStr.compare("subdevice") != 0 && valueStr.compare("params") != 0) { SYNTAX_ERROR(paramsElem->Row()) << "Expected \"param\", \"group\", \"paramlist\"," << "\"subdevice\", or \"params\". Found" << valueStr; } if (valueStr.compare("param") == 0) { ParamList params; params.push_back(readParamTag(paramsElem)); return params; } else if (valueStr.compare("group") == 0) { ParamList params; params.push_back(readGroupTag(paramsElem)); return params; } else if (valueStr.compare("paramlist") == 0) { return readParamListTag(paramsElem); } else if (valueStr.compare("subdevice") == 0) { return readSubDeviceTag(paramsElem); } // "params" return readParamsTag(paramsElem); }
/** * Parses a type definition */ TypeReference* CodeParser::parseType( Scope* scope, TokenStack* stack ) { const char* typeName; TypeReference* type; Token *t; // the next element must be alphanumeric if( !( t = stack->next() ) || ( t->getType() != tok::ALPHA_NUMERIC ) || !( typeName = t->getText() ) || !state->isClass( typeName ) ) { SYNTAX_ERROR( "type identifier expected", stack->last() ); return NULL; } // create the type type = new TypeReference( typeName ); // is the type an array? (e.g. "int[] field") if( stack->hasNext() && ( stack->peek()->getType() == tok::BRACKET_BLOCK ) && ( t = stack->next() ) ) { // TODO finish adding logic here type->setArray( true ); printf( "array = '%s'\n", t->getText() ); } // return the class reference return type; }
static cv_t c_eval_operator(obj_t cont, obj_t values) { assert(is_cont4(cont)); obj_t appl = cont4_arg(cont); obj_t operator = CAR(values); EVAL_LOG("appl=%O operator=%O", appl, operator); COULD_RETRY(); if (!is_procedure(operator)) SYNTAX_ERROR(operator, operator, "must be procedure"); if (!procedure_args_evaluated(operator)) { assert(procedure_is_C(operator) && "implement Scheme special forms"); if (procedure_is_raw(operator)) { return ((cont_proc_t)procedure_code(operator))(cont, values); } else { // N.B., call proc after all other allocations. obj_t arg_list = application_operands(appl); obj_t new_values = CONS(make_uninitialized(), CDR(values)); pair_set_car(new_values, apply_proc(operator, arg_list)); return cv(cont_cont(cont), new_values); } } obj_t arg_list = reverse_list(application_operands(appl)); cont = make_cont5(c_apply_proc, cont_cont(cont), cont_env(cont), operator, CDR(values)); while (!is_null(arg_list)) { cont = make_cont4(c_eval, cont, cont_env(cont), CAR(arg_list)); arg_list = CDR(arg_list); } return cv(cont, EMPTY_LIST); }
RobotInterface::ActionList RobotInterface::XMLReader::Private::readActionsTag(TiXmlElement *actionsElem) { const std::string &valueStr = actionsElem->ValueStr(); if (valueStr.compare("actions") != 0) { SYNTAX_ERROR(actionsElem->Row()) << "Expected \"actions\". Found" << valueStr; } std::string filename; if (actionsElem->QueryStringAttribute("file", &filename) == TIXML_SUCCESS) { // yDebug() << "Found actions file [" << filename << "]"; #ifdef WIN32 std::replace(filename.begin(), filename.end(), '/', '\\'); filename = path + "\\" + filename; #else // WIN32 filename = path + "/" + filename; #endif //WIN32 return readActionsFile(filename); } std::string robotName; if (actionsElem->QueryStringAttribute("robot", &robotName) != TIXML_SUCCESS) { SYNTAX_WARNING(actionsElem->Row()) << "\"actions\" element should contain the \"robot\" attribute"; } if (robotName != robot.name()) { SYNTAX_WARNING(actionsElem->Row()) << "Trying to import a file for the wrong robot. Found" << robotName << "instead of" << robot.name(); } unsigned int build; #if TINYXML_UNSIGNED_INT_BUG if (actionsElem->QueryUnsignedAttribute("build", &build()) != TIXML_SUCCESS) { // No build attribute. Assuming build="0" SYNTAX_WARNING(actionsElem->Row()) << "\"actions\" element should contain the \"build\" attribute [unsigned int]. Assuming 0"; } #else int tmp; if (actionsElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) { // No build attribute. Assuming build="0" SYNTAX_WARNING(actionsElem->Row()) << "\"actions\" element should contain the \"build\" attribute [unsigned int]. Assuming 0"; tmp = 0; } build = (unsigned)tmp; #endif if (build != robot.build()) { SYNTAX_WARNING(actionsElem->Row()) << "Import a file for a different robot build. Found" << build << "instead of" << robot.build(); } ActionList actions; for (TiXmlElement* childElem = actionsElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { ActionList childActions = readActions(childElem); for (ActionList::const_iterator it = childActions.begin(); it != childActions.end(); ++it) { actions.push_back(*it); } } return actions; }
AST* QueryParser::parse(std::string str, AST* ast, const int level) { if(NULL == ast) ast = new AST(); #ifdef DEBUG_PARSING_LEVELS if(level < 1) std::cout << "Parsing:" << std::endl << str; #endif if(str.size() < 2) return NULL; size_t beg = std::string::npos, end = std::string::npos; removeComments(str); str = StringUtils::trim(str); std::string header, body; header = StringUtils::extract(str, beg, end, HEADER_BEGIN, HEADER_END); if(header.size() < 2 || beg != 0) { SYNTAX_ERROR("No header in query", header); return NULL; } std::cout << "\nParsing header: " << header; Header* h = subParse(header, 1); Body* b = NULL; body = str.substr(end); if(body.size() < 2) { WARNING("Body is empty"); } else b = subParse(body, 1); ASSERT(b != 0); if(h != NULL) { ast->setHeader(h); ast->setBody(b); } else return NULL; return ast; }
/** * Parses the class member (field or method) contained within the given token stack */ int CodeParser::parseClassMember( Scope* scope, TokenStack* stack ) { int errorCode = 0; TypeReference* type; const char* name; // the following types are parsed: // method layout: "[static] [final] type|[]| methodName(...) { ... }" // field layout: "[static] [final] type|[]| fieldName| = ....|" int step = 0; bool done = false; while( !done && stack->hasNext() ) { switch( ++step ) { // step 1: get the type of the class member (e.g. "string" or "string[]") case 1: // extract the name of the identifier if( !( type = parseType( scope, stack ) ) ) { return -1; } break; // step 2: get the class member name case 2: // get the type name if( !( name = state->getIdentifierName( stack, "class member" ) ) ) { return -2; } break; // step 3: get the class member instance (field or method) // method layout: "[static] [final] type methodName(...) { ... }" // field layout: "[static] [final] type fieldName[ = ....]" case 3: // each child should be a method (e.g. "type methodName(...)") or field (e.g. "type fieldName") // if there is a parenthesis block, it's likely to be a method errorCode = ( stack->peek()->getType() == tok::PARENTHESIS_BLOCK ) ? parseMethod( scope, name, type, stack ) : parseField( scope, name, type, stack ); // was there an error? if( errorCode ) { return errorCode; } done = true; break; } } // did it complete? if( !done ) { SYNTAX_ERROR( "unexpected end of statement", stack->last() ); return -4; } // return the error code return 0; }
RobotInterface::ActionList RobotInterface::XMLReader::Private::readActionsFile(const std::string &fileName) { std::string old_filename = curr_filename; curr_filename = fileName; yDebug() << "Reading file" << fileName.c_str(); TiXmlDocument *doc = new TiXmlDocument(fileName.c_str()); if (!doc->LoadFile()) { SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc(); } if (!doc->RootElement()) { SYNTAX_ERROR(doc->Row()) << "No root element."; } RobotInterfaceDTD actionsFileDTD; for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) { if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) { if(actionsFileDTD.parse(childNode->ToUnknown(), curr_filename)) { break; } } } if (!actionsFileDTD.valid()) { SYNTAX_WARNING(doc->Row()) << "No DTD found. Assuming version robotInterfaceV1.0"; actionsFileDTD.setDefault(); actionsFileDTD.type = RobotInterfaceDTD::DocTypeActions; } if (actionsFileDTD.type != RobotInterfaceDTD::DocTypeActions) { SYNTAX_ERROR(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeActions) << ". Found" << DocTypeToString(actionsFileDTD.type); } if (actionsFileDTD.majorVersion != dtd.majorVersion) { SYNTAX_ERROR(doc->Row()) << "Trying to import a file with a different robotInterface DTD version"; } RobotInterface::ActionList actions = readActionsTag(doc->RootElement()); delete doc; curr_filename = old_filename; return actions; }
RobotInterface::ParamList RobotInterface::XMLReader::Private::readParamsTag(TiXmlElement *paramsElem) { const std::string &valueStr = paramsElem->ValueStr(); if (valueStr.compare("params") != 0) { SYNTAX_ERROR(paramsElem->Row()) << "Expected \"params\". Found" << valueStr; } std::string filename; if (paramsElem->QueryStringAttribute("file", &filename) == TIXML_SUCCESS) { // yDebug() << "Found params file [" << filename << "]"; filename=rf.findFileByName(filename); return readParamsFile(filename); } std::string robotName; if (paramsElem->QueryStringAttribute("robot", &robotName) != TIXML_SUCCESS) { SYNTAX_WARNING(paramsElem->Row()) << "\"params\" element should contain the \"robot\" attribute"; } if (robotName != robot.name()) { SYNTAX_WARNING(paramsElem->Row()) << "Trying to import a file for the wrong robot. Found" << robotName << "instead of" << robot.name(); } unsigned int build; #if TINYXML_UNSIGNED_INT_BUG if (paramsElem->QueryUnsignedAttribute("build", &build()) != TIXML_SUCCESS) { // No build attribute. Assuming build="0" SYNTAX_WARNING(paramsElem->Row()) << "\"params\" element should contain the \"build\" attribute [unsigned int]. Assuming 0"; } #else int tmp; if (paramsElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) { // No build attribute. Assuming build="0" SYNTAX_WARNING(paramsElem->Row()) << "\"params\" element should contain the \"build\" attribute [unsigned int]. Assuming 0"; tmp = 0; } build = (unsigned)tmp; #endif if (build != robot.build()) { SYNTAX_WARNING(paramsElem->Row()) << "Import a file for a different robot build. Found" << build << "instead of" << robot.build(); } ParamList params; for (TiXmlElement* childElem = paramsElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { ParamList childParams = readParams(childElem); for (ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) { params.push_back(*it); } } return params; }
RobotInterface::Action RobotInterface::XMLReader::Private::readActionTag(TiXmlElement* actionElem) { if (actionElem->ValueStr().compare("action") != 0) { SYNTAX_ERROR(actionElem->Row()) << "Expected \"action\". Found" << actionElem->ValueStr(); } Action action; if (actionElem->QueryValueAttribute<ActionPhase>("phase", &action.phase()) != TIXML_SUCCESS || action.phase() == ActionPhaseUnknown) { SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"phase\" attribute [startup|interrupt{1,2,3}|shutdown]"; } if (actionElem->QueryValueAttribute<ActionType>("type", &action.type()) != TIXML_SUCCESS || action.type() == ActionTypeUnknown) { SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"type\" attribute [configure|calibrate|attach|abort|detach|park|custom]"; } // yDebug() << "Found action [ ]"; #if TINYXML_UNSIGNED_INT_BUG if (actionElem->QueryUnsignedAttribute("level", &action.level()) != TIXML_SUCCESS) { SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"level\" attribute [unsigned int]"; } #else int tmp; if (actionElem->QueryIntAttribute("level", &tmp) != TIXML_SUCCESS || tmp < 0) { SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"level\" attribute [unsigned int]"; } action.level() = (unsigned)tmp; #endif for (TiXmlElement* childElem = actionElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { ParamList childParams = readParams(childElem); for (ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) { action.params().push_back(*it); } } // yDebug() << action; return action; }
/** * Parses the expression from the given token stack */ int CodeParser::parseExpression( Scope* scope, TokenStack* stack ) { int errorCode = 0; Token* t; // gather the arguments up to the end of the statement TokenStack* substack = getStackToEndOfStatement( stack ); // get the argument list while( !errorCode && substack->hasNext() && ( t = substack->next() ) ) { printf( "CodeParser::parseExpression: '%s' [%s]\n", t->getText(), t->getTypeName() ); // handle the token by type switch( t->getType() ) { case tok::ALPHA_NUMERIC: // is the argument a field? if( scope->lookupField( t->getText() ) ) { printf( "CodeParser::parseExpression: Field - [%s]\n", t->getText() ); } // is it a method call? else if( substack->hasNext() && substack->peek()->getType() == tok::PARENTHESIS_BLOCK ) { errorCode = parseExpression_MethodCall( t->getText(), scope, substack ); } break; case tok::DECIMAL: case tok::INTEGER: break; case tok::DQUOTE_TEXT: break; case tok::SQUOTE_TEXT: break; case tok::OPERATOR: break; case tok::PARENTHESIS_BLOCK: break; default: errorCode = -1; SYNTAX_ERROR( "unexpected token", substack->last() ); } } // delete the stack delete substack; // return the error code return errorCode; }
RobotInterface::Device RobotInterface::XMLReader::Private::readDeviceTag(TiXmlElement *deviceElem) { const std::string &valueStr = deviceElem->ValueStr(); if (valueStr.compare("device") != 0) { SYNTAX_ERROR(deviceElem->Row()) << "Expected \"device\". Found" << valueStr; } Device device; if (deviceElem->QueryStringAttribute("name", &device.name()) != TIXML_SUCCESS) { SYNTAX_ERROR(deviceElem->Row()) << "\"device\" element should contain the \"name\" attribute"; } // yDebug() << "Found device [" << device.name() << "]"; if (deviceElem->QueryStringAttribute("type", &device.type()) != TIXML_SUCCESS) { SYNTAX_ERROR(deviceElem->Row()) << "\"device\" element should contain the \"type\" attribute"; } device.params().push_back(Param("robotName", robot.portprefix().c_str())); for (TiXmlElement* childElem = deviceElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { if (childElem->ValueStr().compare("action") == 0 || childElem->ValueStr().compare("actions") == 0) { ActionList childActions = readActions(childElem); for (ActionList::const_iterator it = childActions.begin(); it != childActions.end(); ++it) { device.actions().push_back(*it); } } else { ParamList childParams = readParams(childElem); for (ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) { device.params().push_back(*it); } } } // yDebug() << device; return device; }
/** * Parses the source code */ int CodeParser::parse( Scope* scope, TokenStack* stack ) { int errorCode = 0; Token *t; // get the command arguments while( !errorCode && stack->hasNext() && ( t = stack->peek() ) ) { //printf( "t = %s[%s]\n", t->getTypeName(), t->getText() ); // check situationally switch( t->getType() ) { case tok::CODE_BLOCK: errorCode = parseAnonymuousCodeBlock( scope, ( t = stack->next() ) ); break; case tok::ASSEMBLY_BLOCK: errorCode = assemblyParser->parse( scope, stack ); break; case tok::END_OF_STATEMENT: t = stack->next(); this->modifiers = 0; break; case tok::ALPHA_NUMERIC: // is the token a keyword? if( state->isKeyword( t->getText() ) ) { const char *keyword = stack->next()->getText(); errorCode = parseKeyword( scope, stack, keyword ); } // is it a field/method declaration? else if( state->isClass( t->getText() ) ) { errorCode = parseClassMember( scope, stack ); } // must be an assignment or method invocation ... else { errorCode = parseExpression( scope, stack ); } break; // anything else ... default: SYNTAX_ERROR( "unrecognized command", t ); errorCode = -1; break; } } return errorCode; }
struct Statement* parse_statement(const struct Symbol** symbols, int symbolCount, int* symbolsConsumed) { struct Statement* statement; // Make sure there are symbols left if (symbolCount <= 0) { SYNTAX_ERROR("Unexpected EOF when looking for statement"); } // First try to identify a print statement if (symbols[0]->type == SYMBOL_PRINT) { struct PrintStatement* printstatement = (struct PrintStatement*)calloc(1, sizeof(struct PrintStatement)); statement = &printstatement->base; PRINTF_AST("PRINTSTATEMENT"); PRINTF_AST_ENTER(); printstatement->base.type = STATEMENT_TYPE_PRINT; printstatement->expression = parse_expression(symbols + 1, symbolCount - 1, symbolsConsumed); *symbolsConsumed += 1; // add print keyword PRINTF_AST_LEAVE(); } // Second try to identify an assignment statement else if (symbols[0]->type == SYMBOL_IDENTIFIER && symbols[1]->type == SYMBOL_EQUALS) { struct AssignmentStatement* assignmentstatement = (struct AssignmentStatement*)calloc(1, sizeof(struct AssignmentStatement)); statement = &assignmentstatement->base; PRINTF_AST("ASSIGNSTATEMENT"); PRINTF_AST_ENTER(); assignmentstatement->base.type = STATEMENT_TYPE_ASSIGNMENT; assignmentstatement->identifier = ((struct IdentifierSymbol*)symbols[0])->name; assignmentstatement->expression = parse_expression(symbols + 2, symbolCount - 2, symbolsConsumed); *symbolsConsumed += 2; // add identifier and equals PRINTF_AST_LEAVE(); } // parse error otherwise else { SYNTAX_ERROR_AT(symbols[0], "Invalid beginning of statement"); } return statement; }
RobotInterface::Param RobotInterface::XMLReader::Private::readParamTag(TiXmlElement *paramElem) { if (paramElem->ValueStr().compare("param") != 0) { SYNTAX_ERROR(paramElem->Row()) << "Expected \"param\". Found" << paramElem->ValueStr(); } Param param; if (paramElem->QueryStringAttribute("name", ¶m.name()) != TIXML_SUCCESS) { SYNTAX_ERROR(paramElem->Row()) << "\"param\" element should contain the \"name\" attribute"; } // yDebug() << "Found param [" << param.name() << "]"; const char *valueText = paramElem->GetText(); if (!valueText) { SYNTAX_ERROR(paramElem->Row()) << "\"param\" element should have a value [ \"name\" = " << param.name() << "]"; } param.value() = valueText; // yDebug() << param; return param; }
RobotInterface::Param RobotInterface::XMLReader::Private::readGroupTag(TiXmlElement* groupElem) { if (groupElem->ValueStr().compare("group") != 0) { SYNTAX_ERROR(groupElem->Row()) << "Expected \"group\". Found" << groupElem->ValueStr(); } Param group(true); if (groupElem->QueryStringAttribute("name", &group.name()) != TIXML_SUCCESS) { SYNTAX_ERROR(groupElem->Row()) << "\"group\" element should contain the \"name\" attribute"; } // yDebug() << "Found group [" << group.name() << "]"; ParamList params; for (TiXmlElement* childElem = groupElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { ParamList childParams = readParams(childElem); for (ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) { params.push_back(*it); } } if (params.empty()) { SYNTAX_ERROR(groupElem->Row()) << "\"group\" cannot be empty"; } std::string groupString; for (ParamList::iterator it = params.begin(); it != params.end(); ++it) { if (!groupString.empty()) { groupString += " "; } groupString += "(" + it->name() + " " + it->value() + ")"; } group.value() = groupString; return group; }
RobotInterface::ParamList RobotInterface::XMLReader::Private::readSubDeviceTag(TiXmlElement *subDeviceElem) { if (subDeviceElem->ValueStr().compare("subdevice") != 0) { SYNTAX_ERROR(subDeviceElem->Row()) << "Expected \"subdevice\". Found" << subDeviceElem->ValueStr(); } ParamList params; //FIXME Param featIdParam; Param subDeviceParam; //FIXME featIdParam.name() = "FeatId"; subDeviceParam.name() = "subdevice"; //FIXME if (subDeviceElem->QueryStringAttribute("name", &featIdParam.value()) != TIXML_SUCCESS) { // SYNTAX_ERROR(subDeviceElem->Row()) << "\"subdevice\" element should contain the \"name\" attribute"; // } if (subDeviceElem->QueryStringAttribute("type", &subDeviceParam.value()) != TIXML_SUCCESS) { SYNTAX_ERROR(subDeviceElem->Row()) << "\"subdevice\" element should contain the \"type\" attribute"; } //FIXME params.push_back(featIdParam); params.push_back(subDeviceParam); // yDebug() << "Found subdevice [" << params.at(0).value() << "]"; for (TiXmlElement* childElem = subDeviceElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { ParamList childParams = readParams(childElem); for (ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) { params.push_back(Param(it->name(), it->value())); } } // yDebug() << params; return params; }
/** * Updates the current access modifier */ int CodeParser::updateModifiers( char newModifier, TokenStack* stack ) { // capture the unmodified state const char oldModifier = modifiers; // update the modifiers modifiers |= newModifier; // error if no change if( ( newModifier != 0 ) && ( modifiers == oldModifier ) ) { SYNTAX_ERROR( "duplicate modifier", stack->last() ); return -1; } return 0; }
struct StatementList* parse_statementlist(const struct Symbol** symbols, int symbolCount, int* symbolsConsumed) { struct StatementList* statementlist = (struct StatementList*)calloc(1, sizeof(struct StatementList)); // Make sure there are symbols left if (symbolCount <= 0) { SYNTAX_ERROR("Unexpected EOF when looking for statement list"); } PRINTF_AST("STATEMENTLIST"); PRINTF_AST_ENTER(); // Start by pulling out the next statement int symbolsInStatement = 0; statementlist->statement = parse_statement(symbols, symbolCount, &symbolsInStatement); // If that is not the end of the symbols, parse more statements if (symbols[symbolsInStatement]->type != SYMBOL_EOF) { if (symbols[symbolsInStatement]->type == SYMBOL_EOL) { int symbolsInStatementList = 0; statementlist->statementlist = parse_statementlist( &symbols[symbolsInStatement+1], (symbolCount - 1) - symbolsInStatement, &symbolsInStatementList); *symbolsConsumed = symbolsInStatement + 1 /* newline */ + symbolsInStatementList; } else { SYNTAX_ERROR_AT(symbols[symbolCount-1], "Expected newline or EOF at end of statement"); } } // If that is the end of the symbols, the list is complete else { *symbolsConsumed = symbolsInStatement; } PRINTF_AST_LEAVE(); return statementlist; }
/** * Parses the method call within an expression */ int CodeParser::parseExpression_MethodCall( const char* methodName, Scope* scope, TokenStack* stack ) { int errorCode = 0; list<Parameter*> params; // parse the method parameters if( ( errorCode = parseMethodParameters( scope, stack, params ) ) ) { return errorCode; } // generate the method signature const char* signature = generateSignature( methodName, params ); // lookup the method Method* method = lookupMethod( scope, signature ); if( method == NULL ) { // generate the error message char* errorMessage = new char[256]; sprintf( errorMessage, "Method '%s' could not be found", signature ); // display the error message SYNTAX_ERROR( errorMessage, stack->last() ); delete errorMessage; return -1; } else { printf( "CodeParser::parseExpression: Method call - [%s]\n", signature ); // get the code buffer CodeBuffer* cb = scope->getCodeBuffer(); // parse the method parameter // setup the method call // instruction: PARAMS methodParams // instruction: INVOKE methodSig OFFSET_T offset1 = cb->putInstruction( PARAMS << A_OP ); OFFSET_T offset2 = cb->putInstruction( INVOKE << A_OP ); // add the parameter and reference data scope->addParameterData( new ParameterData( state->nextParamId(), params, offset1 ) ); scope->addReferenceData( new ReferenceData( state->nextDataRefId(), signature, offset2 ) ); return 0; } }
/** * Parses the keyword "return" from the given token stack */ int CodeParser::parseKeyword_Return( Scope* scope, TokenStack* stack ) { // get the scope type ScopeType type = scope->getScopeType(); if( type != METHOD_SCOPE ) { SYNTAX_ERROR( "Statement is only permissible within a method block", stack->last() ); return -1; } // get the method instance Method* method = (Method*)scope; // TODO support "return value" syntax // add the instruction INSTRUCTION_T instruction = RET << A_OP; method->getCodeBuffer()->putInstruction( instruction ); return 0; }
RobotInterface::ActionList RobotInterface::XMLReader::Private::readActions(TiXmlElement *actionsElem) { const std::string &valueStr = actionsElem->ValueStr(); if (valueStr.compare("action") != 0 && valueStr.compare("actions") != 0) { SYNTAX_ERROR(actionsElem->Row()) << "Expected \"action\" or \"actions\". Found" << valueStr; } if (valueStr.compare("action") == 0) { ActionList actionList; actionList.push_back(readActionTag(actionsElem)); return actionList; } // "actions" return readActionsTag(actionsElem); }
RobotInterface::ParamList RobotInterface::XMLReader::Private::readParamListTag(TiXmlElement* paramListElem) { if (paramListElem->ValueStr().compare("paramlist") != 0) { SYNTAX_ERROR(paramListElem->Row()) << "Expected \"paramlist\". Found" << paramListElem->ValueStr(); } ParamList params; Param mainparam; if (paramListElem->QueryStringAttribute("name", &mainparam.name()) != TIXML_SUCCESS) { SYNTAX_ERROR(paramListElem->Row()) << "\"paramlist\" element should contain the \"name\" attribute"; } params.push_back(mainparam); // yDebug() << "Found paramlist [" << params.at(0).name() << "]"; for (TiXmlElement* childElem = paramListElem->FirstChildElement(); childElem != 0; childElem = childElem->NextSiblingElement()) { if (childElem->ValueStr().compare("elem") != 0) { SYNTAX_ERROR(childElem->Row()) << "Expected \"elem\". Found" << childElem->ValueStr(); } Param childParam; if (childElem->QueryStringAttribute("name", &childParam.name()) != TIXML_SUCCESS) { SYNTAX_ERROR(childElem->Row()) << "\"elem\" element should contain the \"name\" attribute"; } const char *valueText = childElem->GetText(); if (!valueText) { SYNTAX_ERROR(childElem->Row()) << "\"elem\" element should have a value [ \"name\" = " << childParam.name() << "]"; } childParam.value() = valueText; params.push_back(childParam); } if (params.empty()) { SYNTAX_ERROR(paramListElem->Row()) << "\"paramlist\" cannot be empty"; } // +1 skips the first element, that is the main param for (ParamList::iterator it = params.begin() + 1; it != params.end(); ++it) { Param ¶m = *it; params.at(0).value() += (params.at(0).value().empty() ? "(" : " ") + param.name(); } params.at(0).value() += ")"; // yDebug() << params; return params; }
/** * Compiles a field declaration */ int CodeParser::parseField( Scope* scope, const char* name, TypeReference* type, TokenStack* stack ) { int errorCode = 0; Token *t1, *t2; const char* data; // create the field, and attach it to the class Field* field = new Field( name, type, this->modifiers ); printf( "field '%s' type='%s' modifiers = %s\n", name, type->getName(), toBinary( this->modifiers ) ); // reset the modifier for the current scope this->modifiers = 0; // is there also an assignment? if( stack->hasNext() && !strcmp( stack->peek()->getText(), "=" ) ) { // capture the t1 = stack->next(); // there must be another token if( !( t2 = stack->next() ) ) { SYNTAX_ERROR( "Unexpected end of statement", t1 ); return NULL; } switch( t2->getType() ) { case tok::SQUOTE_TEXT:; case tok::DQUOTE_TEXT: data = t2->getText(); setupAssignment( scope, field, data ); break; default: parseExpression( scope, stack ); } } // add the field to the scope if( !errorCode ) { scope->addField( field ); } // TODO there may be an expression: int x = 5 * y + 1; return errorCode; }
RobotInterface::DeviceList RobotInterface::XMLReader::Private::readDevices(TiXmlElement *devicesElem) { const std::string &valueStr = devicesElem->ValueStr(); if (valueStr.compare("device") != 0 && valueStr.compare("devices") != 0) { SYNTAX_ERROR(devicesElem->Row()) << "Expected \"device\" or \"devices\". Found" << valueStr; } if (valueStr.compare("device") == 0) { // yDebug() << valueStr; DeviceList deviceList; deviceList.push_back(readDeviceTag(devicesElem)); return deviceList; } // "devices" return readDevicesTag(devicesElem); }