First things first: I'm using the default C++ language standard for MS Visual Studio 2017 (v15.19.11), C++14, along with Boost v1.65.1
I have an input file formatted like this:
IterName SomeName
IterDesc Some Description
COLUMNS fname.XCT posn.detect.R posn.source.z
expt_KF000000.raw 0.0 27.639320225002102
expt_KF000180.raw 216.34457142857138 30.584848796430673
expt_KF000360.raw 72.68914285714277 33.530377367859245
I am trying to parse & load this into a structure like the following:
struct Stax { std::string stage, axis; };
struct Configuration {
std::map<std::string, std::string> filenames; // "expt_KF000000.raw": "XCT", "other_file.raw": "OCT"
std::map<double, Stax> positions; // 0.0: ["Detect", "R"], 27.639: ["Source", "Z"]
};
struct Iteration {
std::string name;
std::string descript;
std::vector<Configuration> configs;
};
Each line after the one containing "COLUMNS" should generate a new Configuration
instance to be added to Iteration.configs
.
As implied by the comments in the code, some columns may be missing ("fname.OCT" in this example)... but the order of the columns may vary (as will the number) so I've tried using local rule state to hold a variable number of parsers, one for each column, as suggested here: https://stackoverflow.com/a/31382602/1206102
The elements of Configuration.positions
are composed of info following the "posn." header string plus any content parsed from the cell itself. Likewise, elements of Configuration.filenames
are composed of whatever follows "fname." in the header plus the cell content. So I have to somehow save the info I parse from the header row in order to use later when the cells are parsed... so I store this alongside the cell parsers in the rule local state var.
I've tried all manner of things from rule locals to Phoenix-wrapped data members, from direct attribute propagation to Fusion-adapted structs & "customization points", even attr_cast
's with transform_attribute
specializations... but nothing has successfully compiled yet. My list of attempts follows:
- https://wandbox.org/permlink/fU1WOazzxOVPbh9n
- https://wandbox.org/permlink/Itlq3HfydUByUSaH
- https://wandbox.org/permlink/96yDzVpCpI0K4ujs
- https://wandbox.org/permlink/u8iWv61jJSQv01bU
My last attempt still produces 11 compile-time errors, the 1st of which ('const_iterator': is not a member of 'Configuration'
) is telling: something (Qi/Fusion/Phoenix) is expecting Configuration
to be iterable... probably because the parsed type that populates it is (a vector of tuples).
That may be the crux of my problem: I'm trying to stuff a parsed iterable into a non-iterable* complex struct: some of the tuples in the parsed vector will go into one data member of the struct, while others will go into a different data member. (*I say non-iterable because it makes no sense to iterate on Configuration
but if Qi/Fusion/Phoenix insists I could try to accomodate. In fact you'll see a [commented out] attempt to define the const_iterator
type for Configuration
.)
I want to accomplish this using Boost.Spirit if at all possible so... any ideas what I'm doing wrong?