%{ #include #include #include #include #include #include #include #include #include #include #ifndef yylex /* We use different prefixes for the lexer and parser. * * Our lexer's prefix is deviceSpecl. * * Our parser's prefix is deviceSpecp. * * Yacc and Bison don't have a way to handle the scenario where the lexer has * a different prefix from the parser that they generate. They assume that the * lexer must have the same prefix as the parser they generate. So we just use * this #define below to override yacc/bison's presumed prefix for the lexer. */ #error "Yacc should have defined yylex as a preprocessor token, and we need to override it to tell yacc the name of our lex function." #endif #undef yylex #define yylex deviceSpecllex #ifdef yytext #undef yytext #endif #define yytext deviceSpecltext // Declare the symbols that our lexer will export. int yylex(void); extern char* yytext; // Declare yytext to access the current token text void yyerror(const char *message) { throw std::runtime_error( std::string("deviceSpec parser error: ") + std::string(message) + " at token: " + std::string(yytext)); } %} %union { char* str; char chr; smo::device::SenseDeviceSpec* sensorSpec; smo::device::InteroceptorDeviceSpec* interoceptorSpec; smo::device::ExtrospectorDeviceSpec* extrospectorSpec; std::vector>* paramVector; std::pair* param; } %token STRING %token PIPE DOUBLE_PIPE LPAREN RPAREN %token KEYWORD_SPECTYPE_ACTUATOR %token KEYWORD_SPECTYPE_EXTROSPECTOR KEYWORD_SPECTYPE_INTEROSPECTOR %token EQUALS // Add new token for '=' %type params opt_params %type param %type spec_body %type interoceptor_spec %type extrospector_spec %% file: /* NOTHING */ | sensor_specs ; sensor_specs: sensor_spec | sensor_specs DOUBLE_PIPE sensor_spec ; sensor_spec: interoceptor_spec | extrospector_spec ; interoceptor_spec: KEYWORD_SPECTYPE_INTEROSPECTOR PIPE spec_body { auto spec = std::make_shared( *static_cast($3)); spec->sensorType = $1; smo::device::DeviceManager::interoceptorDeviceSpecs.push_back(spec); smo::device::DeviceManager::senseDeviceSpecs.push_back(spec); delete $3; } ; extrospector_spec: KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body { auto spec = std::make_shared( *static_cast($3)); spec->sensorType = $1; smo::device::DeviceManager::extrospectorDeviceSpecs.push_back(spec); smo::device::DeviceManager::senseDeviceSpecs.push_back(spec); delete $3; } ; spec_body: STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING { $$ = new smo::device::SenseDeviceSpec(); $$->sensorType = '\0'; $$->implexor = std::string($1); $$->api = std::string($3); $$->apiParams = std::move(*$5); $$->provider = std::string($8); $$->providerParams = std::move(*$10); $$->deviceSelector = std::string($13); delete $5; delete $10; } ; opt_params: params | /* empty */ { $$ = new std::vector>(); } ; params: param { $$ = new std::vector>(); $$->push_back(*$1); delete $1; } | params PIPE param { $$ = $1; $$->push_back(*$3); delete $3; } ; param: STRING { $$ = new std::pair($1, ""); } | STRING EQUALS { $$ = new std::pair($1, ""); } | STRING EQUALS STRING { $$ = new std::pair($1, $3); } ; %%