632a227985
We no longer do intrin specs as a separate stimbuff; rather now we do them as a specifier segment within the pipeline spec of a normal nontrin spec.
232 lines
6.8 KiB
Plaintext
232 lines
6.8 KiB
Plaintext
%{
|
|
#include <vector>
|
|
#include <utility>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
#include <stdexcept>
|
|
#include <memory>
|
|
#include <functional>
|
|
#include <user/deviceAttachmentSpec.h>
|
|
#include <deviceManager/deviceManager.h>
|
|
|
|
#ifndef yylex
|
|
/* We use different prefixes for the lexer and parser.
|
|
* * Our lexer's prefix is deviceAttachmentPipeSpecl.
|
|
* * Our parser's prefix is deviceAttachmentPipeSpecp.
|
|
*
|
|
* 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 deviceAttachmentPipeSpecllex
|
|
|
|
#ifdef yytext
|
|
#undef yytext
|
|
#endif
|
|
#define yytext deviceAttachmentPipeSpecltext
|
|
|
|
// 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("deviceAttachmentPipeSpec parser error: ")
|
|
+ std::string(message)
|
|
+ " at token: " + std::string(yytext));
|
|
}
|
|
|
|
%}
|
|
|
|
%union {
|
|
char* str;
|
|
char chr;
|
|
smo::device::DeviceAttachmentSpec* sensorSpec;
|
|
smo::device::InteroceptorDevAttachmentSpec* interoceptorSpec;
|
|
smo::device::ExtrospectorDevAttachmentSpec* extrospectorSpec;
|
|
std::vector<std::pair<std::string,std::string>>* paramVector;
|
|
std::pair<std::string,std::string>* param;
|
|
smo::device::DapSegment* DapSpecSegment;
|
|
std::vector<smo::device::DapSegment>* DapSegmentVector;
|
|
}
|
|
|
|
%token <str> STRING
|
|
%token PIPE DOUBLE_PIPE LPAREN RPAREN
|
|
%token <chr> KEYWORD_SPECTYPE_ACTUATOR
|
|
%token <chr> KEYWORD_SPECTYPE_EXTROSPECTOR KEYWORD_SPECTYPE_INTEROSPECTOR
|
|
%token EQUALS // Add new token for '='
|
|
|
|
%type <paramVector> params opt_params
|
|
%type <param> param
|
|
%type <sensorSpec> spec_body
|
|
%type <interoceptorSpec> interoceptor_spec
|
|
%type <extrospectorSpec> extrospector_spec
|
|
%type <DapSpecSegment> specifier_segment
|
|
%type <DapSegmentVector> specifier_segments
|
|
|
|
%%
|
|
|
|
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<smo::device::InteroceptorDevAttachmentSpec>(
|
|
*static_cast<smo::device::InteroceptorDevAttachmentSpec *>($3));
|
|
|
|
spec->sensorType = $1;
|
|
smo::device::DeviceManager::commandLineDASpecs.push_back(*spec);
|
|
|
|
delete $3;
|
|
}
|
|
;
|
|
|
|
extrospector_spec:
|
|
KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body {
|
|
auto spec = std::make_shared<smo::device::ExtrospectorDevAttachmentSpec>(
|
|
*static_cast<smo::device::ExtrospectorDevAttachmentSpec *>($3));
|
|
|
|
spec->sensorType = $1;
|
|
smo::device::DeviceManager::commandLineDASpecs.push_back(*spec);
|
|
|
|
delete $3;
|
|
}
|
|
;
|
|
|
|
spec_body:
|
|
STRING PIPE specifier_segments PIPE STRING {
|
|
auto segments = std::unique_ptr<std::vector<smo::device::DapSegment>>($3);
|
|
|
|
if (segments->size() < 3 || segments->size() > 5)
|
|
{
|
|
throw std::runtime_error(
|
|
"DAP spec for device '" + std::string($1) + "' must declare "
|
|
"qualeIfaceApi, stimBuffApi and provider (optionally preceded "
|
|
"by up to one postrin and one negtrin segment); got "
|
|
+ std::to_string(segments->size()) + " pre-devSelector segments.");
|
|
}
|
|
|
|
const size_t nIntrins = segments->size() - 3;
|
|
|
|
$$ = new smo::device::DeviceAttachmentSpec();
|
|
$$->deviceIdentifier = std::string($1);
|
|
$$->sensorType = '\0'; // This will be set by the parent rule
|
|
|
|
for (size_t i = 0; i < nIntrins; ++i)
|
|
{
|
|
auto& seg = (*segments)[i];
|
|
if (seg.name == "postrin")
|
|
{
|
|
if (!$$->postrin.empty())
|
|
{
|
|
throw std::runtime_error(
|
|
"DAP spec for device '" + $$->deviceIdentifier
|
|
+ "' declares more than one postrin segment.");
|
|
}
|
|
$$->postrin = seg.name;
|
|
$$->postrinParams = std::move(seg.params);
|
|
}
|
|
else if (seg.name == "negtrin")
|
|
{
|
|
if (!$$->negtrin.empty())
|
|
{
|
|
throw std::runtime_error(
|
|
"DAP spec for device '" + $$->deviceIdentifier
|
|
+ "' declares more than one negtrin segment.");
|
|
}
|
|
$$->negtrin = seg.name;
|
|
$$->negtrinParams = std::move(seg.params);
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error(
|
|
"DAP spec segment before qualeIfaceApi must be 'postrin' "
|
|
"or 'negtrin' (got '" + seg.name + "') for device '"
|
|
+ $$->deviceIdentifier + "'.");
|
|
}
|
|
}
|
|
|
|
auto& qSeg = (*segments)[nIntrins];
|
|
auto& sSeg = (*segments)[nIntrins + 1];
|
|
auto& pSeg = (*segments)[nIntrins + 2];
|
|
|
|
$$->qualeIfaceApi = std::move(qSeg.name);
|
|
$$->qualeIfaceApiParams = std::move(qSeg.params);
|
|
$$->stimBuffApi = std::move(sSeg.name);
|
|
$$->stimBuffApiParams = std::move(sSeg.params);
|
|
$$->provider = std::move(pSeg.name);
|
|
$$->providerParams = std::move(pSeg.params);
|
|
$$->deviceSelector = std::string($5);
|
|
}
|
|
;
|
|
|
|
specifier_segments:
|
|
specifier_segment {
|
|
$$ = new std::vector<smo::device::DapSegment>();
|
|
$$->push_back(std::move(*$1));
|
|
delete $1;
|
|
}
|
|
| specifier_segments PIPE specifier_segment {
|
|
$$ = $1;
|
|
$$->push_back(std::move(*$3));
|
|
delete $3;
|
|
}
|
|
;
|
|
|
|
specifier_segment:
|
|
STRING LPAREN opt_params RPAREN {
|
|
$$ = new smo::device::DapSegment();
|
|
$$->name = std::string($1);
|
|
$$->params = std::move(*$3);
|
|
delete $3;
|
|
}
|
|
;
|
|
|
|
opt_params:
|
|
params
|
|
| /* empty */ { $$ = new std::vector<std::pair<std::string,std::string>>(); }
|
|
;
|
|
|
|
params:
|
|
param {
|
|
$$ = new std::vector<std::pair<std::string,std::string>>();
|
|
$$->push_back(*$1);
|
|
delete $1;
|
|
}
|
|
| params PIPE param {
|
|
$$ = $1;
|
|
$$->push_back(*$3);
|
|
delete $3;
|
|
}
|
|
;
|
|
|
|
param:
|
|
STRING {
|
|
$$ = new std::pair<std::string,std::string>($1, "");
|
|
}
|
|
| STRING EQUALS {
|
|
$$ = new std::pair<std::string,std::string>($1, "");
|
|
}
|
|
| STRING EQUALS STRING {
|
|
$$ = new std::pair<std::string,std::string>($1, $3);
|
|
}
|
|
;
|
|
|
|
%%
|