2025-01-07 14:08:17 -04:00
|
|
|
%{
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <stdexcept>
|
2025-01-08 06:23:34 -04:00
|
|
|
#include <memory>
|
|
|
|
|
#include <functional>
|
2025-01-13 07:06:28 -04:00
|
|
|
#include <user/senseDeviceSpec.h>
|
2025-01-07 14:08:17 -04:00
|
|
|
#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.
|
|
|
|
|
*/
|
2025-01-07 20:21:15 -04:00
|
|
|
#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."
|
2025-01-07 14:08:17 -04:00
|
|
|
#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: ")
|
2025-01-07 14:24:22 -04:00
|
|
|
+ std::string(message));
|
2025-01-07 14:08:17 -04:00
|
|
|
}
|
|
|
|
|
|
2025-01-13 07:06:28 -04:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-07 14:08:17 -04:00
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%union {
|
|
|
|
|
char* str;
|
|
|
|
|
char chr;
|
2025-01-12 14:31:33 -04:00
|
|
|
SenseDeviceSpec* sensorSpec;
|
|
|
|
|
InteroceptorDeviceSpec* interoceptorSpec;
|
|
|
|
|
ExtrospectorDeviceSpec* extrospectorSpec;
|
2025-01-07 14:08:17 -04:00
|
|
|
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 */
|
2025-01-13 07:06:28 -04:00
|
|
|
| sensor_specs { mirrorDeviceSpecs(); }
|
2025-01-07 14:08:17 -04:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
sensor_specs:
|
|
|
|
|
sensor_spec
|
|
|
|
|
| sensor_specs DOUBLE_PIPE sensor_spec
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
sensor_spec:
|
|
|
|
|
interoceptor_spec
|
|
|
|
|
| extrospector_spec
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
interoceptor_spec:
|
|
|
|
|
KEYWORD_SPECTYPE_INTEROSPECTOR PIPE spec_body {
|
2025-01-12 14:31:33 -04:00
|
|
|
auto spec = std::make_unique<InteroceptorDeviceSpec>(
|
|
|
|
|
*static_cast<InteroceptorDeviceSpec *>($3));
|
2025-01-07 14:08:17 -04:00
|
|
|
|
|
|
|
|
spec->sensorType = $1;
|
2025-01-08 06:23:34 -04:00
|
|
|
DeviceManager::interoceptorDeviceSpecs.push_back(std::move(spec));
|
|
|
|
|
delete $3;
|
2025-01-07 14:08:17 -04:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
extrospector_spec:
|
|
|
|
|
KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body {
|
2025-01-12 14:31:33 -04:00
|
|
|
auto spec = std::make_unique<ExtrospectorDeviceSpec>(
|
|
|
|
|
*static_cast<ExtrospectorDeviceSpec *>($3));
|
2025-01-07 14:08:17 -04:00
|
|
|
|
|
|
|
|
spec->sensorType = $1;
|
2025-01-08 06:23:34 -04:00
|
|
|
DeviceManager::extrospectorDeviceSpecs.push_back(std::move(spec));
|
|
|
|
|
delete $3;
|
2025-01-07 14:08:17 -04:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
spec_body:
|
|
|
|
|
STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING {
|
2025-01-12 14:31:33 -04:00
|
|
|
$$ = new SenseDeviceSpec();
|
2025-01-07 14:08:17 -04:00
|
|
|
$$->sensorType = '\0';
|
|
|
|
|
$$->implexor = std::string($1);
|
|
|
|
|
$$->api = std::string($3);
|
|
|
|
|
$$->apiParams = std::move(*$5);
|
2025-01-07 20:03:03 -04:00
|
|
|
$$->provider = std::string($8);
|
|
|
|
|
$$->providerParams = std::move(*$10);
|
2025-01-07 14:08:17 -04:00
|
|
|
$$->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); }
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
%%
|