spirit and phoenix - passing variables

Started by
2 comments, last by Deyja 16 years, 10 months ago
Please, consider the following snippet:

// Main function
int main()
{
    const std::string input = "[foofoo]\nvar=val";

    test_grammar g;
    std::string output;
    
    // std::string variable;
    // int value;

    std::cout << parse(input.c_str(), g[var(output) = arg1]).full << std::endl // 1
    std::cout << output << std::endl; // foofoo
    
    std::cin.get();
    return 0;
}

// The rather simple grammar I'm using
struct test_closure : closure<test_closure, std::string, std::string, int>
{
    member1 name;
    member2 var;
    member3 val;
};

struct test_grammar : public grammar<test_grammar, test_closure::context_t>
{
    template <typename ScannerT>
    struct definition
    {
        definition(const test_grammar& self)
        {  
           section_title = confix_p(ch_p('['), (*anychar_p)[self.name = construct_<std::string>(arg1, arg2)], ch_p(']'));
           
           item = confix_p(*anychar_p, ch_p('='), *anychar_p);

           section = (section_title >> list_p(item));
        }
        
        rule<ScannerT> section_title, section, item;

        const rule<ScannerT>& start() const { return section; }
    };
};

Seems to be working fine, but is it possible to pass variable and value in the same way as I passed output? If it is, how? g[var(output) = arg1, ...] ? Am I just somehow missing the syntax or am I doing it the "wrong way"?
Advertisement
I don't know off-hand; but a good place to look for answers begins here:

https://lists.sourceforge.net/lists/listinfo/spirit-general

The mailing list is very active, and I'm sure you'd get a fairly quick answer, if nothing happens in this thread.
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
*bump, still struggling with this one. I'm pretty confident this is somehow possible. Any help will be appreciated, thanks!
What, exactly, are you trying to do? If it's what I think it is, this example might help. The key is the closure type, which allows you to carry information through an entire syntax tree. I clipped this code out of a parser I wrote to build an abstract syntax tree for a special purpose language and simplified it some.

#include <boost/spirit.hpp>#include <boost/spirit/phoenix/primitives.hpp>#include <boost/spirit/phoenix/operators.hpp>#include <boost/spirit/phoenix/functions.hpp>	struct closure : boost::spirit::closure<closure, int, int>	{		member1 _result;		member2 _second;	};	rule<boost::spirit::scanner<>, closure::context_t> add;	//matches [int:int]      	add = 		( 			ch_p('[') >> 			int_matcher[add._result = arg1] >> //Notice how we can refer to add. 				//arg1 is the result of int_matcher. (I made the name int_matcher up.)                                //arg1 is always the name of the result when you nest rules.                                //It also will refer to the member1 _result member                                 //of your custom rule's closure.			ch_p(':') >> 			int_matcher[add._second = arg1] >> 			ch_p(']') 		)		[add._result = add._result + add._second]; 	//To actually parse...	int result;	if (parse("[10:5]", (add[ assign_a(result) ])).full )	{		assert(result == 15);	}


Spirit gets real ugly real quick.
You have been warned.

This topic is closed to new replies.

Advertisement