Re: lexeme and leading spaces
Jörg Becker <news <at> elke-joerg.de>
2008-07-04 09:21:38 GMT
On Thursday, 3. July 2008 18:24:19 Jan Swoboda wrote:
> Looks like you don't want to skip initially, so I'd rephrase the
> kill_spaces rule to do its own skipping. Suggested changes are below.
Thanks for your suggestion. But this is exactly what I want to avoid.
This solution is fine for the example, but in the real grammar I have one
literal rule and many kill spaces rules (skip spaces between keywords,
variable names, around brackets, ...). Therefore manually skiping spaces is
error-prone and hard to test.
>
> A cleaner version would be if you could specify a skipper for the
> kill_spaces rule only, but I don't know if that's possible.
Yes, changing or toggling the skip parser on rule level would be nice. I
thought the latter is done by the lexeme directive, but I was wrong, because
the skip parser is called before the rule using the lexeme directive.
I found a solution for all but the first literal. Using the the lexeme
directive for the top rule avoids calling the skip space parser between the
rules on top level. But still loosing the leading spaces. Obviously the skip
parser is called before the first rule (top). I think the skip parser should
not be called before lexeme rules.
#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 2
#include <boost/spirit/attribute.hpp>
#include <boost/spirit/core.hpp>
#include <boost/spirit/phoenix/functions.hpp>
#include <iostream>
using namespace boost::spirit;
using namespace phoenix;
struct my_closure : boost::spirit::closure< my_closure, std::wstring > {
member1 str;
};
struct my_grammar : grammar< my_grammar, my_closure::context_t > {
template < typename scanner_t >
struct definition {
definition ( my_grammar const& self ) {
lit =
lexeme_d[ *( anychar_p - ch_p( '#' ) ) ]
[ lit.str = construct_< std::wstring >( arg1, arg2 ) ]
;
kill_spaces =
ch_p( '#' ) [ kill_spaces.str = '#' ]
>> *( anychar_p - ch_p( '#' ) )
[ kill_spaces.str += construct_< std::wstring >( arg1, arg2 ) ]
>> ch_p( '#' ) [ kill_spaces.str += '#' ]
;
top = lexeme_d[
lit [ self.str = phoenix::arg1 ]
>> kill_spaces [ self.str += phoenix::arg1 ]
>> lit [ self.str += phoenix::arg1 ]
]
;
}
typedef scanner_list <
scanner_t, typename lexeme_scanner< scanner_t >::type
> scanners;
typedef rule< scanners, my_closure::context_t > rule_t;
rule_t kill_spaces, lit, top;
rule_t const& start() const { return top; }
};
};
int
main () {
my_grammar g;
std::wstring ret;
parse_info< wchar_t const * > info;
info = parse(
L" I want to see all (also leading) spaces in the first part "
"# I don't want to see any spaces in the second part. #"
" Here I want to see all (also leading) spaces again. ",
g [ phoenix::var( ret ) = phoenix::arg1 ],
space_p );
assert( info.full );
std::wcout << L"parser returned: '" << ret << L"'." << std::endl;
return 0;
}
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08