%{ #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, and we need to override it to tell yacc the name of our lex function." #endif #undef yylex #define yylex deviceSpecllex // Declare the symbols that our lexer will export. int yylex(void); void yyerror(const char *message) { throw std::runtime_error( std::string("deviceSpec parser error: ") + std::string(message)); } %} %union { char* str; char chr; DeviceManager::SensorDeviceSpec* sensorSpec; DeviceManager::InteroceptorDeviceSpec* interoceptorSpec; DeviceManager::ExtrospectorDeviceSpec* extrospectorSpec; std::vector* stringVector; } %token STRING %token PIPE DOUBLE_PIPE LPAREN RPAREN %token KEYWORD_SPECTYPE_ACTUATOR %token KEYWORD_SPECTYPE_EXTROSPECTOR KEYWORD_SPECTYPE_INTEROSPECTOR %type params opt_params %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 { DeviceManager::InteroceptorDeviceSpec *spec = static_cast($3); spec->sensorType = $1; DeviceManager::interoceptorDeviceSpecs.push_back(*spec); delete spec; } ; extrospector_spec: KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body { DeviceManager::ExtrospectorDeviceSpec *spec = static_cast($3); spec->sensorType = $1; DeviceManager::extrospectorDeviceSpecs.push_back(*spec); delete spec; } ; spec_body: STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING { $$ = new DeviceManager::SensorDeviceSpec(); $$->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: STRING { $$ = new std::vector{ $1 }; } | params PIPE STRING { $$ = $1; $$->push_back($3); } ; %%