Files
salmanoff/hcore/deviceManager/deviceSpecp.yy
T
hayodea edf51a4441 DevSpecp.yy: Fix mirror list use of std::move()d objects
We were building a list of mirrored items filled with the memory
pointed to by unique_ptrs which had already been std::move()d into
other unique_ptrs.
2025-01-13 07:06:28 -04:00

148 lines
4.1 KiB
Plaintext

%{
#include <vector>
#include <utility>
#include <string>
#include <cstring>
#include <cstdlib>
#include <stdexcept>
#include <memory>
#include <functional>
#include <user/senseDeviceSpec.h>
#include <deviceManager/deviceManager.h>
#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
// 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));
}
void mirrorDeviceSpecs() {
for (const auto& interoSpec : DeviceManager::interoceptorDeviceSpecs) {
auto it = std::find_if(
DeviceManager::senseDeviceSpecs.begin(),
DeviceManager::senseDeviceSpecs.end(),
[&interoSpec](const SenseDeviceSpec& spec) {
return spec == *interoSpec;
});
if (it == DeviceManager::senseDeviceSpecs.end()) {
DeviceManager::senseDeviceSpecs.push_back(*interoSpec);
}
}
for (const auto& extroSpec : DeviceManager::extrospectorDeviceSpecs) {
auto it = std::find_if(
DeviceManager::senseDeviceSpecs.begin(),
DeviceManager::senseDeviceSpecs.end(),
[&extroSpec](const SenseDeviceSpec& spec) {
return spec == *extroSpec;
});
if (it == DeviceManager::senseDeviceSpecs.end()) {
DeviceManager::senseDeviceSpecs.push_back(*extroSpec);
}
}
}
%}
%union {
char* str;
char chr;
SenseDeviceSpec* sensorSpec;
InteroceptorDeviceSpec* interoceptorSpec;
ExtrospectorDeviceSpec* extrospectorSpec;
std::vector<std::string>* stringVector;
}
%token <str> STRING
%token PIPE DOUBLE_PIPE LPAREN RPAREN
%token <chr> KEYWORD_SPECTYPE_ACTUATOR
%token <chr> KEYWORD_SPECTYPE_EXTROSPECTOR KEYWORD_SPECTYPE_INTEROSPECTOR
%type <stringVector> params opt_params
%type <sensorSpec> spec_body
%type <interoceptorSpec> interoceptor_spec
%type <extrospectorSpec> extrospector_spec
%%
file: /* NOTHING */
| sensor_specs { mirrorDeviceSpecs(); }
;
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_unique<InteroceptorDeviceSpec>(
*static_cast<InteroceptorDeviceSpec *>($3));
spec->sensorType = $1;
DeviceManager::interoceptorDeviceSpecs.push_back(std::move(spec));
delete $3;
}
;
extrospector_spec:
KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body {
auto spec = std::make_unique<ExtrospectorDeviceSpec>(
*static_cast<ExtrospectorDeviceSpec *>($3));
spec->sensorType = $1;
DeviceManager::extrospectorDeviceSpecs.push_back(std::move(spec));
delete $3;
}
;
spec_body:
STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING {
$$ = new 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<std::string>(); }
;
params:
STRING { $$ = new std::vector<std::string>{ $1 }; }
| params PIPE STRING { $$ = $1; $$->push_back($3); }
;
%%