Re: First-class citizens with only one member causing trouble.
Florian Klemme <[email protected]>
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
I found another workaround I just don't understand. This works perfectly:
// Instructions
instruction = ( // Semicolon terminated instructions
( function_call
| variable_declaration
| variable_assignment
| print_variable
| print_text
| scan_variable
) > ';')
// Non-semicolon terminated instructions
| if_else
| while_loop
| for_loop
| instruction_block;
but this doesn't even compile:
// Instructions
instruction = (function_call > ';')
| (variable_declaration > ';')
| (variable_assignment > ';')
| (print_variable > ';')
| (print_text > ';')
| (scan_variable > ';')
| if_else
| while_loop
| for_loop
| instruction_block;
On 29.07.2016 18:30, Florian Klemme wrote:
>
> Hi,
>
> I have a little compiler project in which Spirit Qi works just fine.
> But there is one little change I'd like to accomplish that causes
> quite some (compilation) trouble. Have a look at this code snippet.
>
> // Instructions
> instruction = (function_call > ';')
> | (variable_declaration > ';')
> | (variable_assignment > ';')
> | print_variable // Implicit semicolon TODO!!!?
> | print_text // Implicit semicolon
> | scan_variable // Implicit semicolon
> | if_else
> | while_loop
> | for_loop
> | instruction_block;
>
> function_call = function_name >> '(' > -(variable_name % ',') >
> ')';
> variable_declaration = qi::lexeme["var"] > variable_name > (('=' >
> expression) | qi::attr(expression::value_t{0u}));
> variable_assignment = variable_name >> '=' > expression;
> print_variable = qi::lexeme["print"] >> variable_name > ';';
> print_text = qi::lexeme["print"] >> qi::lexeme['"' >
> *(qi::char_ - '"') > '"'] > ';';
> scan_variable = qi::lexeme["scan"] > variable_name > ';';
>
> Don't look to deep into what these rules are composed of, the only
> thing that matters is that the first three rules have their trailing
> ';' defined in the instruction rule and the others have their ';' in
> the rule itself.
>
> I want to move all tailing ';' to the instruction rule as shown in the
> first few lines. For the first three rules this hasn't been a problem.
> The literal parser ';' doesn't affect the attribute of the rule so the
> position shouldn't matter.
>
> But in fact, *appending any literal parser before any "// Implicit
> semicolon" comment causes a compilation error*. It took me some time
> to figure out why this is not a problem with the other rules. It turns
> out the problem is that the attribute of the problematic three rules
> are first-class citizens with only one member (which happens to be a
> string, not sure if this is relevant).
>
> So the following ugly workaround actually leads to a compiling (and
> working) solution. By just adding a second member to the attribute of
> the rule.
>
> diff --git a/bf/compiler.cpp b/bf/compiler.cpp
> index 6f83c00..7cea53a 100644
> --- a/bf/compiler.cpp
> +++ b/bf/compiler.cpp
> @@ -103,6 +103,7 @@ namespace instruction {
>
> struct print_variable_t {
> std::string variable_name;
> + int dummy;
> };
>
> struct print_text_t {
> @@ -253,7 +254,8 @@ BOOST_FUSION_ADAPT_STRUCT(
>
> BOOST_FUSION_ADAPT_STRUCT(
> bf::instruction::print_variable_t,
> - (std::string, variable_name))
> + (std::string, variable_name)
> + (int, dummy))
>
> BOOST_FUSION_ADAPT_STRUCT(
> bf::instruction::print_text_t,
> @@ -451,7 +453,7 @@ struct grammar : qi::grammar<iterator,
> program_t(), ascii::space_type> {
> instruction = (function_call > ';')
> | (variable_declaration > ';')
> | (variable_assignment > ';')
> - | print_variable // Implicit semicolon TODO!!!?
> + | (print_variable > ';') // TODO!!!?
> | print_text // Implicit semicolon
> | scan_variable // Implicit semicolon
> | if_else
> @@ -462,7 +464,7 @@ struct grammar : qi::grammar<iterator,
> program_t(), ascii::space_type> {
> function_call = function_name >> '(' > -(variable_name
> % ',') > ')';
> variable_declaration = qi::lexeme["var"] > variable_name >
> (('=' > expression) | qi::attr(expression::value_t{0u}));
> variable_assignment = variable_name >> '=' > expression;
> - print_variable = qi::lexeme["print"] >> variable_name >
> ';';
> + print_variable = qi::lexeme["print"] >> variable_name >
> qi::attr(0);
> print_text = qi::lexeme["print"] >> qi::lexeme['"'
> > *(qi::char_ - '"') > '"'] > ';';
> scan_variable = qi::lexeme["scan"] > variable_name > ';';
> if_else = qi::lexeme["if"] > '(' > expression >
> ')' > instruction > -(qi::lexeme["else"] > instruction);
>
> Have a look at https://github.com/Kruecke/BFGenerator if you want to
> check out the whole code. The critical section is this one:
> https://github.com/Kruecke/BFGenerator/blob/master/bf/compiler.cpp#L454.
> The workaround is committed in a branch as well:
> https://github.com/Kruecke/BFGenerator/compare/semicolon_workaround.
> If you want to run the code, make sure to run "make test" as the other
> rules don't compile this piece of code at the moment.
>
> Please let me know if you have any idea how to fix this problem or
> what mistake I might have made. I am thankful for any ideas. Or is
> there a chance that this is a bug in Spirit Qi?
>
> I tested this with different versions of Boost as well as different
> versions of gcc and msvc. C++14 support is required.
>
> Florian
>
>
>
> ------------------------------------------------------------------------------
>
>
> _______________________________________________
> Spirit-general mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/spirit-general
------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general