Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::spirit::qi and out-of-sequence variables

I'm writing a lexigraphical analyser. It takes an English string, and converts it into a set of latitude/longitude co-ordinates. It's a bit like Google Earth.

Anyway, I've written my symbol tables and grammar, and it's happily parsing formatted data.

struct LatLongDegrees
{
 std::string  dirLat_;
 double   degLat_;
 std::string     dirLong_;
 double   degLong_;
}

For example: {"North", 23.59, "East", -30.82}

Here is my grammar:

 basic =(latitude >> ' ' >> double_ >> ' ' >> longitude >> ' ' >> double_);

Where latitude and longitude are symbol tables that map from shorthand compass directions to strings (eg "e" to "East")

So, on to my question:

I want to add the following rule to my grammar, where the latitude and longitude symbols are in the opposite positions:

reversed = (longitude  >> ' ' >> double_ >> ' ' >> latitude >> double_ )

This parses, BUT the degLat_ and degLong_ values are not reversed along with string values. They are simply parsed directly into the struct, without regard for the string labels.

How do I build a struct (or boost::fusion vector) when the data to be parsed is not sequential?

like image 979
LogicalUnit Avatar asked Jan 24 '11 23:01

LogicalUnit


1 Answers

You have several possibilities. The easiest is to adapt your struct into a Fusion sequence in the required order:

BOOST_FUSION_ADAPT_STRUCT(
    LatLongDegrees,
    (std::string, dirLong_)
    (double, degLong_)
    (std::string, dirLat_)
    (double, degLat_)
);

(yes, the order of adaptation does not have to match the order of the members in the original struct, you can even leave out members or duplicate them). This works fine if you have one particular order you want to parse your members in.

If you need different orderings in the same program, you might want to utilize a similar adaptation mechanism, but which additionally allows to give a name to the adapted struct:

BOOST_FUSION_ADAPT_STRUCT_NAME(
    LatLongDegrees, reversed_LatLongDegrees,
    (std::string, dirLong_)
    (double, degLong_)
    (std::string, dirLat_)
    (double, degLat_)
);

where reversed_LatLongDegrees is the data type used as the attribute in your Spirit grammar:

rule <Iterator, reversed_LatLongDegrees()> reversed;
reversed = longitude  >> ' ' >> double_ >> ' ' >> latitude >> double_;

LatLongDegrees data;
parse(begin, end, reversed, data);

This allows to create several adaptations for the same struct at the same time.

like image 99
hkaiser Avatar answered Nov 20 '22 09:11

hkaiser