spirit/classic/example/intermediate/lazy_parser.cpp
2010-11-12 00:36:49 +00:00

127 lines
3.7 KiB
C++

/*=============================================================================
Copyright (c) 2003 Vaclav Vesely
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
//
// This example demonstrates the lazy_p parser. You should read
// "The Lazy Parser" in the documentation.
//
// We want to parse nested blocks of numbers like this:
//
// dec {
// 1 2 3
// bin {
// 1 10 11
// }
// 4 5 6
// }
//
// where the numbers in the "dec" block are wrote in the decimal system and
// the numbers in the "bin" block are wrote in the binary system. We want
// parser to return the overall sum.
//
// To achive this when base ("bin" or "dec") is parsed, in semantic action
// we store a pointer to the appropriate numeric parser in the closure
// variable block.int_rule. Than, when we need to parse a number we use lazy_p
// parser to invoke the parser stored in the block.int_rule pointer.
//
//-----------------------------------------------------------------------------
#include <boost/assert.hpp>
#include <boost/cstdlib.hpp>
#include <boost/spirit/include/phoenix1.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_symbols.hpp>
#include <boost/spirit/include/classic_attribute.hpp>
#include <boost/spirit/include/classic_dynamic.hpp>
using namespace boost;
using namespace BOOST_SPIRIT_CLASSIC_NS;
using namespace phoenix;
//-----------------------------------------------------------------------------
// my grammar
struct my_grammar
: public grammar<my_grammar, parser_context<int> >
{
// grammar definition
template<typename ScannerT>
struct definition
{
typedef rule<ScannerT> rule_t;
typedef stored_rule<ScannerT, parser_context<int> > number_rule_t;
struct block_closure;
typedef boost::spirit::classic::closure<
block_closure,
int,
typename number_rule_t::alias_t>
closure_base_t;
struct block_closure : closure_base_t
{
typename closure_base_t::member1 sum;
typename closure_base_t::member2 int_rule;
};
// block rule type
typedef rule<ScannerT, typename block_closure::context_t> block_rule_t;
block_rule_t block;
rule_t block_item;
symbols<number_rule_t> base;
definition(my_grammar const& self)
{
block =
base[
block.sum = 0,
// store a number rule in a closure member
block.int_rule = arg1
]
>> "{"
>> *block_item
>> "}"
;
block_item =
// use the stored rule
lazy_p(block.int_rule)[block.sum += arg1]
| block[block.sum += arg1]
;
// bind base keywords and number parsers
base.add
("bin", bin_p)
("dec", uint_p)
;
}
block_rule_t const& start() const
{
return block;
}
};
};
//-----------------------------------------------------------------------------
int main()
{
my_grammar gram;
parse_info<> info;
int result;
info = parse("bin{1 dec{1 2 3} 10}", gram[var(result) = arg1], space_p);
BOOST_ASSERT(info.full);
BOOST_ASSERT(result == 9);
return exit_success;
}
//-----------------------------------------------------------------------------