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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.