I'm attempting to write a (partial) CSS parser using Boost.Spirit X3.
I have the (very) basic setup working:
const auto declaration_block_def = '{' >> +declaration >> '}';
const auto declaration_def = property >> ':' >> value >> ';';
const auto property_def = +(char_ - ":");
const auto value_def = +(char_ - ";");
Here value
is just a simple string parser, and property
a symbol table of all the CSS property names to an enum listing all the properties. But now I wonder if I couldn't in some way encode all the possible key-value pairs, in a strongly typed manner? Concretely, I'd use symbols<enum_type>
with matching symbol table entries for each property that has a fixed number of possibilities, and some custom rule for more complex properties like colors.
The thing is that the declaration
rule has to have a certain attribute, and in CSS, the declaration block can contain any number of elements all with their own "attribute" type. In the end I'd like to end up with a struct I'd pass to BOOST_FUSION_ADAPT_STRUCT in the following form:
enum class align_content : std::uint8_t;
enum class align_items : std::uint8_t;
enum class align_self : std::uint8_t;
struct declaration_block
{
css::align_content align_content{};
css::align_items align_items{};
css::align_self align_self{};
};
Which would then properly default initialize any unspecified members.
I see a few issues popping up for X3 that I don't know how to solve:
- Strongly typed rule attribute as mentioned above
- The fusion adapted struct expects all members being parsed, which rules out my idea of my simple approach actually working.
I have found what seems like a Boost.Spirit.Qi 2 implementation, but as X3 is so different and their end result seems unclear, I can't seem to find any help in that...
It looks like you wish to generate your parser code from struct definition. You can, however you should probably use a code generator.
Here's how I know you can get reasonably close with Qi:
Live On Coliru
Prints
More Info/Ideas
This approach is seen in more detail:
I gave that question has an X3-style answer as well:
For more X3 inspiration I heartily recommend:
x3::as_parser
x3::base_parser
/x3::parser<CRTP>
(e.g. Spirit-Qi: How can I write a nonterminal parser?,One pet peeve for me is that we should be able to use structured binding so we don't nee Phoenix anymore.