From 8190791653d916a2dfe002155f435316bd7e1b69 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Fri, 31 Jan 2003 10:44:50 +0000 Subject: [PATCH] First commit from BOOST_REVIEW branch spirit.sf.net [SVN r17107] --- .gitattributes | 96 + include/boost/spirit.hpp | 67 + include/boost/spirit/Makefile.am | 4 + include/boost/spirit/attribute.hpp | 39 + include/boost/spirit/attribute/Makefile.am | 4 + include/boost/spirit/attribute/closure.hpp | 1077 +++++ include/boost/spirit/attribute/grouping.hpp | 177 + .../boost/spirit/attribute/impl/Makefile.am | 3 + .../boost/spirit/attribute/impl/grouping.ipp | 320 ++ include/boost/spirit/attribute/parametric.hpp | 142 + include/boost/spirit/core.hpp | 65 + include/boost/spirit/core/Makefile.am | 4 + include/boost/spirit/core/basics.hpp | 69 + .../boost/spirit/core/composite/Makefile.am | 4 + .../boost/spirit/core/composite/actions.hpp | 299 ++ .../boost/spirit/core/composite/composite.hpp | 151 + .../spirit/core/composite/directives.hpp | 589 +++ .../boost/spirit/core/composite/epsilon.hpp | 279 ++ .../spirit/core/composite/impl/Makefile.am | 3 + .../spirit/core/composite/impl/composite.ipp | 158 + .../spirit/core/composite/impl/directives.ipp | 374 ++ .../spirit/core/composite/impl/operators.ipp | 668 ++++ .../boost/spirit/core/composite/operators.hpp | 1090 ++++++ include/boost/spirit/core/impl/Makefile.am | 3 + include/boost/spirit/core/impl/basics.ipp | 51 + include/boost/spirit/core/impl/match.ipp | 180 + include/boost/spirit/core/impl/msvc.hpp | 211 + include/boost/spirit/core/impl/parser.ipp | 56 + include/boost/spirit/core/match.hpp | 162 + include/boost/spirit/core/meta/Makefile.am | 4 + .../boost/spirit/core/meta/fundamental.hpp | 93 + .../boost/spirit/core/meta/impl/Makefile.am | 3 + .../spirit/core/meta/impl/fundamental.ipp | 306 ++ .../spirit/core/meta/impl/parser_traits.ipp | 200 + .../spirit/core/meta/impl/parser_type.hpp | 197 + .../boost/spirit/core/meta/impl/traverse.ipp | 553 +++ .../boost/spirit/core/meta/parser_traits.hpp | 318 ++ include/boost/spirit/core/meta/traverse.hpp | 255 ++ .../spirit/core/non_terminal/Makefile.am | 4 + .../spirit/core/non_terminal/grammar.hpp | 76 + .../spirit/core/non_terminal/impl/Makefile.am | 3 + .../spirit/core/non_terminal/impl/grammar.ipp | 301 ++ .../core/non_terminal/impl/object_with_id.ipp | 159 + .../spirit/core/non_terminal/impl/rule.ipp | 101 + .../spirit/core/non_terminal/impl/subrule.ipp | 208 + .../core/non_terminal/parser_context.hpp | 152 + .../spirit/core/non_terminal/parser_id.hpp | 77 + .../boost/spirit/core/non_terminal/rule.hpp | 117 + .../spirit/core/non_terminal/subrule.hpp | 316 ++ include/boost/spirit/core/parser.hpp | 247 ++ .../boost/spirit/core/primitives/Makefile.am | 4 + .../spirit/core/primitives/impl/Makefile.am | 3 + .../spirit/core/primitives/impl/numerics.ipp | 480 +++ .../core/primitives/impl/primitives.ipp | 179 + .../boost/spirit/core/primitives/numerics.hpp | 279 ++ .../spirit/core/primitives/primitives.hpp | 567 +++ include/boost/spirit/core/scanner/Makefile.am | 4 + .../spirit/core/scanner/impl/Makefile.am | 3 + .../spirit/core/scanner/impl/skipper.ipp | 178 + include/boost/spirit/core/scanner/scanner.hpp | 373 ++ include/boost/spirit/core/scanner/skipper.hpp | 171 + include/boost/spirit/debug.hpp | 146 + include/boost/spirit/debug/Makefile.am | 4 + include/boost/spirit/debug/assert.hpp | 36 + include/boost/spirit/debug/debug_node.hpp | 181 + include/boost/spirit/debug/impl/Makefile.am | 3 + .../boost/spirit/debug/impl/parser_names.ipp | 515 +++ include/boost/spirit/debug/minimal.hpp | 84 + include/boost/spirit/debug/parser_names.hpp | 243 ++ include/boost/spirit/dynamic.hpp | 34 + include/boost/spirit/dynamic/for.hpp | 203 + include/boost/spirit/dynamic/if.hpp | 207 + .../boost/spirit/dynamic/impl/conditions.ipp | 126 + include/boost/spirit/dynamic/while.hpp | 229 ++ include/boost/spirit/error_handling.hpp | 22 + .../boost/spirit/error_handling/Makefile.am | 4 + .../spirit/error_handling/exceptions.hpp | 345 ++ .../spirit/error_handling/impl/Makefile.am | 3 + .../spirit/error_handling/impl/exceptions.ipp | 85 + include/boost/spirit/iterator.hpp | 30 + include/boost/spirit/iterator/Makefile.am | 4 + .../boost/spirit/iterator/file_iterator.hpp | 304 ++ .../spirit/iterator/fixed_size_queue.hpp | 306 ++ .../boost/spirit/iterator/impl/Makefile.am | 3 + .../spirit/iterator/impl/file_iterator.ipp | 514 +++ include/boost/spirit/iterator/multi_pass.hpp | 1224 ++++++ .../spirit/iterator/position_iterator.hpp | 195 + include/boost/spirit/phoenix/Makefile.am | 3 + include/boost/spirit/phoenix/actor.hpp | 614 +++ include/boost/spirit/phoenix/binders.hpp | 3450 +++++++++++++++++ include/boost/spirit/phoenix/casts.hpp | 1292 ++++++ include/boost/spirit/phoenix/closures.hpp | 359 ++ include/boost/spirit/phoenix/composite.hpp | 1415 +++++++ include/boost/spirit/phoenix/functions.hpp | 743 ++++ include/boost/spirit/phoenix/operators.hpp | 2215 +++++++++++ include/boost/spirit/phoenix/primitives.hpp | 249 ++ include/boost/spirit/phoenix/special_ops.hpp | 343 ++ include/boost/spirit/phoenix/statements.hpp | 445 +++ .../boost/spirit/phoenix/tuple_helpers.hpp | 1077 +++++ include/boost/spirit/phoenix/tuples.hpp | 1297 +++++++ include/boost/spirit/symbols.hpp | 22 + include/boost/spirit/symbols/Makefile.am | 4 + include/boost/spirit/symbols/impl/Makefile.am | 3 + include/boost/spirit/symbols/impl/symbols.ipp | 98 + include/boost/spirit/symbols/impl/tst.ipp | 272 ++ include/boost/spirit/symbols/symbols.hpp | 239 ++ include/boost/spirit/tree/Makefile.am | 4 + include/boost/spirit/tree/ast.hpp | 323 ++ include/boost/spirit/tree/common.hpp | 1355 +++++++ 109 files changed, 33148 insertions(+) create mode 100644 .gitattributes create mode 100644 include/boost/spirit.hpp create mode 100644 include/boost/spirit/Makefile.am create mode 100644 include/boost/spirit/attribute.hpp create mode 100644 include/boost/spirit/attribute/Makefile.am create mode 100644 include/boost/spirit/attribute/closure.hpp create mode 100644 include/boost/spirit/attribute/grouping.hpp create mode 100644 include/boost/spirit/attribute/impl/Makefile.am create mode 100644 include/boost/spirit/attribute/impl/grouping.ipp create mode 100644 include/boost/spirit/attribute/parametric.hpp create mode 100644 include/boost/spirit/core.hpp create mode 100644 include/boost/spirit/core/Makefile.am create mode 100644 include/boost/spirit/core/basics.hpp create mode 100644 include/boost/spirit/core/composite/Makefile.am create mode 100644 include/boost/spirit/core/composite/actions.hpp create mode 100644 include/boost/spirit/core/composite/composite.hpp create mode 100644 include/boost/spirit/core/composite/directives.hpp create mode 100644 include/boost/spirit/core/composite/epsilon.hpp create mode 100644 include/boost/spirit/core/composite/impl/Makefile.am create mode 100644 include/boost/spirit/core/composite/impl/composite.ipp create mode 100644 include/boost/spirit/core/composite/impl/directives.ipp create mode 100644 include/boost/spirit/core/composite/impl/operators.ipp create mode 100644 include/boost/spirit/core/composite/operators.hpp create mode 100644 include/boost/spirit/core/impl/Makefile.am create mode 100644 include/boost/spirit/core/impl/basics.ipp create mode 100644 include/boost/spirit/core/impl/match.ipp create mode 100644 include/boost/spirit/core/impl/msvc.hpp create mode 100644 include/boost/spirit/core/impl/parser.ipp create mode 100644 include/boost/spirit/core/match.hpp create mode 100644 include/boost/spirit/core/meta/Makefile.am create mode 100644 include/boost/spirit/core/meta/fundamental.hpp create mode 100644 include/boost/spirit/core/meta/impl/Makefile.am create mode 100644 include/boost/spirit/core/meta/impl/fundamental.ipp create mode 100644 include/boost/spirit/core/meta/impl/parser_traits.ipp create mode 100644 include/boost/spirit/core/meta/impl/parser_type.hpp create mode 100644 include/boost/spirit/core/meta/impl/traverse.ipp create mode 100644 include/boost/spirit/core/meta/parser_traits.hpp create mode 100644 include/boost/spirit/core/meta/traverse.hpp create mode 100644 include/boost/spirit/core/non_terminal/Makefile.am create mode 100644 include/boost/spirit/core/non_terminal/grammar.hpp create mode 100644 include/boost/spirit/core/non_terminal/impl/Makefile.am create mode 100644 include/boost/spirit/core/non_terminal/impl/grammar.ipp create mode 100644 include/boost/spirit/core/non_terminal/impl/object_with_id.ipp create mode 100644 include/boost/spirit/core/non_terminal/impl/rule.ipp create mode 100644 include/boost/spirit/core/non_terminal/impl/subrule.ipp create mode 100644 include/boost/spirit/core/non_terminal/parser_context.hpp create mode 100644 include/boost/spirit/core/non_terminal/parser_id.hpp create mode 100644 include/boost/spirit/core/non_terminal/rule.hpp create mode 100644 include/boost/spirit/core/non_terminal/subrule.hpp create mode 100644 include/boost/spirit/core/parser.hpp create mode 100644 include/boost/spirit/core/primitives/Makefile.am create mode 100644 include/boost/spirit/core/primitives/impl/Makefile.am create mode 100644 include/boost/spirit/core/primitives/impl/numerics.ipp create mode 100644 include/boost/spirit/core/primitives/impl/primitives.ipp create mode 100644 include/boost/spirit/core/primitives/numerics.hpp create mode 100644 include/boost/spirit/core/primitives/primitives.hpp create mode 100644 include/boost/spirit/core/scanner/Makefile.am create mode 100644 include/boost/spirit/core/scanner/impl/Makefile.am create mode 100644 include/boost/spirit/core/scanner/impl/skipper.ipp create mode 100644 include/boost/spirit/core/scanner/scanner.hpp create mode 100644 include/boost/spirit/core/scanner/skipper.hpp create mode 100644 include/boost/spirit/debug.hpp create mode 100644 include/boost/spirit/debug/Makefile.am create mode 100644 include/boost/spirit/debug/assert.hpp create mode 100644 include/boost/spirit/debug/debug_node.hpp create mode 100644 include/boost/spirit/debug/impl/Makefile.am create mode 100644 include/boost/spirit/debug/impl/parser_names.ipp create mode 100644 include/boost/spirit/debug/minimal.hpp create mode 100644 include/boost/spirit/debug/parser_names.hpp create mode 100644 include/boost/spirit/dynamic.hpp create mode 100644 include/boost/spirit/dynamic/for.hpp create mode 100644 include/boost/spirit/dynamic/if.hpp create mode 100644 include/boost/spirit/dynamic/impl/conditions.ipp create mode 100644 include/boost/spirit/dynamic/while.hpp create mode 100644 include/boost/spirit/error_handling.hpp create mode 100644 include/boost/spirit/error_handling/Makefile.am create mode 100644 include/boost/spirit/error_handling/exceptions.hpp create mode 100644 include/boost/spirit/error_handling/impl/Makefile.am create mode 100644 include/boost/spirit/error_handling/impl/exceptions.ipp create mode 100644 include/boost/spirit/iterator.hpp create mode 100644 include/boost/spirit/iterator/Makefile.am create mode 100644 include/boost/spirit/iterator/file_iterator.hpp create mode 100644 include/boost/spirit/iterator/fixed_size_queue.hpp create mode 100644 include/boost/spirit/iterator/impl/Makefile.am create mode 100644 include/boost/spirit/iterator/impl/file_iterator.ipp create mode 100644 include/boost/spirit/iterator/multi_pass.hpp create mode 100644 include/boost/spirit/iterator/position_iterator.hpp create mode 100644 include/boost/spirit/phoenix/Makefile.am create mode 100644 include/boost/spirit/phoenix/actor.hpp create mode 100644 include/boost/spirit/phoenix/binders.hpp create mode 100644 include/boost/spirit/phoenix/casts.hpp create mode 100644 include/boost/spirit/phoenix/closures.hpp create mode 100644 include/boost/spirit/phoenix/composite.hpp create mode 100644 include/boost/spirit/phoenix/functions.hpp create mode 100644 include/boost/spirit/phoenix/operators.hpp create mode 100644 include/boost/spirit/phoenix/primitives.hpp create mode 100644 include/boost/spirit/phoenix/special_ops.hpp create mode 100644 include/boost/spirit/phoenix/statements.hpp create mode 100644 include/boost/spirit/phoenix/tuple_helpers.hpp create mode 100644 include/boost/spirit/phoenix/tuples.hpp create mode 100644 include/boost/spirit/symbols.hpp create mode 100644 include/boost/spirit/symbols/Makefile.am create mode 100644 include/boost/spirit/symbols/impl/Makefile.am create mode 100644 include/boost/spirit/symbols/impl/symbols.ipp create mode 100644 include/boost/spirit/symbols/impl/tst.ipp create mode 100644 include/boost/spirit/symbols/symbols.hpp create mode 100644 include/boost/spirit/tree/Makefile.am create mode 100644 include/boost/spirit/tree/ast.hpp create mode 100644 include/boost/spirit/tree/common.hpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..3e84d7c70 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/include/boost/spirit.hpp b/include/boost/spirit.hpp new file mode 100644 index 000000000..ab2f93967 --- /dev/null +++ b/include/boost/spirit.hpp @@ -0,0 +1,67 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2001-2003 Hartmut Kaiser + Copyright (c) 2002-2003 Martin Wille + Copyright (c) 2002 Juan Carlos Arevalo-Baeza + Copyright (c) 2002 Raghavendra Satish + Copyright (c) 2002 Jeff Westfahl + Copyright (c) 2001 Bruce Florman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(SPIRIT_HPP) +#define SPIRIT_HPP + +#define SPIRIT_VERSION 0x1501 +#define SPIRIT_PIZZA_VERSION PEPPERONI_PLUS // :-) + +/////////////////////////////////////////////////////////////////////////////// +// +// If SPIRIT_DEBUG is defined, the following header includes the +// Spirit.Debug layer, otherwise the non-debug Spirit.Core is included. +// +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.ErrorHandling +// +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/error_handling.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.Iterators +// +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/iterator.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.Symbols +// +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/symbols.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.Utilities +// +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/utility.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.Attributes +// +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/attribute.hpp" + +#endif // !defined(SPIRIT_HPP) diff --git a/include/boost/spirit/Makefile.am b/include/boost/spirit/Makefile.am new file mode 100644 index 000000000..3656b8e8f --- /dev/null +++ b/include/boost/spirit/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = tree core debug error_handling symbols utility attribute iterator +spiritinclude_HEADERS = attribute.hpp core.hpp debug.hpp error_handling.hpp iterator.hpp symbols.hpp utility.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit diff --git a/include/boost/spirit/attribute.hpp b/include/boost/spirit/attribute.hpp new file mode 100644 index 000000000..34e230665 --- /dev/null +++ b/include/boost/spirit/attribute.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_ATTRIBUTE_MAIN_HPP) +#define BOOST_SPIRIT_ATTRIBUTE_MAIN_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// Master header for Spirit.Attributes +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// Phoenix predefined maximum limit. This limit defines the maximum +// number of elements a tuple can hold. This number defaults to 3. The +// actual maximum is rounded up in multiples of 3. Thus, if this value +// is 4, the actual limit is 6. The ultimate maximum limit in this +// implementation is 15. +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(PHOENIX_LIMIT) +#define PHOENIX_LIMIT 3 +#endif // !defined(PHOENIX_LIMIT) + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/attribute/parametric.hpp" +#include "boost/spirit/attribute/closure.hpp" +#include "boost/spirit/attribute/grouping.hpp" + +#endif // !defined(BOOST_SPIRIT_ATTRIBUTE_MAIN_HPP) diff --git a/include/boost/spirit/attribute/Makefile.am b/include/boost/spirit/attribute/Makefile.am new file mode 100644 index 000000000..f3d24c6d5 --- /dev/null +++ b/include/boost/spirit/attribute/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = closure.hpp grouping.hpp parametric.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/attribute diff --git a/include/boost/spirit/attribute/closure.hpp b/include/boost/spirit/attribute/closure.hpp new file mode 100644 index 000000000..ea85d75a0 --- /dev/null +++ b/include/boost/spirit/attribute/closure.hpp @@ -0,0 +1,1077 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_CLOSURE_HPP +#define BOOST_SPIRIT_CLOSURE_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/composite/composite.hpp" +#include "boost/spirit/attribute/parametric.hpp" + +#include "boost/phoenix/closures.hpp" +#include "boost/phoenix/primitives.hpp" +#include "boost/phoenix/casts.hpp" +#include "boost/phoenix/operators.hpp" +#include "boost/phoenix/tuple_helpers.hpp" + +#include + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit predefined maximum closure limit. This limit defines the maximum +// number of elements a closure can hold. This number defaults to 3. The +// actual maximum is rounded up in multiples of 3. Thus, if this value +// is 4, the actual limit is 6. The ultimate maximum limit in this +// implementation is 15. +// +// It should NOT be greater than PHOENIX_LIMIT! +// +/////////////////////////////////////////////////////////////////////////////// + +#if !defined(BOOST_SPIRIT_CLOSURE_LIMIT) +#define BOOST_SPIRIT_CLOSURE_LIMIT PHOENIX_LIMIT +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// ensure BOOST_SPIRIT_CLOSURE_LIMIT <= PHOENIX_LIMIT and SPIRIT_CLOSURE_LIMIT <= 15 +// +/////////////////////////////////////////////////////////////////////////////// +BOOST_STATIC_ASSERT(BOOST_SPIRIT_CLOSURE_LIMIT <= PHOENIX_LIMIT); +BOOST_STATIC_ASSERT(BOOST_SPIRIT_CLOSURE_LIMIT <= 15); + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // closure_context class + // + /////////////////////////////////////////////////////////////////////////// + template + class closure_context + { + public: + + typedef typename phoenix::tuple_element<0, + typename ClosureT::tuple_t>::type attr_t; + typedef ClosureT base_t; + + closure_context(ClosureT const& clos) + : frame(clos) {} + + ~closure_context() {} + + template + void pre_parse(ParserT const&, ScannerT const&) {} + + template + ResultT& post_parse(ResultT& hit, ParserT const&, ScannerT const&) + { hit.value() = frame[phoenix::tuple_index<0>()]; return hit; } + + private: + + phoenix::closure_frame frame; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // init_closure_context class + // + // The init_closure_context class is a special parser context type + // which additionally initializes a closure contained in the derived + // parser with values from a given tuple. Please note, that this + // given tuple does not contain the required values directly, it + // contains phoenix::actor objects. These actors have to be + // dereferenced to gain the values to be used for initialization + // (this is done by the help of the phoenix::convert_actors<> + // template). + // + /////////////////////////////////////////////////////////////////////////// + + template + class init_closure_context + { + typedef typename ClosureT::tuple_t tuple_t; + typedef typename ClosureT::closure_t closure_t; + + public: + + init_closure_context(ClosureT const& clos) + : frame(clos.subject(), phoenix::convert_actors(clos.init)) {} + + ~init_closure_context() {} + + template + void pre_parse(ParserT const& p, ScannerT const&) {} + + template + ResultT& post_parse(ResultT& hit, ParserT const&, ScannerT const&) + { hit.value() = frame[phoenix::tuple_index<0>()]; return hit; } + + private: + + phoenix::closure_frame frame; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // init_closure_parser class + // + /////////////////////////////////////////////////////////////////////////// + template + struct init_closure_parser + : public unary > > + { + typedef init_closure_parser self_t; + typedef unary > base_t; + typedef typename ParserT::phoenix_closure_t closure_t; + typedef typename ParserT::tuple_t tuple_t; + typedef typename phoenix::tuple_element<0, tuple_t>::type attr_t; + + template + struct result + { + typedef typename match_result::type type; + }; + + init_closure_parser(ParserT const& p, ActorTupleT const& init_) + : base_t(p), init(init_) {} + + template + typename parser_result::type + parse_main(ScannerT const& scan) const + { + return this->subject().parse_main(scan); + } + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef init_closure_context init_context_t; + typedef parser_scanner_linker scanner_t; + typedef parser_context_linker context_t; + typedef typename parser_result::type result_t; + BOOST_SPIRIT_CONTEXT_PARSE( + scan, *this, scanner_t, context_t, result_t); + } + + ActorTupleT init; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // closure class + // + /////////////////////////////////////////////////////////////////////////// + template < + typename DerivedT + , typename T0 = phoenix::nil_t + , typename T1 = phoenix::nil_t + , typename T2 = phoenix::nil_t + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 3 + , typename T3 = phoenix::nil_t + , typename T4 = phoenix::nil_t + , typename T5 = phoenix::nil_t + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 6 + , typename T6 = phoenix::nil_t + , typename T7 = phoenix::nil_t + , typename T8 = phoenix::nil_t + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 9 + , typename T9 = phoenix::nil_t + , typename T10 = phoenix::nil_t + , typename T11 = phoenix::nil_t + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 12 + , typename T12 = phoenix::nil_t + , typename T13 = phoenix::nil_t + , typename T14 = phoenix::nil_t + + #endif + #endif + #endif + #endif + > + struct closure : + public phoenix::closure< + T0, T1, T2 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 3 + , T3, T4, T5 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 6 + , T6, T7, T8 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 9 + , T9, T10, T11 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 12 + , T12, T13, T14 + #endif + #endif + #endif + #endif + > + { + typedef phoenix::closure< + T0, T1, T2 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 3 + , T3, T4, T5 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 6 + , T6, T7, T8 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 9 + , T9, T10, T11 + #if BOOST_SPIRIT_CLOSURE_LIMIT > 12 + , T12, T13, T14 + #endif + #endif + #endif + #endif + > phoenix_closure_t; + + typedef closure_context context_t; + + template + struct aux + { + DerivedT2& aux_derived() + { return *static_cast(this); } + + DerivedT2 const& aux_derived() const + { return *static_cast(this); } + + // initialization functions + template + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type + > + > + operator()(A const &a) const + { + typedef typename phoenix::as_actor::type a_t; + typedef phoenix::tuple actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a) + ) + ); + } + + template + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()(A const &a, B const &b) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef phoenix::tuple actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b) + ) + ); + } + + template + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()(A const &a, B const &b, C const &c) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef phoenix::tuple actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c) + ) + ); + } + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 3 + + template < + typename A, typename B, typename C, typename D + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f) + ) + ); + } + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 6 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i) + ) + ); + } + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 9 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i, J const &j + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef typename phoenix::as_actor::type j_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t, j_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i), + phoenix::as_actor::convert(j) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i, J const &j, + K const &k + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef typename phoenix::as_actor::type j_t; + typedef typename phoenix::as_actor::type k_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t, j_t, + k_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i), + phoenix::as_actor::convert(j), + phoenix::as_actor::convert(k) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i, J const &j, + K const &k, L const &l + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef typename phoenix::as_actor::type j_t; + typedef typename phoenix::as_actor::type k_t; + typedef typename phoenix::as_actor::type l_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t, j_t, + k_t, l_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i), + phoenix::as_actor::convert(j), + phoenix::as_actor::convert(k), + phoenix::as_actor::convert(l) + ) + ); + } + + #if BOOST_SPIRIT_CLOSURE_LIMIT > 12 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i, J const &j, + K const &k, L const &l, M const &m + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef typename phoenix::as_actor::type j_t; + typedef typename phoenix::as_actor::type k_t; + typedef typename phoenix::as_actor::type l_t; + typedef typename phoenix::as_actor::type m_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t, j_t, + k_t, l_t, m_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i), + phoenix::as_actor::convert(j), + phoenix::as_actor::convert(k), + phoenix::as_actor::convert(l), + phoenix::as_actor::convert(m) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i, J const &j, + K const &k, L const &l, M const &m, N const &n + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef typename phoenix::as_actor::type j_t; + typedef typename phoenix::as_actor::type k_t; + typedef typename phoenix::as_actor::type l_t; + typedef typename phoenix::as_actor::type m_t; + typedef typename phoenix::as_actor::type n_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t, j_t, + k_t, l_t, m_t, n_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i), + phoenix::as_actor::convert(j), + phoenix::as_actor::convert(k), + phoenix::as_actor::convert(l), + phoenix::as_actor::convert(m), + phoenix::as_actor::convert(n) + ) + ); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O + > + init_closure_parser< + DerivedT2, + phoenix::tuple< + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type, + typename phoenix::as_actor::type + > + > + operator()( + A const &a, B const &b, C const &c, D const &d, E const &e, + F const &f, G const &g, H const &h, I const &i, J const &j, + K const &k, L const &l, M const &m, N const &n, O const &o + ) const + { + typedef typename phoenix::as_actor::type a_t; + typedef typename phoenix::as_actor::type b_t; + typedef typename phoenix::as_actor::type c_t; + typedef typename phoenix::as_actor::type d_t; + typedef typename phoenix::as_actor::type e_t; + typedef typename phoenix::as_actor::type f_t; + typedef typename phoenix::as_actor::type g_t; + typedef typename phoenix::as_actor::type h_t; + typedef typename phoenix::as_actor::type i_t; + typedef typename phoenix::as_actor::type j_t; + typedef typename phoenix::as_actor::type k_t; + typedef typename phoenix::as_actor::type l_t; + typedef typename phoenix::as_actor::type m_t; + typedef typename phoenix::as_actor::type n_t; + typedef typename phoenix::as_actor::type o_t; + typedef phoenix::tuple< + a_t, b_t, c_t, d_t, e_t, f_t, g_t, h_t, i_t, j_t, + k_t, l_t, m_t, n_t, o_t + > actor_tuple_t; + + return init_closure_parser( + aux_derived(), + actor_tuple_t( + phoenix::as_actor::convert(a), + phoenix::as_actor::convert(b), + phoenix::as_actor::convert(c), + phoenix::as_actor::convert(d), + phoenix::as_actor::convert(e), + phoenix::as_actor::convert(f), + phoenix::as_actor::convert(g), + phoenix::as_actor::convert(h), + phoenix::as_actor::convert(i), + phoenix::as_actor::convert(j), + phoenix::as_actor::convert(k), + phoenix::as_actor::convert(l), + phoenix::as_actor::convert(m), + phoenix::as_actor::convert(n), + phoenix::as_actor::convert(o) + ) + ); + } + + #endif + #endif + #endif + #endif + }; + + ~closure() {} + }; + + /////////////////////////////////////////////////////////////////////////// + // + // overloads for chseq_p and str_p taking in phoenix actors + // + /////////////////////////////////////////////////////////////////////////// + template + struct container_begin + { + typedef container_begin self_t; + + template + struct result + { + typedef typename phoenix::actor_result + ::plain_type::iterator type; + }; + + container_begin(ActorT actor_) + : actor(actor_) {} + + template + typename phoenix::actor_result::type + eval(TupleT const& /*args*/) const + { return actor().begin(); } + + ActorT actor; + }; + + template + struct container_end + { + typedef container_begin self_t; + + template + struct result + { + typedef typename phoenix::actor_result + ::plain_type::iterator type; + }; + + container_end(ActorT actor_) + : actor(actor_) {} + + template + typename phoenix::actor_result::type + eval(TupleT const& /*args*/) const + { return actor().end(); } + + ActorT actor; + }; + + template + inline f_chseq< + phoenix::actor > >, + phoenix::actor > > + > + f_chseq_p(phoenix::actor const& a) + { + typedef phoenix::actor > > + container_begin_t; + typedef phoenix::actor > > + container_end_t; + typedef f_chseq result_t; + + return result_t(container_begin_t(a), container_end_t(a)); + } + + template + inline f_strlit< + phoenix::actor > >, + phoenix::actor > > + > + f_str_p(phoenix::actor const& a) + { + typedef phoenix::actor > > + container_begin_t; + typedef phoenix::actor > > + container_end_t; + typedef f_strlit result_t; + + return result_t(container_begin_t(a), container_end_t(a)); + } + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/attribute/grouping.hpp b/include/boost/spirit/attribute/grouping.hpp new file mode 100644 index 000000000..8e61b02fd --- /dev/null +++ b/include/boost/spirit/attribute/grouping.hpp @@ -0,0 +1,177 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_GROUPING_HPP +#define BOOST_SPIRIT_GROUPING_HPP + +#include + +#include "boost/phoenix/tuples.hpp" +#include "boost/phoenix/tuple_helpers.hpp" +#include "boost/phoenix/functions.hpp" + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/attribute/impl/grouping.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// grouping_result class +// +// This type computer returnes the tuple type of a grouping parser. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct grouping_result { + + typedef typename impl::tuple_result + ::template result::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// grouping_parser class +// +// The grouping parser template handles the composition of single parser +// results of a composite parser into one overall parser result, which +// can be used for accessing all the parser results from inside a single +// semantic action code attached to the grouping parser. For instance +// +// std::pair c; +// group_d[real_p >> ',' >> real_p] +// [ +// c = construct >(arg1, arg3) +// ] +// +// will parse two comma separated real numbers and assigns them after +// a successful match to the pair variable 'c'. As you can see, the +// result of the first real_p parser is accessible through the 'arg1' +// placeholder variable and the third parser result (the second real_p) +// is accessible through the 'arg3' placeholder variable. +// +// If a single parser does not return a result value (the corresponding +// match<> result contains nil_t as its value), a std::pair of iterators +// pointing to the begin and the end of the corresponding matched input +// sequence will be stored as the parser result. For instance +// +// std::string result_string; +// rule<> esc_string = *(c_escape_ch_p - '"'); +// group_d[ch_p('"') >> esc_string >> '"'] +// [ +// result_string = +// construct(first(arg2), second(arg2)); +// ] +// +// will fill the return_string variable with the C style escaped character +// string, which was embedded into the '"'. +// +/////////////////////////////////////////////////////////////////////////////// + +struct grouping_parser_gen; + +template +struct grouping_parser +: public unary > > +{ + typedef grouping_parser self_t; + typedef grouping_parser_gen parser_generator_t; + typedef unary_parser_category parser_category_t; + + typedef unary > base_t; + typedef typename ParserT::parser_category_t base_category_t; + + template + struct result + { + typedef + typename grouping_result::type + tuple_t; + + typedef phoenix::unpack_tuple attr_t; + typedef typename match_result::type type; + }; + + grouping_parser() + : base_t(ParserT()) {} + + grouping_parser(ParserT const &p) + : base_t(p) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + impl::grouped_parser p; + return p.parse(this->subject(), scan); + } +}; + +struct grouping_parser_gen { + + template + struct result { + + typedef grouping_parser type; + }; + + template + static grouping_parser + generate (parser const &p) + { + return grouping_parser(p.derived()); + } + + template + grouping_parser + operator[] (parser const &p) const + { + return grouping_parser(p.derived()); + } +}; + +const grouping_parser_gen group_d = grouping_parser_gen(); + +/////////////////////////////////////////////////////////////////////////////// +// +// first() and second() lazy access functions for accessing the .first and +// .second members of a std::pair as embedded into the grouping result tuple +// for parsers, not returning an explicit result. +// +/////////////////////////////////////////////////////////////////////////////// + +struct first_impl { + + template + struct result { typedef IteratorT type; }; + + template + IteratorT operator()(std::pair const &p) const + { return p.first; } +}; + +struct second_impl { + + template + struct result { typedef IteratorT type; }; + + template + IteratorT operator()(std::pair const &p) const + { return p.second; } +}; + +phoenix::function const first; +phoenix::function const second; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // BOOST_SPIRIT_GROUPING_HPP diff --git a/include/boost/spirit/attribute/impl/Makefile.am b/include/boost/spirit/attribute/impl/Makefile.am new file mode 100644 index 000000000..2f50e187a --- /dev/null +++ b/include/boost/spirit/attribute/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = grouping.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/attribute/impl diff --git a/include/boost/spirit/attribute/impl/grouping.ipp b/include/boost/spirit/attribute/impl/grouping.ipp new file mode 100644 index 000000000..89aaf2a04 --- /dev/null +++ b/include/boost/spirit/attribute/impl/grouping.ipp @@ -0,0 +1,320 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_GROUPING_IPP +#define BOOST_SPIRIT_GROUPING_IPP + +#include +#include "boost/spirit/core/meta/traverse.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +namespace impl +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple_result type computer +// +// This template class returns the type of a tuple containing all the +// return values of all parsers, which compose a given parser. +// +// For all parser types except binary_category_parser type parsers the +// tuple_result template returnes the return type of a given parser +// wrapped into a tuple. +// For binary_parser_category type parsers the tuple_result template +// returnes a tuple, which containes the tuple members of the left +// subparser concatinated with the tuple members of right subparser. +// +/////////////////////////////////////////////////////////////////////////////// + +template +struct tuple_result; + +template <> +struct tuple_result { + + template + struct result { + + // The type 'match_t' is the type of the match<> class returned by the + // parser under inspection. + + typedef typename parser_result::type match_t; + + // The type 'type' is the parser return type of the parser under + // inspection, converted to a corresponding tuple type. + // If the parser under inspection does not return any value, a std::pair + // containing the corresponding 'begin' and 'end' iterators pointing to + // the begin and the end of the matched input sequence is considered to + // be the parser result. + +#if defined(__BORLANDC__) && __BORLANDC__ >= 0x561 + enum { + value = ::boost::is_same::value + }; +#else + BOOST_STATIC_CONSTANT(int, + value = (::boost::is_same::value)); +#endif + + typedef result self_t; + typedef typename ScannerT::iterator_t iterator_t; + typedef typename + if_t, + std::pair, + typename match_t::attr_t + >::type + result_t; + typedef typename phoenix::make_tuple::type type; + }; +}; + +template <> +struct tuple_result { + + template + struct result { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + typedef typename tuple_result + ::template result::type subject_result_t; + + // The type 'type' is the parser return type of the subject of the + // parser under inspection + + typedef subject_result_t type; + }; +}; + +template <> +struct tuple_result { + + template + struct result { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + typedef typename tuple_result + ::template result::type subject_result_t; + + // The type 'type' is the parser return type of the subject of the + // parser under inspection + + typedef subject_result_t type; + }; +}; + +template <> +struct tuple_result { + + template + struct result { + + typedef typename ParserT::left_t left_t; + typedef typename ParserT::right_t right_t; + typedef typename left_t::parser_category_t left_category_t; + typedef typename right_t::parser_category_t right_category_t; + + typedef typename tuple_result + ::template result::type left_result_t; + typedef typename tuple_result + ::template result::type right_result_t; + + // The type 'type' is the concatenation of the two tuple types, returned + // by the left and right subparsers of the binary parser under inspection. + + typedef + typename phoenix::concat_tuples::type + type; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// grouped_parser parse helper template +// +// The grouping should be done for binary_category type parsers only. +// All other parsers are left without any change. +// +/////////////////////////////////////////////////////////////////////////////// + +template < + typename ParserT, typename ScannerT, typename GroupingT, + typename CategoryT +> +struct grouped_parser +: public parser > { + + typedef CategoryT parser_category_t; + + static typename parser_result::type + parse (ParserT const &p, ScannerT const &scan) + { + return p.parse(scan); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +template +class group_actor { + +public: + group_actor (TupleT &tuple_) : t(tuple_) {} + + template + void operator() (T const &val) const + { + t[phoenix::tuple_index()] = val; + } + + template + void operator()(IteratorT const &begin, IteratorT const &end) const + { + t[phoenix::tuple_index()] = std::pair(begin, end); + } + +private: + mutable TupleT &t; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// group_transform template +// +// The group_transform template is a metafunction, which is used during +// parser traversal of the composite parser to be grouped. It attaches an +// action parser to all leaf parsers (all plain_parser_category parsers), +// which in turn will assign the result of the leaf parser to the +// corresponding tuple member of the grouped parser result tuple. +// +/////////////////////////////////////////////////////////////////////////////// + +template +class group_transform_plain_policy { + +public: + + group_transform_plain_policy(TupleT &tuple_) : t(tuple_) {} + + template + struct plain_result { + + typedef group_actor actor_t; + typedef action type; + }; + + template + typename parser_traversal_plain_result::type + generate_plain(ParserT const &parser_, EnvT const &env) const + { + typedef group_actor actor_t; + return parser_[actor_t(t)]; + } + +private: + TupleT &t; +}; + +////////////////////////////////// +template +struct group_transform_policies +: public group_transform_plain_policy, + public unary_identity_policy, + public action_identity_policy, + public binary_identity_policy +{ + group_transform_policies(TupleT &tuple_) + : group_transform_plain_policy(tuple_) {} +}; + +////////////////////////////////// +template +struct group_transform +: public group_transform_policies, TupleT> { + + group_transform(TupleT &tuple_) + : group_transform_policies, TupleT>(tuple_) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// This template is the real workhorse behind the group_d generated parsers, +// if the parser to group is a binary parser. +// +// The main work this template does, is to attach a special actor as a +// semantic action recursivly to all leaf parsers of the original binary +// parser. This is done by the help of the post_order parser traversal +// algorithm. So during the parsing process every leaf parser calls the +// corresponding operator() functions of its respective actor, providing it +// with its parser result. +// +// The attached actors are constructed such, that they assign the parser +// result values to the corresponding member of the overall result tuple. +// +// The correct tuple member number is computed during the post_order parser +// traversal process such, that the leaf parsers are numbered from left to +// right. Such the most left leaf parser result is accessible as 'arg1' inside +// the sematic action code attached to the grouped parser, the second leaf +// parser result is accessible 'arg2' and so on. +// +// After a successful match this tuple value is feeded into the usual +// Spirit semantic action mechanics and the tuple members are available from +// inside the semantic action code attached to the grouped parser. +// +/////////////////////////////////////////////////////////////////////////////// + +template +struct grouped_parser +: public parser< + grouped_parser > +{ + typedef typename parser_result::type result_t; + typedef typename result_t::attr_t::tuple_t tuple_t; + typedef binary_parser_category parser_category_t; + typedef + grouped_parser + self_t; + + typedef typename parser_result::type embedded_result_t; + + // the resulting tuple should contain at least 2 elements + BOOST_STATIC_ASSERT(tuple_t::length >= 2); + + result_t + parse (ParserT const &p, ScannerT const &scan) const + { + typename ScannerT::iterator_t save = scan.first; + embedded_result_t hit = + post_order::traverse(group_transform(t), p).parse(scan); + + if (hit) { + return scan.create_match(hit.length(), + phoenix::unpack_tuple(t), save, scan.first); + } + return scan.no_match(); + } + +private: + mutable tuple_t t; +}; + +/////////////////////////////////////////////////////////////////////////////// +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // BOOST_SPIRIT_GROUPING_IPP diff --git a/include/boost/spirit/attribute/parametric.hpp b/include/boost/spirit/attribute/parametric.hpp new file mode 100644 index 000000000..90238d2e1 --- /dev/null +++ b/include/boost/spirit/attribute/parametric.hpp @@ -0,0 +1,142 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_PARAMETRIC_HPP +#define BOOST_SPIRIT_PARAMETRIC_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/composite/composite.hpp" +#include "boost/spirit/core/primitives/primitives.hpp" + +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // f_chlit class [ functional version of chlit ] + // + /////////////////////////////////////////////////////////////////////////// + template + struct f_chlit : public char_parser > + { + f_chlit(ChGenT chgen_) + : chgen(chgen_) {} + + template + bool test(T ch) const + { return ch == chgen(); } + + ChGenT chgen; + }; + + template + inline f_chlit + f_ch_p(ChGenT chgen) + { return f_chlit(chgen); } + + /////////////////////////////////////////////////////////////////////////// + // + // f_range class [ functional version of range ] + // + /////////////////////////////////////////////////////////////////////////// + template + struct f_range : public char_parser > + { + f_range(ChGenAT first_, ChGenBT last_) + : first(first_), last(last_) + {} + + template + bool test(T ch) const + { + BOOST_SPIRIT_ASSERT(first() <= last()); + return (ch >= first()) && (ch <= last()); + } + + ChGenAT first; + ChGenBT last; + }; + + template + inline f_range + f_range_p(ChGenAT first, ChGenBT last) + { return f_range(first, last); } + + /////////////////////////////////////////////////////////////////////////// + // + // f_chseq class [ functional version of chseq ] + // + /////////////////////////////////////////////////////////////////////////// + template + class f_chseq : public parser > + { + public: + + typedef f_chseq self_t; + + f_chseq(IterGenAT first_, IterGenBT last_) + : first(first_), last(last_) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::string_parser_parse(first(), last(), scan); + } + + private: + + IterGenAT first; + IterGenBT last; + }; + + template + inline f_chseq + f_chseq_p(IterGenAT first, IterGenBT last) + { return f_chseq(first, last); } + + /////////////////////////////////////////////////////////////////////////// + // + // f_strlit class [ functional version of strlit ] + // + /////////////////////////////////////////////////////////////////////////// + template + class f_strlit : public parser > + { + public: + + typedef f_strlit self_t; + + f_strlit(IterGenAT first, IterGenBT last) + : seq(first, last) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::contiguous_parser_parse + (seq, scan, scan); + } + + private: + + f_chseq seq; + }; + + template + inline f_strlit + f_str_p(IterGenAT first, IterGenBT last) + { return f_strlit(first, last); } + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core.hpp b/include/boost/spirit/core.hpp new file mode 100644 index 000000000..2a1e0e3f5 --- /dev/null +++ b/include/boost/spirit/core.hpp @@ -0,0 +1,65 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2001-2003 Hartmut Kaiser + Copyright (c) 2002-2003 Martin Wille + Copyright (c) 2002 Raghavendra Satish + Copyright (c) 2001 Bruce Florman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_CORE_MAIN_HPP) +#define BOOST_SPIRIT_CORE_MAIN_HPP + +#include "boost/spirit/debug.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.Core includes +// +/////////////////////////////////////////////////////////////////////////////// + +// Spirit.Core.Kernel +#include "boost/spirit/core/basics.hpp" +#include "boost/spirit/core/match.hpp" +#include "boost/spirit/core/parser.hpp" + +// Spirit.Core.Primitives +#include "boost/spirit/core/primitives/primitives.hpp" +#include "boost/spirit/core/primitives/numerics.hpp" + +// Spirit.Core.Meta +#include "boost/spirit/core/meta/fundamental.hpp" +#include "boost/spirit/core/meta/parser_traits.hpp" +#include "boost/spirit/core/meta/impl/parser_type.hpp" +#include "boost/spirit/core/meta/traverse.hpp" + +// Spirit.Core.Scanner +#include "boost/spirit/core/scanner/scanner.hpp" +#include "boost/spirit/core/scanner/skipper.hpp" + +// Spirit.Core.NonTerminal +#include "boost/spirit/core/non_terminal/subrule.hpp" +#include "boost/spirit/core/non_terminal/rule.hpp" +#include "boost/spirit/core/non_terminal/grammar.hpp" + +// Spirit.Core.Composite +#include "boost/spirit/core/composite/actions.hpp" +#include "boost/spirit/core/composite/composite.hpp" +#include "boost/spirit/core/composite/directives.hpp" +#include "boost/spirit/core/composite/operators.hpp" +#include "boost/spirit/core/composite/epsilon.hpp" + +#if defined(BOOST_SPIRIT_DEBUG) + ////////////////////////////////// + #include "boost/spirit/debug/parser_names.hpp" + +#endif // BOOST_SPIRIT_DEBUG + +#endif // BOOST_SPIRIT_CORE_MAIN_HPP + diff --git a/include/boost/spirit/core/Makefile.am b/include/boost/spirit/core/Makefile.am new file mode 100644 index 000000000..883380271 --- /dev/null +++ b/include/boost/spirit/core/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl composite meta non_terminal primitives scanner +spiritinclude_HEADERS = basics.hpp match.hpp parser.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/core diff --git a/include/boost/spirit/core/basics.hpp b/include/boost/spirit/core/basics.hpp new file mode 100644 index 000000000..768808247 --- /dev/null +++ b/include/boost/spirit/core/basics.hpp @@ -0,0 +1,69 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_BASICS_HPP) +#define BOOST_SPIRIT_BASICS_HPP + +#include +#include + +#if defined(BOOST_MSVC) || defined(BOOST_INTEL_CXX_VERSION) +#include "boost/spirit/core/impl/msvc.hpp" +#endif + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +#define BOOST_SPIRIT_TYPENAME +#else +#define BOOST_SPIRIT_TYPENAME typename +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + struct nil_t {}; + struct void_t {}; + struct default_t {}; + + template + struct int_t { BOOST_STATIC_CONSTANT(int, value = N); }; + + template + struct bool_t { BOOST_STATIC_CONSTANT(bool, value = C); }; + typedef bool_t true_t; + typedef bool_t false_t; + + /////////////////////////////////////////////////////////////////////////// + // + // if_t selects type A or B depending on the condition C. + // If C is of type true_t, A is selected, otherwise B + // + /////////////////////////////////////////////////////////////////////////// + #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct if_t + { + typedef typename impl::chooser::type chooser_t; + typedef typename chooser_t::template result::type type; + }; + + #else + template + struct if_t { typedef A type; }; + + template + struct if_t { typedef B type; }; + + #endif + +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/composite/Makefile.am b/include/boost/spirit/core/composite/Makefile.am new file mode 100644 index 000000000..f133c6e79 --- /dev/null +++ b/include/boost/spirit/core/composite/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = actions.hpp composite.hpp directives.hpp operators.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/composite diff --git a/include/boost/spirit/core/composite/actions.hpp b/include/boost/spirit/core/composite/actions.hpp new file mode 100644 index 000000000..d5c942990 --- /dev/null +++ b/include/boost/spirit/core/composite/actions.hpp @@ -0,0 +1,299 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_ACTIONS_HPP +#define BOOST_SPIRIT_ACTIONS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/composite/composite.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // action class + // + // The action class binds a parser with a user defined semantic + // action. Instances of action are never created manually. Instead, + // action objects are typically created indirectly through + // expression templates of the form: + // + // p[f] + // + // where p is a parser and f is a function or functor. The semantic + // action may be a function or a functor. When the parser is + // successful, the actor calls the scanner's action_policy policy + // (see scanner.hpp): + // + // scan.do_action(actor, attribute, first, last); + // + // passing in these information: + // + // actor: The action's function or functor + // attribute: The match (returned by the parser) object's + // attribute (see match.hpp) + // first: Iterator pointing to the start of the matching + // portion of the input + // last: Iterator pointing to one past the end of the + // matching portion of the input + // + // It is the responsibility of the scanner's action_policy policy to + // dispatch the function or functor as it sees fit. The expected + // function or functor signature depends on the parser being + // wrapped. In general, if the attribute type of the parser being + // wrapped is a nil_t, the function or functor expect the signature: + // + // void func(Iterator first, Iterator last); // functions + // + // struct ftor // functors + // { + // void func(Iterator first, Iterator last) const; + // }; + // + // where Iterator is the type of the iterator that is being used and + // first and last are the iterators pointing to the matching portion + // of the input. + // + // If the attribute type of the parser being wrapped is not a nil_t, + // the function or functor usually expect the signature: + // + // void func(T val); // functions + // + // struct ftor // functors + // { + // void func(T val) const; + // }; + // + // where T is the attribute type and val is the attribute value + // returned by the parser being wrapped. + // + /////////////////////////////////////////////////////////////////////////// + template + class action : public unary > > + { + public: + + typedef action self_t; + typedef action_parser_category parser_category_t; + typedef unary > base_t; + typedef ActionT predicate_t; + + template + struct result + { + typedef typename parser_result::type type; + }; + + action() + : base_t(ParserT()) + , actor(ActionT()) {} + + action(ParserT const& p, ActionT const& a) + : base_t(p) + , actor(a) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename ScannerT::iterator_t iterator_t; + typedef typename parser_result::type result_t; + + scan.at_end(); // allow skipper to take effect + iterator_t save = scan.first; + result_t hit = this->subject().parse(scan); + if (hit) + scan.do_action(actor, hit.value(), save, scan.first); + return hit; + } + + ActionT const& predicate() const { return actor; } + + private: + + ActionT actor; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // assign_actor class + // + // assign_actor is a predefined semantic action functor. It can be + // used to extract the result of a successful parse and assign it to + // a variable. The functor overloads two function call operators: + // operator(), one that takes in a single value argument and another + // that accepts two iterators (first and last). + // + // The constructor expects a reference to a variable. The functor is + // polymorphic and should work with any variable type as long as it + // is compatible with the requirements outlined below. + // + // 1 The single argument function call operator assigns the + // argument received to the variable. The variable is required + // to accept the statement: + // + // v = value; + // + // where v is the variable and value is the extracted result + // of the parser. + // + // 2 The other function call operator that takes in the + // first/last iterator expects the variable to accept the + // statement: + // + // v.assign(first, last); + // + // 2.a The variable has a member function assign, taking in + // the iterator pair. Any STL container that has an + // assign(first, last) member function may be used. + // + // Requirements 1 and 2 are exclusive and applies only if the + // corresponding single or double argument operator is actually + // called. + // + // Instances of assign_actor are not created directly. Instead a + // generator function: + // + // assign(T& ref) + // + // taking in a reference to a variable of arbitrary type is used to + // instantiate an assign_actor object of the proper type. + // + /////////////////////////////////////////////////////////////////////////// + template + class assign_actor + { + public: + + explicit + assign_actor(T& ref_) + : ref(ref_) {} + + template + void operator()(T2 const& val) const + { ref = val; } + + template + void operator()(IteratorT const& first, IteratorT const& last) const + { ref.assign(first, last); } + + private: + + T& ref; + }; + + ////////////////////////////////// + template + inline assign_actor const + assign(T& ref) + { + return assign_actor(ref); + } + + /////////////////////////////////////////////////////////////////////////// + // + // append_actor class + // + // append_actor is a predefined semantic action functor. It can be + // used to extract the result of a successful parse and append it to + // a variable. The functor overloads two function call operators: + // operator(), one that takes in a single value argument and another + // that accepts two iterators (first and last). + // + // The constructor expects a reference to a variable. The functor is + // polymorphic and should work with any variable type as long as it + // is compatible with the requirements outlined below. + // + // 1 The variable is assumed to be a container of some sort. An + // STL container is a perfectly valid candidate. + // + // 2 The single argument function call operator appends the + // extracted parser result and appends it to the container. + // The container is required to accept the statement: + // + // c.insert(c.end(), value) + // + // where c is the container and value is the extracted result + // of the parser. + // + // 2.a The container is required to have a member function + // end() that returns an iterator to its 'end' element. + // + // 2.b The container is required to have a member function + // insert that takes in the 'end' iterator and a value + // compatible with the container's element type. + // + // 3 The function call operator that takes in the first/last + // iterator first constructs a value from the iterator pair + // before appending the value to the container. The container + // is required to accept the statement: + // + // c.insert(c.end(), T::value_type(first, last)); + // + // where c is the container and T is the container type. In + // addition to the requirements 1 and 2 above, + // + // 3.a The container is also required to have a typedef + // value_type (the container's value type) that can be + // constructed given a first/last iterator pair. + // + // Requirement 2 is exclusive of requirement 3. Requirement 3 + // only applies if the corresponding double argument operator + // is actually called. + // + // Instances of append_actor are not created directly. Instead a + // generator function: + // + // append(T& ref) + // + // taking in a reference to a variable of arbitrary type is used to + // instantiate an append_actor object of the proper type. + // + /////////////////////////////////////////////////////////////////////////// + template + class append_actor + { + public: + + explicit + append_actor(T& ref_) + : ref(ref_) {} + + template + void operator()(T2 const& val) const + { ref.insert(ref.end(), val); } + + template + void operator()(IteratorT const& first, IteratorT const& last) const + { + typedef typename T::value_type value_type; + ref.insert(ref.end(), value_type(first, last)); + } + + private: + + T& ref; + }; + + ////////////////////////////////// + template + inline append_actor const + append(T& ref) + { + return append_actor(ref); + } + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/composite/composite.hpp b/include/boost/spirit/core/composite/composite.hpp new file mode 100644 index 000000000..2f09f9bd0 --- /dev/null +++ b/include/boost/spirit/core/composite/composite.hpp @@ -0,0 +1,151 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#define BOOST_SPIRIT_COMPOSITE_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/composite/impl/composite.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // unary class. + // + // Composite class composed of a single subject. This template class + // is parameterized by the subject type S and a base class to + // inherit from, BaseT. The unary class is meant to be a base class + // to inherit from. The inheritance structure, given the BaseT + // template parameter places the unary class in the middle of a + // linear, single parent hierarchy. For instance, given a class S + // and a base class B, a class D can derive from unary: + // + // struct D : public unary {...}; + // + // The inheritance structure is thus: + // + // B + // | + // unary (has S) + // | + // D + // + // The subject can be accessed from the derived class D as: + // this->subject(); + // + // Typically, the subject S is specified as typename S::embed_t. + // embed_t specifies how the subject is embedded in the composite + // (See parser.hpp for details). + // + /////////////////////////////////////////////////////////////////////////// + template + class unary : public impl::subject + { + typedef impl::subject base_t; + typedef typename base_t::param_t param_t; + typedef typename base_t::return_t return_t; + + public: + + typedef S subject_t; + typedef typename S::embed_t subject_embed_t; + + unary() + : base_t() {} + + unary(BaseT const& base) + : base_t(base) {} + + unary(param_t s) + : base_t(s) {} + + unary(BaseT const& base, param_t s) + : base_t(base, s) {} + + return_t + subject() const + { return base_t::get(); } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // binary class. + // + // Composite class composed of a pair (left and right). This + // template class is parameterized by the left and right subject + // types A and B and a base class to inherit from, BaseT. The binary + // class is meant to be a base class to inherit from. The + // inheritance structure, given the BaseT template parameter places + // the binary class in the middle of a linear, single parent + // hierarchy. For instance, given classes X and Y and a base class + // B, a class D can derive from binary: + // + // struct D : public binary {...}; + // + // The inheritance structure is thus: + // + // B + // | + // binary (has X and Y) + // | + // D + // + // The left and right subjects can be accessed from the derived + // class D as: this->left(); and this->right(); + // + // Typically, the pairs X and Y are specified as typename X::embed_t + // and typename Y::embed_t. embed_t specifies how the subject is + // embedded in the composite (See parser.hpp for details). + // + /////////////////////////////////////////////////////////////////////////////// + template + class binary + : public + impl::left_subject > + { + typedef + impl::left_subject > left_base_t; + typedef typename left_base_t::param_t left_param_t; + typedef typename left_base_t::return_t left_return_t; + + typedef impl::right_subject right_base_t; + typedef typename right_base_t::param_t right_param_t; + typedef typename right_base_t::return_t right_return_t; + + public: + + typedef A left_t; + typedef typename A::embed_t left_embed_t; + + typedef B right_t; + typedef typename B::embed_t right_embed_t; + + binary() + : left_base_t(right_base_t()) {} + + binary(left_param_t a, right_param_t b) + : left_base_t(right_base_t(b), a) {} + + left_return_t + left() const + { return left_base_t::left(); } + + right_return_t + right() const + { return right_base_t::right(); } + }; + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/composite/directives.hpp b/include/boost/spirit/core/composite/directives.hpp new file mode 100644 index 000000000..7a1abe7d4 --- /dev/null +++ b/include/boost/spirit/core/composite/directives.hpp @@ -0,0 +1,589 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_DIRECTIVES_HPP) +#define BOOST_SPIRIT_DIRECTIVES_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_PRIMITIVES_HPP) +#include "boost/spirit/core/primitives/primitives.hpp" +#endif + +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#include "boost/spirit/core/composite/composite.hpp" +#endif + +#if !defined(BOOST_SPIRIT_DIRECTIVES_IPP) +#include "boost/spirit/core/composite/impl/directives.ipp" +#endif + +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // no_skipper_iteration_policy class + // + /////////////////////////////////////////////////////////////////////////// + template + struct no_skipper_iteration_policy : public BaseT + { + typedef BaseT base_t; + + no_skipper_iteration_policy() + : BaseT() {} + + template + no_skipper_iteration_policy(PolicyT const& other) + : BaseT(other) {} + + template + void + skip(ScannerT const& /*scan*/) const {} + }; + + /////////////////////////////////////////////////////////////////////////// + // + // contiguous class + // + /////////////////////////////////////////////////////////////////////////// + struct lexeme_parser_gen; + + template + struct contiguous + : public unary > > + { + typedef contiguous self_t; + typedef unary_parser_category parser_category_t; + typedef lexeme_parser_gen parser_generator_t; + typedef unary > base_t; + + template + struct result + { + typedef typename parser_result::type type; + }; + + contiguous() + : base_t(ParserT()) {} + + contiguous(ParserT const& p) + : base_t(p) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::contiguous_parser_parse + (this->subject(), scan, scan); + } + }; + + struct lexeme_parser_gen + { + template + struct result { + + typedef contiguous type; + }; + + template + static contiguous + generate(parser const& subject) + { + return contiguous(subject.derived()); + } + + template + contiguous + operator[](parser const& subject) const + { + return contiguous(subject.derived()); + } + }; + + ////////////////////////////////// + const lexeme_parser_gen lexeme_d = lexeme_parser_gen(); + + /////////////////////////////////////////////////////////////////////////// + // + // inhibit_case_iteration_policy class + // + /////////////////////////////////////////////////////////////////////////// + template + struct inhibit_case_iteration_policy : public BaseT + { + typedef BaseT base_t; + + inhibit_case_iteration_policy() + : BaseT() {} + + template + inhibit_case_iteration_policy(PolicyT const& other) + : BaseT(other) {} + + template + CharT filter(CharT ch) const + { return impl::tolower_(ch); } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // inhibit_case class + // + /////////////////////////////////////////////////////////////////////////// + struct inhibit_case_parser_gen; + + template + struct inhibit_case + : public unary > > + { + typedef inhibit_case self_t; + typedef unary_parser_category parser_category_t; + typedef inhibit_case_parser_gen parser_generator_t; + typedef unary > base_t; + + template + struct result + { + typedef typename parser_result::type type; + }; + + inhibit_case() + : base_t(ParserT()) {} + + inhibit_case(ParserT const& p) + : base_t(p) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::inhibit_case_parser_parse + (this->subject(), scan, scan); + } + }; + + template + struct inhibit_case_parser_gen_base + { + // This hack is needed to make borland happy. + // If these member operators were defined in the + // inhibit_case_parser_gen class, or if this class + // is non-templated, borland ICEs. + + static inhibit_case > + generate(char const* str) + { return inhibit_case >(str); } + + static inhibit_case > + generate(wchar_t const* str) + { return inhibit_case >(str); } + + static inhibit_case > + generate(char ch) + { return inhibit_case >(ch); } + + static inhibit_case > + generate(wchar_t ch) + { return inhibit_case >(ch); } + + template + static inhibit_case + generate(parser const& subject) + { return inhibit_case(subject.derived()); } + + inhibit_case > + operator[](char const* str) const + { return inhibit_case >(str); } + + inhibit_case > + operator[](wchar_t const* str) const + { return inhibit_case >(str); } + + inhibit_case > + operator[](char ch) const + { return inhibit_case >(ch); } + + inhibit_case > + operator[](wchar_t ch) const + { return inhibit_case >(ch); } + + template + inhibit_case + operator[](parser const& subject) const + { return inhibit_case(subject.derived()); } + }; + + ////////////////////////////////// + struct inhibit_case_parser_gen : public inhibit_case_parser_gen_base<0> + { + inhibit_case_parser_gen() {} + }; + + ////////////////////////////////// + const inhibit_case_parser_gen nocase_d = inhibit_case_parser_gen(); + + /////////////////////////////////////////////////////////////////////////// + // + // longest_alternative class + // + /////////////////////////////////////////////////////////////////////////// + struct longest_parser_gen; + + template + struct longest_alternative + : public binary > > + { + typedef longest_alternative self_t; + typedef binary_parser_category parser_category_t; + typedef longest_parser_gen parser_generator_t; + typedef binary > base_t; + + longest_alternative() + : base_t(A(), B()) {} + + longest_alternative(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typename ScannerT::iterator_t save = scan.first; + result_t l = this->left().parse(scan); + std::swap(scan.first, save); + result_t r = this->right().parse(scan); + + if (l || r) + { + if (l.length() > r.length()) + { + scan.first = save; + return l; + } + return r; + } + + return scan.no_match(); + } + }; + + struct longest_parser_gen + { + template + struct result { + + typedef typename + impl::to_longest_alternative >::result_t + type; + }; + + template + static typename + impl::to_longest_alternative >::result_t + generate(alternative const& alt) + { + return impl::to_longest_alternative >:: + convert(alt); + } + + template + typename impl::to_longest_alternative >::result_t + operator[](alternative const& alt) const + { + return impl::to_longest_alternative >:: + convert(alt); + } + }; + + const longest_parser_gen longest_d = longest_parser_gen(); + + /////////////////////////////////////////////////////////////////////////// + // + // shortest_alternative class + // + /////////////////////////////////////////////////////////////////////////// + struct shortest_parser_gen; + + template + struct shortest_alternative + : public binary > > + { + typedef shortest_alternative self_t; + typedef binary_parser_category parser_category_t; + typedef shortest_parser_gen parser_generator_t; + typedef binary > base_t; + + shortest_alternative() + : base_t(A(), B()) {} + + shortest_alternative(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typename ScannerT::iterator_t save = scan.first; + result_t l = this->left().parse(scan); + std::swap(scan.first, save); + result_t r = this->right().parse(scan); + + if (l || r) + { + if (l.length() < r.length()) + { + scan.first = save; + return l; + } + return r; + } + + return scan.no_match(); + } + }; + + struct shortest_parser_gen + { + template + struct result { + + typedef typename + impl::to_shortest_alternative >::result_t + type; + }; + + template + static typename + impl::to_shortest_alternative >::result_t + generate(alternative const& alt) + { + return impl::to_shortest_alternative >:: + convert(alt); + } + + template + typename impl::to_shortest_alternative >::result_t + operator[](alternative const& alt) const + { + return impl::to_shortest_alternative >:: + convert(alt); + } + }; + + const shortest_parser_gen shortest_d = shortest_parser_gen(); + + /////////////////////////////////////////////////////////////////////////// + // + // min_bounded class + // + /////////////////////////////////////////////////////////////////////////// + template + struct min_bounded_gen; + + template + struct min_bounded + : public unary > > + { + typedef min_bounded self_t; + typedef unary_parser_category parser_category_t; + typedef min_bounded_gen parser_generator_t; + typedef unary > base_t; + + template + struct result + { + typedef typename parser_result::type type; + }; + + min_bounded() + : base_t(ParserT()) {} + + min_bounded(ParserT const& p, BoundsT const& min__) + : base_t(p) + , min_(min__) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + result_t hit = this->subject().parse(scan); + if (hit.value() < min_) + return scan.no_match(); + return hit; + } + + BoundsT min_; + }; + + template + struct min_bounded_gen + { + min_bounded_gen(BoundsT const& min__) + : min_(min__) {} + + template + min_bounded + operator[](parser const& p) const + { return min_bounded(p.derived(), min_); } + + BoundsT min_; + }; + + template + inline min_bounded_gen + min_limit_d(BoundsT const& min_) + { return min_bounded_gen(min_); } + + /////////////////////////////////////////////////////////////////////////// + // + // max_bounded class + // + /////////////////////////////////////////////////////////////////////////// + template + struct max_bounded_gen; + + template + struct max_bounded + : public unary > > + { + typedef max_bounded self_t; + typedef unary_parser_category parser_category_t; + typedef max_bounded_gen parser_generator_t; + typedef unary > base_t; + + template + struct result + { + typedef typename parser_result::type type; + }; + + max_bounded() + : base_t(ParserT()) {} + + max_bounded(ParserT const& p, BoundsT const& max__) + : base_t(p) + , max_(max__) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + result_t hit = this->subject().parse(scan); + if (hit.value() > max_) + return scan.no_match(); + return hit; + } + + BoundsT max_; + }; + + template + struct max_bounded_gen + { + max_bounded_gen(BoundsT const& max__) + : max_(max__) {} + + template + max_bounded + operator[](parser const& p) const + { return max_bounded(p.derived(), max_); } + + BoundsT max_; + }; + + ////////////////////////////////// + template + inline max_bounded_gen + max_limit_d(BoundsT const& max_) + { return max_bounded_gen(max_); } + + /////////////////////////////////////////////////////////////////////////// + // + // bounded class + // + /////////////////////////////////////////////////////////////////////////// + template + struct bounded_gen; + + template + struct bounded + : public unary > > + { + typedef bounded self_t; + typedef unary_parser_category parser_category_t; + typedef bounded_gen parser_generator_t; + typedef unary > base_t; + + template + struct result + { + typedef typename parser_result::type type; + }; + + bounded() + : base_t(ParserT()) {} + + bounded(ParserT const& p, BoundsT const& min__, BoundsT const& max__) + : base_t(p) + , min_(min__) + , max_(max__) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + result_t hit = this->subject().parse(scan); + if (hit.value() < min_ || hit.value() > max_) + return scan.no_match(); + return hit; + } + + BoundsT min_, max_; + }; + + template + struct bounded_gen + { + bounded_gen(BoundsT const& min__, BoundsT const& max__) + : min_(min__) + , max_(max__) {} + + template + bounded + operator[](parser const& p) const + { return bounded(p.derived(), min_, max_); } + + BoundsT min_, max_; + }; + + template + inline bounded_gen + limit_d(BoundsT const& min_, BoundsT const& max_) + { return bounded_gen(min_, max_); } + +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/composite/epsilon.hpp b/include/boost/spirit/core/composite/epsilon.hpp new file mode 100644 index 000000000..4df4ebaeb --- /dev/null +++ b/include/boost/spirit/core/composite/epsilon.hpp @@ -0,0 +1,279 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_EPSILON_HPP +#define BOOST_SPIRIT_EPSILON_HPP + +//////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_PARSER_TRAITS_HPP) +#include "boost/spirit/core/meta/parser_traits.hpp" +#endif + +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#include "boost/spirit/core/composite/composite.hpp" +#endif + +//////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// condition_parser class +// +// handles expresions of the form +// epsilon_p(cond) +// where cond is a function or a functor that returns a value +// suitable to be used in boolean context. The expression returns +// a parser that returns an empty match when the condition evaluates +// to true. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct condition_parser + : public impl::subject > > +{ + typedef condition_parser self_t; + typedef impl::subject > base_t; + + // not explicit! (needed for implementation of if_p et al.) + condition_parser(CondT const &cond) : base_t(cond) {} + condition_parser() : base_t() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + if (positive == this->get()()) + return scan.empty_match(); + else + return scan.no_match(); + } + + condition_parser + negate() const + { + return condition_parser(this->get()); + } + +private: +}; + +template +inline condition_parser +operator~(condition_parser const &p) +{ + return p.negate(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// empty_match_parser class +// +// handles expressions of the form +// epsilon_p(subject) +// where subject is a parser. The expresion returns a composite +// parser that returns an empty match if the subject parser matches. +// +/////////////////////////////////////////////////////////////////////////////// +struct empty_match_parser_gen; +struct negated_empty_match_parser_gen; + +template struct negated_empty_match_parser; + +template +struct empty_match_parser + : public unary > > +{ + typedef empty_match_parser self_t; + typedef unary > base_t; + typedef unary_parser_category parser_category_t; + typedef empty_match_parser_gen parser_genererator_t; + typedef self_t embed_t; + + explicit empty_match_parser(SubjectT const &p) : base_t(p) {} + empty_match_parser() : base_t() {} + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typename ScannerT::iterator_t save(scan.first); + bool matches = this->subject().parse(scan); + if (matches) + { + scan.first = save; // reset the position + return scan.empty_match(); + } + else + return scan.no_match(); + } + + negated_empty_match_parser + negate() const + { + return negated_empty_match_parser(this->subject()); + } +}; + +template +struct negated_empty_match_parser + : public unary > > +{ + typedef negated_empty_match_parser self_t; + typedef unary > base_t; + typedef unary_parser_category parser_category_t; + typedef negated_empty_match_parser_gen parser_genererator_t; + + explicit negated_empty_match_parser(SubjectT const &p) : base_t(p) {} + negated_empty_match_parser() : base_t() {} + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typename ScannerT::iterator_t save(scan.first); + + bool matches = this->subject().parse(scan); + if (!matches) + { + scan.first = save; // reset the position + return scan.empty_match(); + } + else + return scan.no_match(); + } + + empty_match_parser + negate() const + { + return empty_match_parser(this->subject()); + } +}; + +////////////////////////////// +struct empty_match_parser_gen +{ + template + struct result + { + typedef empty_match_parser type; + }; + + template + static empty_match_parser + generate(parser const &subject) + { + return empty_match_parser(subject.derived()); + } +}; + +struct negated_empty_match_parser_gen +{ + template + struct result + { + typedef negated_empty_match_parser type; + }; + + template + static negated_empty_match_parser + generate(parser const &subject) + { + return negated_empty_match_parser(subject.derived()); + } +}; + +////////////////////////////// +template +inline /*struct*/ negated_empty_match_parser +operator ~(empty_match_parser const &p) +{ + return p.negate(); +} + +template +inline /*struct*/ empty_match_parser +operator ~(negated_empty_match_parser const &p) +{ + return p.negate(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// epsilon_ parser and parser generator class +// +// Operates as primitive parser that always matches an empty sequence. +// +// Also operates as a parser generator. According to the type of the +// argument an instance of empty_match_parser<> (when the argument is +// a parser) or condition_parser<> (when the argument is not a parser) +// is returned by operator(). +// +/////////////////////////////////////////////////////////////////////////////// +namespace impl +{ + template + struct epsilon_selector + { + typedef typename as_parser::type subject_t; + typedef typename + if_t + ::value> + ,empty_match_parser + ,condition_parser + >::type type; + }; +} // namespace impl + +struct epsilon_parser : public parser +{ + typedef epsilon_parser self_t; + + epsilon_parser() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { return scan.empty_match(); } + + template + typename impl::epsilon_selector::type + operator()(SubjectT const &subject) const + { + typedef typename impl::epsilon_selector::type result_t; + return result_t(subject); + } +}; + +////////////////////////////////// +epsilon_parser const epsilon_p = epsilon_parser(); +epsilon_parser const eps_p = epsilon_parser(); + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/composite/impl/Makefile.am b/include/boost/spirit/core/composite/impl/Makefile.am new file mode 100644 index 000000000..1bce13bf2 --- /dev/null +++ b/include/boost/spirit/core/composite/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = composite.ipp directives.ipp operators.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/composite/impl diff --git a/include/boost/spirit/core/composite/impl/composite.ipp b/include/boost/spirit/core/composite/impl/composite.ipp new file mode 100644 index 000000000..7242a041a --- /dev/null +++ b/include/boost/spirit/core/composite/impl/composite.ipp @@ -0,0 +1,158 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined BOOST_SPIRIT_COMPOSITE_IPP +#define BOOST_SPIRIT_COMPOSITE_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl + { + /////////////////////////////////////////////////////////////////////// + // + // This class is used when the subject is known to be empty + // (zero size). In such a case, the subject is not stored + // as a member variable to save space. + // + /////////////////////////////////////////////////////////////////////// + template + struct empty_subject : public BaseT + { + typedef typename boost::call_traits::param_type param_t; + typedef T return_t; + + empty_subject() + : BaseT() {} + + empty_subject(BaseT const& base) + : BaseT(base) {} + + empty_subject(param_t) + : BaseT() {} + + empty_subject(BaseT const& base, param_t) + : BaseT(base) {} + + return_t get() const { return return_t(); } + }; + + /////////////////////////////////////////////////////////////////////// + // + // This class is used when the subject is known to be non-empty + // (non-zero size). In a such a case, the subject is stored + // as a member variable. + // + /////////////////////////////////////////////////////////////////////// + template + struct non_empty_subject : public BaseT + { + typedef typename boost::call_traits::param_type param_t; + typedef typename boost::call_traits::const_reference return_t; + + non_empty_subject() + : BaseT(), s() {} + + non_empty_subject(BaseT const& base) + : BaseT(base), s() {} + + non_empty_subject(param_t s_) + : BaseT(), s(s_) {} + + non_empty_subject(BaseT const& base, param_t s_) + : BaseT(base), s(s_) {} + + return_t get() const { return s; } + T s; + }; + + /////////////////////////////////////////////////////////////////////// + // + // Test T if it is empty and switch the proper implementation + // class appropriately (empty_subject or non_empty_subject) + // + /////////////////////////////////////////////////////////////////////// + template + struct subject_type + { + enum { is_empty = boost::is_empty::value }; + typedef typename if_t + < + bool_t, // IF + empty_subject, // THEN + non_empty_subject // ELSE + >::type type; + }; + + /////////////////////////////////////////////////////////////////////// + // + // subject, left_subject and right_subject classes. + // + // The three classes below are virtually similar except for the + // names. These classes are used by the public unary and binary + // classes for the unary::subject, binary::left and binary::right + // implementations. + // + /////////////////////////////////////////////////////////////////////// + template + struct subject : subject_type::type + { + typedef typename subject_type::type base_t; + typedef typename boost::call_traits::param_type param_t; + typedef typename base_t::return_t return_t; + + subject() : base_t() {} + subject(BaseT const& base) : base_t(base) {} + subject(param_t s) : base_t(s) {} + subject(BaseT const& base, param_t s) : base_t(base, s) {} + }; + + ////////////////////////////////// + template + struct left_subject : subject_type::type + { + typedef typename subject_type::type base_t; + typedef typename boost::call_traits::param_type param_t; + typedef typename base_t::return_t return_t; + + left_subject() : base_t() {} + left_subject(BaseT const& base) : base_t(base) {} + left_subject(param_t s) : base_t(s) {} + left_subject(BaseT const& base, param_t s) : base_t(base, s) {} + + return_t + left() const { return base_t::get(); } + }; + + ////////////////////////////////// + template + struct right_subject : subject_type::type + { + typedef typename subject_type::type base_t; + typedef typename boost::call_traits::param_type param_t; + typedef typename base_t::return_t return_t; + + right_subject() : base_t() {} + right_subject(BaseT const& base) : base_t(base) {} + right_subject(param_t s) : base_t(s) {} + right_subject(BaseT const& base, param_t s) : base_t(base, s) {} + + return_t + right() const { return base_t::get(); } + }; + } +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/composite/impl/directives.ipp b/include/boost/spirit/core/composite/impl/directives.ipp new file mode 100644 index 000000000..7ce8bcfcc --- /dev/null +++ b/include/boost/spirit/core/composite/impl/directives.ipp @@ -0,0 +1,374 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001 Daniel Nuffer + Copyright (c) 2001 Bruce Florman + Copyright (c) 2002 Raghavendra Satish + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_DIRECTIVES_IPP) +#define BOOST_SPIRIT_DIRECTIVES_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/scanner/skipper.hpp" + +namespace boost { namespace spirit { + + template + struct no_skipper_iteration_policy; + + template + struct inhibit_case_iteration_policy; + + template + struct alternative; + + template + struct longest_alternative; + + template + struct shortest_alternative; + + namespace impl + { + template + inline RT + contiguous_parser_parse( + ST const& s, + ScannerT const& scan, + skipper_iteration_policy const&) + { + typedef scanner_policies< + no_skipper_iteration_policy< + BOOST_SPIRIT_TYPENAME ScannerT::iteration_policy_t>, + BOOST_SPIRIT_TYPENAME ScannerT::match_policy_t, + BOOST_SPIRIT_TYPENAME ScannerT::action_policy_t + > policies_t; + + scan.skip(scan); + RT hit = s.parse(scan.change_policies(policies_t(scan))); + // We will not do a post skip!!! + return hit; + } + + template + inline RT + contiguous_parser_parse( + ST const& s, + ScannerT const& scan, + no_skipper_iteration_policy const&) + { + return s.parse(scan); + } + + template + inline RT + contiguous_parser_parse( + ST const& s, + ScannerT const& scan, + iteration_policy const&) + { + return s.parse(scan); + } + + template < + typename RT, + typename ParserT, + typename ScannerT, + typename BaseT> + inline RT + implicit_lexeme_parse( + ParserT const& p, + ScannerT const& scan, + skipper_iteration_policy const&) + { + typedef scanner_policies< + no_skipper_iteration_policy< + BOOST_SPIRIT_TYPENAME ScannerT::iteration_policy_t>, + BOOST_SPIRIT_TYPENAME ScannerT::match_policy_t, + BOOST_SPIRIT_TYPENAME ScannerT::action_policy_t + > policies_t; + + scan.skip(scan); + RT hit = p.parse_main(scan.change_policies(policies_t(scan))); + // We will not do a post skip!!! + return hit; + } + + template < + typename RT, + typename ParserT, + typename ScannerT, + typename BaseT> + inline RT + implicit_lexeme_parse( + ParserT const& p, + ScannerT const& scan, + no_skipper_iteration_policy const&) + { + return p.parse_main(scan); + } + + template + inline RT + implicit_lexeme_parse( + ParserT const& p, + ScannerT const& scan, + iteration_policy const&) + { + return p.parse_main(scan); + } + + template + inline RT + inhibit_case_parser_parse( + ST const& s, + ScannerT const& scan, + iteration_policy const&) + { + typedef scanner_policies< + inhibit_case_iteration_policy< + BOOST_SPIRIT_TYPENAME ScannerT::iteration_policy_t>, + BOOST_SPIRIT_TYPENAME ScannerT::match_policy_t, + BOOST_SPIRIT_TYPENAME ScannerT::action_policy_t + > policies_t; + + return s.parse(scan.change_policies(policies_t(scan))); + } + + template + inline RT + inhibit_case_parser_parse( + ST const& s, + ScannerT const& scan, + inhibit_case_iteration_policy const&) + { + return s.parse(scan); + } + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + /////////////////////////////////////////////////////////////////////// + // + // from spirit 1.1 (copyright (c) 2001 Bruce Florman) + // various workarounds to support longest and shortest directives + // + /////////////////////////////////////////////////////////////////////// + template + struct is_alternative + { + // Determine at compile time (without partial specialization) + // whether a given type is an instance of the alternative + + static T t(); + template + static char test_(alternative const&); // no implementation + static int test_(...); // no implementation + enum { r = sizeof(char) == sizeof(test_(t())) }; + typedef bool_t value; + }; + + template struct select_to_longest; + + template + struct to_longest_alternative + { + typedef typename select_to_longest::result_t result_t; + typedef typename select_to_longest::plain_t plain_t; + typedef typename select_to_longest::choose_t choose_t; + static result_t convert(T const& a); + }; + + template + struct to_longest_generic + { + typedef T const& result_t; + typedef T plain_t; + typedef false_t choose_t; + }; + + template + inline T const& + to_longest_convert(T const& a, false_t) + { return a; } + + template + struct to_longest_recursive + { + typedef typename to_longest_alternative< + typename T::left_t>::plain_t a_t; + typedef typename to_longest_alternative< + typename T::right_t>::plain_t b_t; + + typedef longest_alternative result_t; + + typedef result_t plain_t; + typedef true_t choose_t; + }; + + template + inline typename to_longest_alternative >::result_t + to_longest_convert(alternative const& alt, true_t) + { + typedef typename to_longest_alternative< + alternative >::result_t result_t; + return result_t( + to_longest_alternative::convert(alt.left()), + to_longest_alternative::convert(alt.right())); + } + + template + inline typename to_longest_alternative::result_t + to_longest_alternative::convert(T const& a) + { + return to_longest_convert( + a, to_longest_alternative::choose_t()); + } + + template + struct select_to_longest + { + typedef typename if_t + < + is_alternative::value // IF + , to_longest_recursive // THEN + , to_longest_generic // ELSE + >::type type; + + typedef typename select_to_longest::type::result_t result_t; + typedef typename select_to_longest::type::plain_t plain_t; + typedef typename select_to_longest::type::choose_t choose_t; + }; + + template struct select_to_shortest; + + template + struct to_shortest_alternative + { + typedef typename select_to_shortest::result_t result_t; + typedef typename select_to_shortest::plain_t plain_t; + typedef typename select_to_shortest::choose_t choose_t; + static result_t convert(T const& a); + }; + + template + struct to_shortest_generic + { + typedef T const& result_t; + typedef T plain_t; + typedef false_t choose_t; + }; + + template + inline T const& + to_shortest_convert(T const& a, false_t) { return a; } + + template + struct to_shortest_recursive + { + typedef typename to_shortest_alternative< + typename T::left_t>::plain_t a_t; + typedef typename to_shortest_alternative< + typename T::right_t>::plain_t b_t; + + typedef shortest_alternative result_t; + + typedef result_t plain_t; + typedef true_t choose_t; + }; + + template + inline typename to_shortest_alternative >::result_t + to_shortest_convert(alternative const& alt, true_t) + { + typedef typename to_shortest_alternative< + alternative >::result_t result_t; + return result_t( + to_shortest_alternative::convert(alt.left()), + to_shortest_alternative::convert(alt.right())); + } + + template + inline typename to_shortest_alternative::result_t + to_shortest_alternative::convert(T const& a) + { + return to_shortest_convert( + a, to_shortest_alternative::choose_t()); + } + + template + struct select_to_shortest + { + typedef typename if_t + < + is_alternative::value // IF + , to_shortest_recursive // THEN + , to_shortest_generic // ELSE + >::type type; + + typedef typename select_to_shortest::type::result_t result_t; + typedef typename select_to_shortest::type::plain_t plain_t; + typedef typename select_to_shortest::type::choose_t choose_t; + }; +#else + template + struct to_longest_alternative + { + typedef T result_t; + static result_t const& + convert(T const& a) // Special (end) case + { return a; } + }; + + template + struct to_longest_alternative > + { + typedef typename to_longest_alternative::result_t a_t; + typedef typename to_longest_alternative::result_t b_t; + typedef longest_alternative result_t; + + static result_t + convert(alternative const& alt) // Recursive case + { + return result_t( + to_longest_alternative::convert(alt.left()), + to_longest_alternative::convert(alt.right())); + } + }; + + template + struct to_shortest_alternative + { + typedef T result_t; + static result_t const& + convert(T const& a) // Special (end) case + { return a; } + }; + + template + struct to_shortest_alternative > + { + typedef typename to_shortest_alternative::result_t a_t; + typedef typename to_shortest_alternative::result_t b_t; + typedef shortest_alternative result_t; + + static result_t + convert(alternative const& alt) // Recursive case + { + return result_t( + to_shortest_alternative::convert(alt.left()), + to_shortest_alternative::convert(alt.right())); + } + }; +#endif + } + +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/composite/impl/operators.ipp b/include/boost/spirit/core/composite/impl/operators.ipp new file mode 100644 index 000000000..9c91141fe --- /dev/null +++ b/include/boost/spirit/core/composite/impl/operators.ipp @@ -0,0 +1,668 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_OPERATORS_IPP) +#define BOOST_SPIRIT_OPERATORS_IPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// sequence class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline sequence +operator>>(parser const& a, parser const& b) +{ + return sequence(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator>>(parser const& a, char b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator>>(char a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator>>(parser const& a, char const* b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator>>(char const* a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator>>(parser const& a, wchar_t b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator>>(wchar_t a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator>>(parser const& a, wchar_t const* b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator>>(wchar_t const* a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// sequential-and operators implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline sequence +operator&&(parser const& a, parser const& b) +{ + return sequence(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator&&(parser const& a, char b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator&&(char a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator&&(parser const& a, char const* b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator&&(char const* a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator&&(parser const& a, wchar_t b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator&&(wchar_t a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequence > +operator&&(parser const& a, wchar_t const* b) +{ + return sequence >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequence, B> +operator&&(wchar_t const* a, parser const& b) +{ + return sequence, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// sequential-or class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline sequential_or +operator||(parser const& a, parser const& b) +{ + return sequential_or(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline sequential_or > +operator||(parser const& a, char b) +{ + return sequential_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequential_or, B> +operator||(char a, parser const& b) +{ + return sequential_or, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequential_or > +operator||(parser const& a, char const* b) +{ + return sequential_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequential_or, B> +operator||(char const* a, parser const& b) +{ + return sequential_or, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequential_or > +operator||(parser const& a, wchar_t b) +{ + return sequential_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequential_or, B> +operator||(wchar_t a, parser const& b) +{ + return sequential_or, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline sequential_or > +operator||(parser const& a, wchar_t const* b) +{ + return sequential_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline sequential_or, B> +operator||(wchar_t const* a, parser const& b) +{ + return sequential_or, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// alternative class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline alternative +operator|(parser const& a, parser const& b) +{ + return alternative(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline alternative > +operator|(parser const& a, char b) +{ + return alternative >(a.derived(), b); +} + +////////////////////////////////// +template +inline alternative, B> +operator|(char a, parser const& b) +{ + return alternative, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline alternative > +operator|(parser const& a, char const* b) +{ + return alternative >(a.derived(), b); +} + +////////////////////////////////// +template +inline alternative, B> +operator|(char const* a, parser const& b) +{ + return alternative, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline alternative > +operator|(parser const& a, wchar_t b) +{ + return alternative >(a.derived(), b); +} + +////////////////////////////////// +template +inline alternative, B> +operator|(wchar_t a, parser const& b) +{ + return alternative, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline alternative > +operator|(parser const& a, wchar_t const* b) +{ + return alternative >(a.derived(), b); +} + +////////////////////////////////// +template +inline alternative, B> +operator|(wchar_t const* a, parser const& b) +{ + return alternative, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// intersection class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline intersection +operator&(parser const& a, parser const& b) +{ + return intersection(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline intersection > +operator&(parser const& a, char b) +{ + return intersection >(a.derived(), b); +} + +////////////////////////////////// +template +inline intersection, B> +operator&(char a, parser const& b) +{ + return intersection, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline intersection > +operator&(parser const& a, char const* b) +{ + return intersection >(a.derived(), b); +} + +////////////////////////////////// +template +inline intersection, B> +operator&(char const* a, parser const& b) +{ + return intersection, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline intersection > +operator&(parser const& a, wchar_t b) +{ + return intersection >(a.derived(), b); +} + +////////////////////////////////// +template +inline intersection, B> +operator&(wchar_t a, parser const& b) +{ + return intersection, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline intersection > +operator&(parser const& a, wchar_t const* b) +{ + return intersection >(a.derived(), b); +} + +////////////////////////////////// +template +inline intersection, B> +operator&(wchar_t const* a, parser const& b) +{ + return intersection, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// difference class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline difference +operator-(parser const& a, parser const& b) +{ + return difference(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline difference > +operator-(parser const& a, char b) +{ + return difference >(a.derived(), b); +} + +////////////////////////////////// +template +inline difference, B> +operator-(char a, parser const& b) +{ + return difference, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline difference > +operator-(parser const& a, char const* b) +{ + return difference >(a.derived(), b); +} + +////////////////////////////////// +template +inline difference, B> +operator-(char const* a, parser const& b) +{ + return difference, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline difference > +operator-(parser const& a, wchar_t b) +{ + return difference >(a.derived(), b); +} + +////////////////////////////////// +template +inline difference, B> +operator-(wchar_t a, parser const& b) +{ + return difference, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline difference > +operator-(parser const& a, wchar_t const* b) +{ + return difference >(a.derived(), b); +} + +////////////////////////////////// +template +inline difference, B> +operator-(wchar_t const* a, parser const& b) +{ + return difference, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// exclusive_or class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline exclusive_or +operator^(parser const& a, parser const& b) +{ + return exclusive_or(a.derived(), b.derived()); +} + +////////////////////////////////// +template +inline exclusive_or > +operator^(parser const& a, char b) +{ + return exclusive_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline exclusive_or, B> +operator^(char a, parser const& b) +{ + return exclusive_or, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline exclusive_or > +operator^(parser const& a, char const* b) +{ + return exclusive_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline exclusive_or, B> +operator^(char const* a, parser const& b) +{ + return exclusive_or, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline exclusive_or > +operator^(parser const& a, wchar_t b) +{ + return exclusive_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline exclusive_or, B> +operator^(wchar_t a, parser const& b) +{ + return exclusive_or, B>(a, b.derived()); +} + +////////////////////////////////// +template +inline exclusive_or > +operator^(parser const& a, wchar_t const* b) +{ + return exclusive_or >(a.derived(), b); +} + +////////////////////////////////// +template +inline exclusive_or, B> +operator^(wchar_t const* a, parser const& b) +{ + return exclusive_or, B>(a, b.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// optional class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +optional +operator!(parser const& a) +{ + return optional(a.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// kleene_star class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline kleene_star +operator*(parser const& a) +{ + return kleene_star(a.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// positive class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline positive +operator+(parser const& a) +{ + return positive(a.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// operator% is defined as: +// a % b ---> a >> *(b >> a) +// +/////////////////////////////////////////////////////////////////////////////// +template +inline sequence > > +operator%(parser const& a, parser const& b) +{ + return a.derived() >> *(b.derived() >> a.derived()); +} + +////////////////////////////////// +template +inline sequence, A> > > +operator%(parser const& a, char b) +{ + return a.derived() >> *(b >> a.derived()); +} + +////////////////////////////////// +template +inline sequence, kleene_star > > > +operator%(char a, parser const& b) +{ + return a >> *(b.derived() >> a); +} + +////////////////////////////////// +template +inline sequence, A> > > +operator%(parser const& a, char const* b) +{ + return a.derived() >> *(b >> a.derived()); +} + +////////////////////////////////// +template +inline sequence, + kleene_star > > > +operator%(char const* a, parser const& b) +{ + return a >> *(b.derived() >> a); +} + +////////////////////////////////// +template +inline sequence, A> > > +operator%(parser const& a, wchar_t b) +{ + return a.derived() >> *(b >> a.derived()); +} + +////////////////////////////////// +template +inline sequence, kleene_star > > > +operator%(wchar_t a, parser const& b) +{ + return a >> *(b.derived() >> a); +} + +////////////////////////////////// +template +inline sequence, A> > > +operator%(parser const& a, wchar_t const* b) +{ + return a.derived() >> *(b >> a.derived()); +} + +////////////////////////////////// +template +inline sequence, + kleene_star > > > +operator%(wchar_t const* a, parser const& b) +{ + return a >> *(b.derived() >> a); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/composite/operators.hpp b/include/boost/spirit/core/composite/operators.hpp new file mode 100644 index 000000000..9ea9ab58d --- /dev/null +++ b/include/boost/spirit/core/composite/operators.hpp @@ -0,0 +1,1090 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_OPERATORS_HPP) +#define BOOST_SPIRIT_OPERATORS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/primitives/primitives.hpp" +#include "boost/spirit/core/composite/composite.hpp" +#include "boost/spirit/core/meta/impl/parser_type.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// sequence class +// +// Handles expressions of the form: +// +// a >> b +// +// where a and b are parsers. The expression returns a composite +// parser that matches a and b in sequence. One (not both) of the +// operands may be a literal char, wchar_t or a primitive string +// char const*, wchar_t const*. +// +/////////////////////////////////////////////////////////////////////////////// +struct sequence_parser_gen; + +template +struct sequence : public binary > > +{ + typedef sequence self_t; + typedef binary_parser_category parser_category_t; + typedef sequence_parser_gen parser_generator_t; + typedef binary > base_t; + + sequence() + : base_t(A(), B()) {} + sequence(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + if (result_t ma = this->left().parse(scan)) + if (result_t mb = this->right().parse(scan)) + { + scan.concat_match(ma, mb); + return ma; + } + return scan.no_match(); + } +}; + +////////////////////////////////// +struct sequence_parser_gen +{ + template + struct result { + + typedef + sequence::type, typename as_parser::type> + type; + }; + + template + static sequence::type, typename as_parser::type> + generate(A const& a, B const& b) + { + return sequence::type, + BOOST_SPIRIT_TYPENAME as_parser::type> + (as_parser::convert(a), as_parser::convert(b)); + } +}; + +////////////////////////////////// +template +sequence +operator>>(parser const& a, parser const& b); + +////////////////////////////////// +template +sequence > +operator>>(parser const& a, char b); + +////////////////////////////////// +template +sequence, B> +operator>>(char a, parser const& b); + +////////////////////////////////// +template +sequence > +operator>>(parser const& a, char const* b); + +////////////////////////////////// +template +sequence, B> +operator>>(char const* a, parser const& b); + +////////////////////////////////// +template +sequence > +operator>>(parser const& a, wchar_t b); + +////////////////////////////////// +template +sequence, B> +operator>>(wchar_t a, parser const& b); + +////////////////////////////////// +template +sequence > +operator>>(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +sequence, B> +operator>>(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// sequential-and operators +// +// Handles expressions of the form: +// +// a && b +// +// Same as a >> b. +// +/////////////////////////////////////////////////////////////////////////////// +template +sequence +operator&&(parser const& a, parser const& b); + +////////////////////////////////// +template +sequence > +operator&&(parser const& a, char b); + +////////////////////////////////// +template +sequence, B> +operator&&(char a, parser const& b); + +////////////////////////////////// +template +sequence > +operator&&(parser const& a, char const* b); + +////////////////////////////////// +template +sequence, B> +operator&&(char const* a, parser const& b); + +////////////////////////////////// +template +sequence > +operator&&(parser const& a, wchar_t b); + +////////////////////////////////// +template +sequence, B> +operator&&(wchar_t a, parser const& b); + +////////////////////////////////// +template +sequence > +operator&&(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +sequence, B> +operator&&(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// sequential-or class +// +// Handles expressions of the form: +// +// a || b +// +// Equivalent to +// +// a | b | a >> b; +// +// where a and b are parsers. The expression returns a composite +// parser that matches matches a or b in sequence. One (not both) of +// the operands may be a literal char, wchar_t or a primitive string +// char const*, wchar_t const*. +// +/////////////////////////////////////////////////////////////////////////////// +struct sequential_or_parser_gen; + +template +struct sequential_or : public binary > > +{ + typedef sequential_or self_t; + typedef binary_parser_category parser_category_t; + typedef sequential_or_parser_gen parser_generator_t; + typedef binary > base_t; + + sequential_or() + : base_t(A(), B()) {} + sequential_or(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + { // scope for save + iterator_t save = scan.first; + if (result_t ma = this->left().parse(scan)) + { + save = scan.first; + if (result_t mb = this->right().parse(scan)) + { + // matched a b + scan.concat_match(ma, mb); + return ma; + } + else + { + // matched a + scan.first = save; + return ma; + } + } + scan.first = save; + } + + // matched b + return this->right().parse(scan); + } +}; + +////////////////////////////////// +struct sequential_or_parser_gen +{ + template + struct result { + + typedef sequential_or< + typename as_parser::type, typename as_parser::type + > type; + }; + + template + static sequential_or + < + typename as_parser::type, + typename as_parser::type + > + generate(A const& a, B const& b) + { + return sequential_or::type, + BOOST_SPIRIT_TYPENAME as_parser::type> + (as_parser::convert(a), as_parser::convert(b)); + } +}; + +////////////////////////////////// +template +sequential_or +operator||(parser const& a, parser const& b); + +////////////////////////////////// +template +sequential_or > +operator||(parser const& a, char b); + +////////////////////////////////// +template +sequential_or, B> +operator||(char a, parser const& b); + +////////////////////////////////// +template +sequential_or > +operator||(parser const& a, char const* b); + +////////////////////////////////// +template +sequential_or, B> +operator||(char const* a, parser const& b); +////////////////////////////////// +template +sequential_or > +operator||(parser const& a, wchar_t b); + +////////////////////////////////// +template +sequential_or, B> +operator||(wchar_t a, parser const& b); + +////////////////////////////////// +template +sequential_or > +operator||(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +sequential_or, B> +operator||(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// alternative class +// +// Handles expressions of the form: +// +// a | b +// +// where a and b are parsers. The expression returns a composite +// parser that matches a or b. One (not both) of the operands may +// be a literal char, wchar_t or a primitive string char const*, +// wchar_t const*. +// +// The expression is short circuit evaluated. b is never touched +// when a is returns a successful match. +// +/////////////////////////////////////////////////////////////////////////////// +struct alternative_parser_gen; + +template +struct alternative +: public binary > > +{ + typedef alternative self_t; + typedef binary_parser_category parser_category_t; + typedef alternative_parser_gen parser_generator_t; + typedef binary > base_t; + + alternative() + : base_t(A(), B()) {} + alternative(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + { // scope for save + iterator_t save = scan.first; + if (result_t hit = this->left().parse(scan)) + return hit; + scan.first = save; + } + return this->right().parse(scan); + } +}; + +////////////////////////////////// +struct alternative_parser_gen +{ + template + struct result { + + typedef alternative< + typename as_parser::type, typename as_parser::type + > type; + }; + + template + static alternative + < + typename as_parser::type, + typename as_parser::type + > + generate(A const& a, B const& b) + { + return alternative::type, + BOOST_SPIRIT_TYPENAME as_parser::type> + (as_parser::convert(a), as_parser::convert(b)); + } +}; + +////////////////////////////////// +template +alternative +operator|(parser const& a, parser const& b); + +////////////////////////////////// +template +alternative > +operator|(parser const& a, char b); + +////////////////////////////////// +template +alternative, B> +operator|(char a, parser const& b); + +////////////////////////////////// +template +alternative > +operator|(parser const& a, char const* b); + +////////////////////////////////// +template +alternative, B> +operator|(char const* a, parser const& b); + +////////////////////////////////// +template +alternative > +operator|(parser const& a, wchar_t b); + +////////////////////////////////// +template +alternative, B> +operator|(wchar_t a, parser const& b); + +////////////////////////////////// +template +alternative > +operator|(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +alternative, B> +operator|(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// intersection class +// +// Handles expressions of the form: +// +// a & b +// +// where a and b are parsers. The expression returns a composite +// parser that matches a and b. One (not both) of the operands may +// be a literal char, wchar_t or a primitive string char const*, +// wchar_t const*. +// +// The expression is short circuit evaluated. b is never touched +// when a is returns a no-match. +// +/////////////////////////////////////////////////////////////////////////////// +struct intersection_parser_gen; + +template +struct intersection +: public binary > > +{ + typedef intersection self_t; + typedef binary_parser_category parser_category_t; + typedef intersection_parser_gen parser_generator_t; + typedef binary > base_t; + + intersection() + : base_t(A(), B()) {} + intersection(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + if (result_t hl = this->left().parse(scan)) + { + ScannerT bscan(scan.first, scan.first); + scan.first = save; + result_t hr = this->right().parse(bscan); + if (hl.length() == hr.length()) + return hl; + } + + return scan.no_match(); + } +}; + +////////////////////////////////// +struct intersection_parser_gen +{ + template + struct result { + + typedef intersection< + typename as_parser::type, typename as_parser::type + > type; + }; + + template + static intersection + < + typename as_parser::type, + typename as_parser::type + > + generate(A const& a, B const& b) + { + return intersection::type, + BOOST_SPIRIT_TYPENAME as_parser::type> + (as_parser::convert(a), as_parser::convert(b)); + } +}; + +////////////////////////////////// +template +intersection +operator&(parser const& a, parser const& b); + +////////////////////////////////// +template +intersection > +operator&(parser const& a, char b); + +////////////////////////////////// +template +intersection, B> +operator&(char a, parser const& b); + +////////////////////////////////// +template +intersection > +operator&(parser const& a, char const* b); + +////////////////////////////////// +template +intersection, B> +operator&(char const* a, parser const& b); + +////////////////////////////////// +template +intersection > +operator&(parser const& a, wchar_t b); + +////////////////////////////////// +template +intersection, B> +operator&(wchar_t a, parser const& b); + +////////////////////////////////// +template +intersection > +operator&(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +intersection, B> +operator&(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// difference: a - b; Matches a but not b +// +// Handles expressions of the form: +// +// a - b +// +// where a and b are parsers. The expression returns a composite +// parser that matches a but not b. One (not both) of the operands +// may be a literal char, wchar_t or a primitive string char const*, +// wchar_t const*. +// +/////////////////////////////////////////////////////////////////////////////// +struct difference_parser_gen; + +template +struct difference +: public binary > > +{ + typedef difference self_t; + typedef binary_parser_category parser_category_t; + typedef difference_parser_gen parser_generator_t; + typedef binary > base_t; + + difference() + : base_t(A(), B()) {} + difference(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + if (result_t hl = this->left().parse(scan)) + { + std::swap(save, scan.first); + result_t hr = this->right().parse(scan); + if (!hr || (hr.length() < hl.length())) + { + scan.first = save; + return hl; + } + } + + return scan.no_match(); + } +}; + +////////////////////////////////// +struct difference_parser_gen +{ + template + struct result { + + typedef difference< + typename as_parser::type, typename as_parser::type + > type; + }; + + template + static difference + < + typename as_parser::type, + typename as_parser::type + > + generate(A const& a, B const& b) + { + return difference::type, + BOOST_SPIRIT_TYPENAME as_parser::type> + (as_parser::convert(a), as_parser::convert(b)); + } +}; + +////////////////////////////////// +template +difference +operator-(parser const& a, parser const& b); + +////////////////////////////////// +template +difference > +operator-(parser const& a, char b); + +////////////////////////////////// +template +difference, B> +operator-(char a, parser const& b); + +////////////////////////////////// +template +difference > +operator-(parser const& a, char const* b); + +////////////////////////////////// +template +difference, B> +operator-(char const* a, parser const& b); + +////////////////////////////////// +template +difference > +operator-(parser const& a, wchar_t b); + +////////////////////////////////// +template +difference, B> +operator-(wchar_t a, parser const& b); + +////////////////////////////////// +template +difference > +operator-(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +difference, B> +operator-(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// exclusive_or class +// +// Handles expressions of the form: +// +// a ^ b +// +// where a and b are parsers. The expression returns a composite +// parser that matches a or b but not both. One (not both) of the +// operands may be a literal char, wchar_t or a primitive string +// char const*, wchar_t const*. +// +/////////////////////////////////////////////////////////////////////////////// +struct exclusive_or_parser_gen; + +template +struct exclusive_or +: public binary > > +{ + typedef exclusive_or self_t; + typedef binary_parser_category parser_category_t; + typedef exclusive_or_parser_gen parser_generator_t; + typedef binary > base_t; + + exclusive_or() + : base_t(A(), B()) {} + exclusive_or(A const& a, B const& b) + : base_t(a, b) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + + iterator_t save = scan.first; + result_t l = this->left().parse(scan); + std::swap(save, scan.first); + result_t r = this->right().parse(scan); + + if (bool(l) ^ bool(r)) + { + if (l) + scan.first = save; + return bool(l) ? l : r; + } + + return scan.no_match(); + } +}; + +////////////////////////////////// +struct exclusive_or_parser_gen +{ + template + struct result { + + typedef exclusive_or< + typename as_parser::type, typename as_parser::type + > type; + }; + + template + static exclusive_or + < + typename as_parser::type, + typename as_parser::type + > + generate(A const& a, B const& b) + { + return exclusive_or::type, + BOOST_SPIRIT_TYPENAME as_parser::type> + (as_parser::convert(a), as_parser::convert(b)); + } +}; + +////////////////////////////////// +template +exclusive_or +operator^(parser const& a, parser const& b); + +////////////////////////////////// +template +exclusive_or > +operator^(parser const& a, char b); + +////////////////////////////////// +template +exclusive_or, B> +operator^(char a, parser const& b); + +////////////////////////////////// +template +exclusive_or > +operator^(parser const& a, char const* b); + +////////////////////////////////// +template +exclusive_or, B> +operator^(char const* a, parser const& b); + +////////////////////////////////// +template +exclusive_or > +operator^(parser const& a, wchar_t b); + +////////////////////////////////// +template +exclusive_or, B> +operator^(wchar_t a, parser const& b); + +////////////////////////////////// +template +exclusive_or > +operator^(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +exclusive_or, B> +operator^(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +// +// optional class +// +// Handles expressions of the form: +// +// !a +// +// where a is a parser. The expression returns a composite +// parser that matches its subject zero (0) or one (1) time. +// +/////////////////////////////////////////////////////////////////////////////// +struct optional_parser_gen; + +template +struct optional +: public unary > > +{ + typedef optional self_t; + typedef unary_parser_category parser_category_t; + typedef optional_parser_gen parser_generator_t; + typedef unary > base_t; + + optional() + : base_t(S()) {} + optional(S const& a) + : base_t(a) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + if (result_t r = this->subject().parse(scan)) + { + return r; + } + else + { + scan.first = save; + return scan.empty_match(); + } + } +}; + +////////////////////////////////// +struct optional_parser_gen +{ + template + struct result { + + typedef optional type; + }; + + template + static optional + generate(parser const& a) + { + return optional(a.derived()); + } +}; + +////////////////////////////////// +template +optional +operator!(parser const& a); + +/////////////////////////////////////////////////////////////////////////////// +// +// kleene_star class +// +// Handles expressions of the form: +// +// *a +// +// where a is a parser. The expression returns a composite +// parser that matches its subject zero (0) or more times. +// +/////////////////////////////////////////////////////////////////////////////// +struct kleene_star_parser_gen; + +template +struct kleene_star +: public unary > > +{ + typedef kleene_star self_t; + typedef unary_parser_category parser_category_t; + typedef kleene_star_parser_gen parser_generator_t; + typedef unary > base_t; + + kleene_star() + : base_t(S()) {} + kleene_star(S const& a) + : base_t(a) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + result_t hit = scan.empty_match(); + + for (;;) + { + iterator_t save = scan.first; + if (result_t next = this->subject().parse(scan)) + { + scan.concat_match(hit, next); + } + else + { + scan.first = save; + return hit; + } + } + } +}; + +////////////////////////////////// +struct kleene_star_parser_gen +{ + template + struct result { + + typedef kleene_star type; + }; + + template + static kleene_star + generate(parser const& a) + { + return kleene_star(a.derived()); + } +}; + +////////////////////////////////// +template +kleene_star +operator*(parser const& a); + +/////////////////////////////////////////////////////////////////////////////// +// +// positive class +// +// Handles expressions of the form: +// +// +a +// +// where a is a parser. The expression returns a composite +// parser that matches its subject one (1) or more times. +// +/////////////////////////////////////////////////////////////////////////////// +struct positive_parser_gen; + +template +struct positive +: public unary > > +{ + typedef positive self_t; + typedef unary_parser_category parser_category_t; + typedef positive_parser_gen parser_generator_t; + typedef unary > base_t; + + positive() + : base_t(S()) {} + positive(S const& a) + : base_t(a) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + result_t hit = this->subject().parse(scan); + + if (hit) + { + for (;;) + { + iterator_t save = scan.first; + if (result_t next = this->subject().parse(scan)) + { + scan.concat_match(hit, next); + } + else + { + scan.first = save; + break; + } + } + } + return hit; + } +}; + +////////////////////////////////// +struct positive_parser_gen +{ + template + struct result { + + typedef positive type; + }; + + template + static positive + generate(parser const& a) + { + return positive(a.derived()); + } +}; + +////////////////////////////////// +template +inline positive +operator + (parser const& a); + +/////////////////////////////////////////////////////////////////////////////// +// +// operator% is defined as: +// a % b ---> a >> *(b >> a) +// +/////////////////////////////////////////////////////////////////////////////// +template +sequence > > +operator%(parser const& a, parser const& b); + +////////////////////////////////// +template +sequence, A> > > +operator%(parser const& a, char b); + +////////////////////////////////// +template +sequence, kleene_star > > > +operator%(char a, parser const& b); + +////////////////////////////////// +template +sequence, A> > > +operator%(parser const& a, char const* b); + +////////////////////////////////// +template +sequence, + kleene_star > > > +operator%(char const* a, parser const& b); + +////////////////////////////////// +template +sequence, A> > > +operator%(parser const& a, wchar_t b); + +////////////////////////////////// +template +sequence, kleene_star > > > +operator%(wchar_t a, parser const& b); + +////////////////////////////////// +template +sequence, A> > > +operator%(parser const& a, wchar_t const* b); + +////////////////////////////////// +template +sequence, + kleene_star > > > +operator%(wchar_t const* a, parser const& b); + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif + +#include "boost/spirit/core/composite/impl/operators.ipp" diff --git a/include/boost/spirit/core/impl/Makefile.am b/include/boost/spirit/core/impl/Makefile.am new file mode 100644 index 000000000..b029b73be --- /dev/null +++ b/include/boost/spirit/core/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = basics.ipp match.ipp msvc.hpp parser.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/impl diff --git a/include/boost/spirit/core/impl/basics.ipp b/include/boost/spirit/core/impl/basics.ipp new file mode 100644 index 000000000..1cd674fb8 --- /dev/null +++ b/include/boost/spirit/core/impl/basics.ipp @@ -0,0 +1,51 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined BOOST_SPIRIT_BASICS_IPP +#define BOOST_SPIRIT_BASICS_IPP + +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +namespace boost { namespace spirit { + +////////////////////////////////// +template +struct bool_t; +typedef bool_t false_t; + + namespace impl + { + ////////////////////////////////// + struct chooser0 + { + template + struct result { typedef A type; }; + }; + + ////////////////////////////////// + struct chooser1 + { + template + struct result { typedef B type; }; + }; + + ////////////////////////////////// + template struct chooser + { typedef chooser0 type; }; + + template <> struct chooser + { typedef chooser1 type; }; + } + +}} // namespace boost::spirit + +#endif +#endif + diff --git a/include/boost/spirit/core/impl/match.ipp b/include/boost/spirit/core/impl/match.ipp new file mode 100644 index 000000000..c5c1eae2a --- /dev/null +++ b/include/boost/spirit/core/impl/match.ipp @@ -0,0 +1,180 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_MATCH_IPP) +#define BOOST_SPIRIT_MATCH_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + template + class match; + + namespace impl + { + /////////////////////////////////////////////////////////////////////// + // + // Assignment of the match result + // + // Implementation note: This assignment is wrapped by a + // template to allow its specialization for other types + // elsewhere. + // + /////////////////////////////////////////////////////////////////////// + template + struct convert + { + template + static T + to_result(T1 const &t) { return T(t); } + }; + + #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + struct match_attr_helper1 // T is not a boost::reference_wrapper + { + template + struct apply + { + template + static T get(MatchT const& m) + { return T(m.value()); } + + static T get(match const&) + { return T(); } + + static T get_default() + { return T(); } + }; + }; + + struct match_attr_helper2 // T is a boost::reference_wrapper + { + template + struct apply + { + template + static T get(MatchT const& m) + { + return convert + ::template to_result(m.value()); + } + + static T get(match const&) + { + typedef typename T::type plain_type; + static plain_type v; + return T(v); + } + + static T get_default() + { + typedef typename T::type plain_type; + static plain_type v; + return T(v); + } + }; + }; + + template + struct match_attr + { + typedef if_t< + bool_t::value>, // IF + match_attr_helper2, // THEN + match_attr_helper1 // ELSE + >::type select_t; + + template + static T get(MatchT const& m) + { return select_t::template apply::get(m); } + + static T get(match const& m) + { return select_t::template apply::get(m); } + + static T get_default() + { return select_t::template apply::get_default(); } + }; + + #else // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct match_attr + { + template + static T get(MatchT const& m) + { + return convert + ::template to_result(m.value()); + } + + static T get(match const&) + { return T(); } + + static T get_default() + { return T(); } + }; + + template + struct match_attr > + { + template + static boost::reference_wrapper + get(MatchT const& m) + { return boost::reference_wrapper(m.value()); } + + static boost::reference_wrapper + get(match const&) + { + static T v; + return boost::reference_wrapper(v); + } + + static boost::reference_wrapper + get_default() + { + static T v; + return boost::reference_wrapper(v); + } + }; + + #endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template <> + struct match_attr + { + template + static nil_t get(MatchT const&) + { return nil_t(); } + static nil_t get_default() + { return nil_t(); } + }; + + + #if !defined(__BORLANDC__) + struct dummy { void nonnull() {}; }; + typedef void (dummy::*safe_bool)(); + #else + typedef bool safe_bool; + #endif + + #if !defined(__BORLANDC__) + #define BOOST_SPIRIT_SAFE_BOOL(cond) ((cond) ? &impl::dummy::nonnull : 0) + #else + #define BOOST_SPIRIT_SAFE_BOOL(cond) (cond) + #endif + +}}} // namespace boost::spirit::impl + +#endif + diff --git a/include/boost/spirit/core/impl/msvc.hpp b/include/boost/spirit/core/impl/msvc.hpp new file mode 100644 index 000000000..ce0e0e3eb --- /dev/null +++ b/include/boost/spirit/core/impl/msvc.hpp @@ -0,0 +1,211 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002 Raghavendra Satish + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_MSVC_HPP +#define BOOST_SPIRIT_MSVC_HPP + +#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)) \ + || (defined(BOOST_INTEL_CXX_VERSION) && !defined(_STLPORT_VERSION)) +#include + +namespace boost { namespace spirit { namespace impl { + + #if !defined(BOOST_INTEL_CXX_VERSION) + + ////////////////////////////////// + template< typename T > + struct msvc_never_true + { enum { value = false }; }; + + // warning: not a well-formed C++ + // workaround for MSVC 6.5's "dependent template typedef bug" + // workaround by Aleksey Gurtovoy (from boost::mpl library) + + ////////////////////////////////// + #define BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER(name, templ) \ + namespace impl \ + { \ + template \ + struct name \ + { \ + template struct f_ : F {}; \ + \ + template <> struct f_ \ + { \ + template \ + struct templ { typedef P param_t; }; \ + }; \ + \ + template struct result_ \ + : f_::value>::template templ \ + { \ + typedef f_::value>:: \ + template templ param_t; \ + }; \ + }; \ + } \ + + #define BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER2(name, templ) \ + namespace impl \ + { \ + template \ + struct name \ + { \ + template struct f_ : F {}; \ + \ + template <> struct f_ \ + { \ + template \ + struct templ { typedef T1 param_t; }; \ + }; \ + \ + template struct result_ \ + : f_::value>::template templ \ + { \ + typedef f_::value>:: \ + template templ param_t; \ + }; \ + }; \ + } \ + + #define BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER3(name, templ) \ + namespace impl \ + { \ + template \ + struct name \ + { \ + template struct f_ : F {}; \ + \ + template <> struct f_ \ + { \ + template \ + struct templ { typedef T1 param_t; }; \ + }; \ + \ + template struct result_ \ + : f_::value>::template templ \ + { \ + typedef f_::value>:: \ + template templ param_t; \ + }; \ + }; \ + } \ + + #define BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER4(name, templ) \ + namespace impl \ + { \ + template \ + struct name \ + { \ + template struct f_ : F {}; \ + \ + template <> struct f_ \ + { \ + template < \ + typename T1, typename T2, typename T3, typename T4> \ + struct templ { typedef T1 param_t; }; \ + }; \ + \ + template \ + struct result_ \ + : f_::value>::template templ \ + { \ + typedef f_::value>:: \ + template templ param_t; \ + }; \ + }; \ + } \ + +#endif + /////////////////////////////////////////////////////////////////////// + // + // Iterator traits require partial specialization. The VC++ + // iterator_traits class in "utility" does not define pointer + // or reference types. The "difference_type" is called the + // distance_type to enure conformity we define an iterator + // traits class inside spirit namespace. The user will have to + // SPECIALIZE this iterator type if they use iterators + // + /////////////////////////////////////////////////////////////////////// + + template + struct iterator_traits + { + typedef typename IterT::difference_type difference_type; + typedef typename IterT::value_type value_type; + typedef typename IterT::pointer pointer; + typedef typename IterT::reference reference; + typedef typename IterT::iterator_category iterator_category; + }; + + //commonly used iterator_traits + template<> + struct iterator_traits + { + typedef std::random_access_iterator_tag iterator_category; + typedef char value_type; + typedef ptrdiff_t difference_type; + typedef const char* pointer; + typedef const char& reference; + }; + + template<> + struct iterator_traits + { + typedef std::random_access_iterator_tag iterator_category; + typedef char value_type; + typedef ptrdiff_t difference_type; + typedef char* pointer; + typedef char& reference; + }; + + template<> + struct iterator_traits + { + typedef std::random_access_iterator_tag iterator_category; + typedef wchar_t value_type; + typedef ptrdiff_t difference_type; + typedef const wchar_t* pointer; + typedef const wchar_t& reference; + }; + + template<> + struct iterator_traits + { + typedef std::random_access_iterator_tag iterator_category; + typedef wchar_t value_type; + typedef ptrdiff_t difference_type; + typedef wchar_t* pointer; + typedef wchar_t& reference; + }; + + // the istream_iterator of VC++6.0 doesn't have the appropriate + // traits classes defined. For supporting multi-pass + + template<> + struct iterator_traits< +#if defined (_STLPORT_VERSION) + std::istream_iterator > +#else + std::istream_iterator > > +#endif + { + typedef std::forward_iterator_tag iterator_category; + typedef char* pointer; + typedef char& reference; + typedef char value_type; + typedef ptrdiff_t difference_type; + }; + +}}} // namespace boost::spirit::impl + +#endif +#endif diff --git a/include/boost/spirit/core/impl/parser.ipp b/include/boost/spirit/core/impl/parser.ipp new file mode 100644 index 000000000..c0702243d --- /dev/null +++ b/include/boost/spirit/core/impl/parser.ipp @@ -0,0 +1,56 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_IPP) +#define BOOST_SPIRIT_PARSER_IPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // Generic parse function implementation + // + /////////////////////////////////////////////////////////////////////////// + template + inline parse_info + parse( + IteratorT const& first_, + IteratorT const& last, + parser const& p) + { + IteratorT first = first_; + scanner > scan(first, last); + match hit = p.derived().parse(scan); + return parse_info( + first, hit, hit && (first == last), hit.length()); + } + + /////////////////////////////////////////////////////////////////////////// + // + // Parse function for null terminated strings implementation + // + /////////////////////////////////////////////////////////////////////////// + template + inline parse_info + parse( + CharT const* str, + parser const& p) + { + CharT const* last = str; + while (*last) + last++; + return parse(str, last, p); + } + +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/match.hpp b/include/boost/spirit/core/match.hpp new file mode 100644 index 000000000..a95344db5 --- /dev/null +++ b/include/boost/spirit/core/match.hpp @@ -0,0 +1,162 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_MATCH_HPP) +#define BOOST_SPIRIT_MATCH_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/call_traits.hpp" + +#if !defined(BOOST_SPIRIT_BASICS_HPP) +#include "boost/spirit/core/basics.hpp" +#endif + +#if !defined(BOOST_SPIRIT_MATCH_IPP) +#include "boost/spirit/core/impl/match.ipp" +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // match class + // + // The match holds the result of a parser. A match object evaluates + // to true when a succesful match is found, otherwise false. The + // length of the match is the number of characters (or tokens) that + // is successfully matched. This can be queried through its length() + // member function. A negative value means that the match is + // unsucessful. + // + // Each parser may have an associated attribute. This attribute is + // also returned back to the client on a successful parse through + // the match object. The match's value() member function returns a + // reference to this value. + // + /////////////////////////////////////////////////////////////////////////// + template + class match + { + public: + + typedef T attr_t; + typedef typename boost::call_traits::param_type param_type; + typedef typename boost::call_traits::reference reference; + typedef typename boost::call_traits::const_reference const_reference; + + match() + : len(-1), val(impl::match_attr::get_default()) {} + + explicit + match(unsigned length) + : len(length), val((impl::match_attr::get_default())) {} + + match(unsigned length, param_type val_) + : len(length), val(val_) {} + + operator impl::safe_bool() const + { return BOOST_SPIRIT_SAFE_BOOL(len >= 0); } + + bool operator!() const + { return len < 0; } + + int length() const { return len; } + const_reference value() const { return val; } + reference value() { return val; } + + template + match(match const& other) + : len(other.length()), val(impl::match_attr::get(other)) {} + + template + match& + operator=(match const& other) + { + len = other.length(); + val = impl::match_attr::get(other); + return *this; + } + + template + void + concat(MatchT const& other) + { + BOOST_SPIRIT_ASSERT(*this && other); + len += other.length(); + } + + private: + + int len; + T val; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // match class specialization for nil_t values + // + /////////////////////////////////////////////////////////////////////////// + template <> + class match + { + + public: + + typedef nil_t attr_t; + + match() + : len(-1) {} + + explicit + match(unsigned length) + : len(length) {} + + match(unsigned length, nil_t) + : len(length) {} + + operator impl::safe_bool() const + { return BOOST_SPIRIT_SAFE_BOOL(len >= 0); } + + bool operator!() const + { return len < 0; } + + int length() const { return len; } + nil_t value() const { return nil_t(); } + + template + match(match const& other) + : len(other.length()) {} + + template + match<>& + operator=(match const& other) + { + len = other.length(); + return *this; + } + + template + void + concat(match const& other) + { + BOOST_SPIRIT_ASSERT(*this && other); + len += other.length(); + } + + private: + + int len; + }; + +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/meta/Makefile.am b/include/boost/spirit/core/meta/Makefile.am new file mode 100644 index 000000000..b35a5a5b7 --- /dev/null +++ b/include/boost/spirit/core/meta/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = fundamental.hpp parser_traits.hpp traverse.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/meta diff --git a/include/boost/spirit/core/meta/fundamental.hpp b/include/boost/spirit/core/meta/fundamental.hpp new file mode 100644 index 000000000..33760f54c --- /dev/null +++ b/include/boost/spirit/core/meta/fundamental.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_FUNDAMENTAL_HPP) +#define BOOST_SPIRIT_FUNDAMENTAL_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/meta/impl/fundamental.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// Helper template for counting the number of nodes contained in a +// given parser type. +// All parser_category type parsers are counted as nodes. +// +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +template +struct node_count { + + typedef typename ParserT::parser_category_t parser_category_t; + typedef impl::nodes nodes_t; + + typedef typename impl::count_wrapper + ::template result_ > count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value); +}; + +#else + +template +struct node_count { + + typedef typename ParserT::parser_category_t parser_category_t; + typedef typename impl::nodes + ::template count > count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value); +}; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// Helper template for counting the number of leaf nodes contained in a +// given parser type. +// Only plain_parser_category type parsers are counted as leaf nodes. +// +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +template +struct leaf_count { + + typedef typename ParserT::parser_category_t parser_category_t; + typedef impl::leafs nodes_t; + + typedef typename impl::count_wrapper + ::template result_ > count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value); +}; + +#else + +template +struct leaf_count { + + typedef typename ParserT::parser_category_t parser_category_t; + typedef typename impl::leafs + ::template count > count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value); +}; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // !defined(BOOST_SPIRIT_FUNDAMENTAL_HPP) diff --git a/include/boost/spirit/core/meta/impl/Makefile.am b/include/boost/spirit/core/meta/impl/Makefile.am new file mode 100644 index 000000000..ce8c2de90 --- /dev/null +++ b/include/boost/spirit/core/meta/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = fundamental.ipp parser_traits.ipp parser_type.hpp traverse.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/meta/impl diff --git a/include/boost/spirit/core/meta/impl/fundamental.ipp b/include/boost/spirit/core/meta/impl/fundamental.ipp new file mode 100644 index 000000000..3575d787f --- /dev/null +++ b/include/boost/spirit/core/meta/impl/fundamental.ipp @@ -0,0 +1,306 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_FUNDAMENTAL_IPP) +#define BOOST_SPIRIT_FUNDAMENTAL_IPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER2(count_wrapper, count); +#endif // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////// + // + // Helper template for counting the number of nodes contained in a + // given parser type. + // All parser_category type parsers are counted as nodes. + // + /////////////////////////////////////////////////////////////////////////// + template + struct nodes; + + template <> + struct nodes { + + template + struct count { + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { value = (LeafCountT::value + 1) }; + }; + }; + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + + template <> + struct nodes { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + typedef nodes nodes_t; + typedef typename count_wrapper + ::template result_ count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value + 1); + }; + }; + + template <> + struct nodes { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + typedef nodes nodes_t; + typedef typename count_wrapper + ::template result_ count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value + 1); + }; + }; + + template <> + struct nodes { + + template + struct count { + + typedef typename ParserT::left_t left_t; + typedef typename ParserT::right_t right_t; + typedef typename left_t::parser_category_t left_category_t; + typedef typename right_t::parser_category_t right_category_t; + + typedef nodes left_nodes_t; + typedef typename count_wrapper + ::template result_ left_count_t; + + typedef nodes right_nodes_t; + typedef typename count_wrapper + ::template result_ right_count_t; + + BOOST_STATIC_CONSTANT(int, + value = (left_count_t::value + right_count_t::value + 1)); + }; + }; + +#else + + template <> + struct nodes { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { value = (nodes + ::template count::value + 1) }; + }; + }; + + template <> + struct nodes { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { value = (nodes + ::template count::value + 1) }; + }; + }; + + template <> + struct nodes { + + template + struct count { + + typedef typename ParserT::left_t left_t; + typedef typename ParserT::right_t right_t; + typedef typename left_t::parser_category_t left_category_t; + typedef typename right_t::parser_category_t right_category_t; + + typedef count self_t; + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { + leftcount = (nodes + ::template count::value), + rightcount = (nodes + ::template count::value), + value = ((self_t::leftcount) + (self_t::rightcount) + 1) + }; + }; + }; + +#endif + + /////////////////////////////////////////////////////////////////////////// + // + // Helper template for counting the number of leaf nodes contained in a + // given parser type. + // Only plain_parser_category type parsers are counted as leaf nodes. + // + /////////////////////////////////////////////////////////////////////////// + template + struct leafs; + + template <> + struct leafs { + + template + struct count { + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { value = (LeafCountT::value + 1) }; + }; + }; + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + + template <> + struct leafs { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + typedef leafs nodes_t; + typedef typename count_wrapper + ::template result_ count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value); + }; + }; + + template <> + struct leafs { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + typedef leafs nodes_t; + typedef typename count_wrapper + ::template result_ count_t; + + BOOST_STATIC_CONSTANT(int, value = count_t::value); + }; + }; + + template <> + struct leafs { + + template + struct count { + + typedef typename ParserT::left_t left_t; + typedef typename ParserT::right_t right_t; + typedef typename left_t::parser_category_t left_category_t; + typedef typename right_t::parser_category_t right_category_t; + + typedef leafs left_nodes_t; + typedef typename count_wrapper + ::template result_ left_count_t; + + typedef leafs right_nodes_t; + typedef typename count_wrapper + ::template result_ right_count_t; + + BOOST_STATIC_CONSTANT(int, + value = (left_count_t::value + right_count_t::value)); + }; + }; + +#else + + template <> + struct leafs { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { value = (leafs + ::template count::value) }; + }; + }; + + template <> + struct leafs { + + template + struct count { + + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { value = (leafs + ::template count::value) }; + }; + }; + + template <> + struct leafs { + + template + struct count { + + typedef typename ParserT::left_t left_t; + typedef typename ParserT::right_t right_t; + typedef typename left_t::parser_category_t left_category_t; + typedef typename right_t::parser_category_t right_category_t; + + typedef count self_t; + + // __BORLANDC__ == 0x0561 isn't happy with BOOST_STATIC_CONSTANT + enum { + leftcount = (leafs + ::template count::value), + rightcount = (leafs + ::template count::value), + value = (self_t::leftcount + self_t::rightcount) + }; + }; + }; + +#endif + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // !defined(BOOST_SPIRIT_FUNDAMENTAL_IPP) diff --git a/include/boost/spirit/core/meta/impl/parser_traits.ipp b/include/boost/spirit/core/meta/impl/parser_traits.ipp new file mode 100644 index 000000000..70628058e --- /dev/null +++ b/include/boost/spirit/core/meta/impl/parser_traits.ipp @@ -0,0 +1,200 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_TRAITS_IPP) +#define BOOST_SPIRIT_PARSER_TRAITS_IPP + +#include "boost/spirit/core/composite/operators.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +namespace impl +{ + struct is_parser_helper + { + typedef struct { char dummy[1]; } no; + typedef struct { no dummy[2]; } yes; + + template + static yes test(parser const *); + + static no test(...); + }; + + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + /////////////////////////////////////////////////////////////////////////// + // + // from spirit 1.1 (copyright (c) 2001 Bruce Florman) + // various workarounds to support compile time decisions without partial + // template specialization whether a given type is an instance of a + // concrete parser type. + // + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + template + struct parser_type_traits + { + // Determine at compile time (without partial specialization) + // whether a given type is an instance of the alternative + + static T t(); + + typedef struct { char dummy[1]; } size1_t; + typedef struct { char dummy[2]; } size2_t; + typedef struct { char dummy[3]; } size3_t; + typedef struct { char dummy[4]; } size4_t; + typedef struct { char dummy[5]; } size5_t; + typedef struct { char dummy[6]; } size6_t; + typedef struct { char dummy[7]; } size7_t; + typedef struct { char dummy[8]; } size8_t; + typedef struct { char dummy[9]; } size9_t; + typedef struct { char dummy[10]; } size10_t; + + // the following functions need no implementation + template + static size1_t test_(alternative const&); + template + static size2_t test_(sequence const&); + template + static size3_t test_(sequential_or const&); + template + static size4_t test_(intersection const&); + template + static size5_t test_(difference const&); + template + static size6_t test_(exclusive_or const&); + template + static size7_t test_(optional const&); + template + static size8_t test_(kleene_star const&); + template + static size9_t test_(positive const&); + + static size10_t test_(...); + + BOOST_STATIC_CONSTANT(bool, + is_alternative = (sizeof(size1_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_sequence = (sizeof(size2_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_sequential_or = (sizeof(size3_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_intersection = (sizeof(size4_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_difference = (sizeof(size5_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_exclusive_or = (sizeof(size6_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_optional = (sizeof(size7_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_kleene_star = (sizeof(size8_t) == sizeof(test_(t()))) ); + BOOST_STATIC_CONSTANT(bool, + is_positive = (sizeof(size9_t) == sizeof(test_(t()))) ); + }; + +#else + + /////////////////////////////////////////////////////////////////////////// + struct parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_alternative = false); + BOOST_STATIC_CONSTANT(bool, is_sequence = false); + BOOST_STATIC_CONSTANT(bool, is_sequential_or = false); + BOOST_STATIC_CONSTANT(bool, is_intersection = false); + BOOST_STATIC_CONSTANT(bool, is_difference = false); + BOOST_STATIC_CONSTANT(bool, is_exclusive_or = false); + BOOST_STATIC_CONSTANT(bool, is_optional = false); + BOOST_STATIC_CONSTANT(bool, is_kleene_star = false); + BOOST_STATIC_CONSTANT(bool, is_positive = false); + }; + + template + struct parser_type_traits : public parser_type_traits_base { + + // no definition here, fallback for all not explicitly mentioned parser + // types + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_alternative = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_sequence = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_sequential_or = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_intersection = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_difference = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_exclusive_or = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_optional = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_kleene_star = true); + }; + + template + struct parser_type_traits > + : public parser_type_traits_base { + + BOOST_STATIC_CONSTANT(bool, is_positive = true); + }; + +#endif // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // !defined(BOOST_SPIRIT_PARSER_TRAITS_IPP) diff --git a/include/boost/spirit/core/meta/impl/parser_type.hpp b/include/boost/spirit/core/meta/impl/parser_type.hpp new file mode 100644 index 000000000..c11f62e55 --- /dev/null +++ b/include/boost/spirit/core/meta/impl/parser_type.hpp @@ -0,0 +1,197 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_TYPE_HPP) +#define BOOST_SPIRIT_PARSER_TYPE_HPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/primitives/primitives.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// +// Helper templates to derive the parser type from an auxilliary type and to +// generate an object of the required parser type given an auxilliary object. +// Supported types to convert are parsers, single characters and character +// strings. +// +/////////////////////////////////////////////////////////////////////////////// + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +/////////////////////////////////////////////////////////////////////////////// +// conformant compilers support PTS +template +struct as_parser +{ + typedef T type; + static type const& convert(type const& p) { return p; } +}; + +template<> +struct as_parser +{ + typedef chlit type; + static type convert(char ch) { return type(ch); } +}; + +template<> +struct as_parser +{ + typedef chlit type; + static type convert(wchar_t ch) { return type(ch); } +}; + +template<> +struct as_parser +{ + typedef strlit type; + static type convert(char const* str) { return type(str); } +}; + +template<> +struct as_parser +{ + typedef strlit type; + static type convert(wchar_t const* str) { return type(str); } +}; + +#ifdef __BORLANDC__ + +template<> +struct as_parser +{ + typedef strlit type; + static type convert(char* str) { return type(str); } +}; + +template<> +struct as_parser +{ + typedef strlit type; + static type convert(wchar_t* str) { return type(str); } +}; + +#endif // __BORLANDC__ + +template +struct as_parser +{ + typedef strlit type; + static type convert(char const str[N]) { return type(str); } +}; + +template +struct as_parser +{ + typedef strlit type; + static type convert(wchar_t const str[N]) { return type(str); } +}; + +#if !defined(__MWERKS__) || (__MWERKS__ > 0x2407) + +template +struct as_parser +{ + typedef strlit type; + static type convert(char const str[N]) { return type(str); } +}; + +template +struct as_parser +{ + typedef strlit type; + static type convert(wchar_t const str[N]) { return type(str); } +}; + +#endif // !defined(__MWERKS__) || (__MWERKS__ > 0x2407) + +#else // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +/////////////////////////////////////////////////////////////////////////////// +// some compilers do not support PTS + +template +struct as_parser +{ + enum + { + is_cptr = boost::is_convertible::value, + is_wcptr = boost::is_convertible::value + }; + +// helps to dispatch to the correct version of get for char[] and T + typedef + typename if_t, int_t<0>, int_t<1> >::type + selector_t; + +// return type (type) and formal argument (arg_type) of convert + typedef + typename if_t< + bool_t, char const *, + typename if_t, wchar_t const *, T>::type + >::type + arg_type; + + typedef + typename if_t< + bool_t, strlit, + typename if_t, strlit, T>::type + >::type + type; + + static as_parser::type::embed_t convert(arg_type const &t) + { return convert(t, selector_t()); } + +private: + + static as_parser::type::embed_t convert(arg_type str, int_t<0> sel) + { return type(str); } + + static as_parser::type::embed_t convert(arg_type const &p, int_t<1> sel) + { return p; } +}; + +template<> +struct as_parser +{ + typedef chlit type; + static type convert(char ch) { return type(ch); } +}; + +template<> +struct as_parser +{ + typedef chlit type; + static type convert(wchar_t ch) { return type(ch); } +}; + +template<> +struct as_parser +{ + typedef strlit type; + static type convert(char const* str) { return type(str);} +}; + +template<> +struct as_parser +{ + typedef strlit type; + static type convert(wchar_t const* str) { return type(str);} +}; + +#endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/meta/impl/traverse.ipp b/include/boost/spirit/core/meta/impl/traverse.ipp new file mode 100644 index 000000000..f98a60973 --- /dev/null +++ b/include/boost/spirit/core/meta/impl/traverse.ipp @@ -0,0 +1,553 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TRAVERSE_IPP) +#define BOOST_SPIRIT_TRAVERSE_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/meta/fundamental.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +namespace impl +{ + + template + struct traverse_post_order_return_category; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// +// Environment class for post_order_traversal +// +/////////////////////////////////////////////////////////////////////////////// + +template +struct traverse_post_order_env { + + BOOST_STATIC_CONSTANT(int, level = Level); + BOOST_STATIC_CONSTANT(int, node = Node); + BOOST_STATIC_CONSTANT(int, index = Index); + BOOST_STATIC_CONSTANT(int, lastleft = LastLeft); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// traverse_post_order_return template +// +// This template is a helper for dispatching the calculation of a parser +// type result for a traversal level to the corresponding parser_category +// based specialization. +// +/////////////////////////////////////////////////////////////////////////////// + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER3( + traverse_post_order_return_category_wrapper, result); + +template +struct traverse_post_order_return { + + typedef typename ParserT::parser_category_t parser_category_t; + typedef impl::traverse_post_order_return_category return_t; + + typedef typename impl::traverse_post_order_return_category_wrapper + ::template result_::type type; +}; + +#else + +template +struct traverse_post_order_return { + + typedef typename ParserT::parser_category_t parser_category_t; + typedef typename impl::traverse_post_order_return_category + ::template result::type type; +}; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// parser_traversal_..._result templates +// +// These are metafunctions, which calculate the resulting parser type +// for all subparsers and feed these types to the user supplied +// metafunctions to get back the resulting parser type of this traversal +// level. +// +/////////////////////////////////////////////////////////////////////////////// + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER2( + parser_traversal_plain_result_wrapper, plain_result); + +template +struct parser_traversal_plain_result { + + // actual resulting parser type + typedef typename impl::parser_traversal_plain_result_wrapper + ::template result_::type nexttype; + typedef typename impl::parser_traversal_plain_result_wrapper + ::template result_::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER3( + parser_traversal_unary_result_wrapper, unary_result); + +template +struct parser_traversal_unary_result { + + BOOST_STATIC_CONSTANT(int, inclevel = (EnvT::level+1)); + BOOST_STATIC_CONSTANT(int, decnode = (EnvT::node-1)); + + // traversal environment and parser return type for the subject parser + typedef traverse_post_order_env< + inclevel, decnode, EnvT::index, EnvT::lastleft + > + subject_env_t; + typedef typename traverse_post_order_return< + MetaT, SubjectT, subject_env_t + >::type + subject_t; + + // actual traversal environment and resulting parser type + typedef typename impl::parser_traversal_unary_result_wrapper + ::template result_::type nexttype; + typedef typename impl::parser_traversal_unary_result_wrapper + ::template result_::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER3( + parser_traversal_action_result_wrapper, action_result); + +template +struct parser_traversal_action_result { + + BOOST_STATIC_CONSTANT(int, inclevel = (EnvT::level+1)); + BOOST_STATIC_CONSTANT(int, decnode = (EnvT::node-1)); + + // traversal environment and parser return type for the subject parser + typedef traverse_post_order_env< + inclevel, decnode, EnvT::index, EnvT::lastleft + > + subject_env_t; + typedef typename traverse_post_order_return< + MetaT, SubjectT, subject_env_t + >::type + subject_t; + + // actual traversal environment and resulting parser type + typedef typename impl::parser_traversal_action_result_wrapper + ::template result_::type nexttype; + typedef typename impl::parser_traversal_action_result_wrapper + ::template result_::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER4( + parser_traversal_binary_result_wrapper, binary_result); + +template < + typename MetaT, typename ParserT, typename LeftT, + typename RightT, typename EnvT +> +struct parser_traversal_binary_result { + + BOOST_STATIC_CONSTANT(int, + thisnum = (node_count::value + EnvT::lastleft-1)); + BOOST_STATIC_CONSTANT(int, + leftnum = (node_count::value + EnvT::lastleft-1)); + BOOST_STATIC_CONSTANT(int, rightnum = (thisnum-1)); + BOOST_STATIC_CONSTANT(int, + leafnum = (leaf_count::value + EnvT::index)); + BOOST_STATIC_CONSTANT(int, inclevel = (EnvT::level+1)); + BOOST_STATIC_CONSTANT(int, lastleft = (leftnum+1)); + + // left traversal environment and resulting parser type + typedef traverse_post_order_env< + inclevel, leftnum, EnvT::index, EnvT::lastleft + > left_sub_env_t; + typedef typename traverse_post_order_return< + MetaT, LeftT, left_sub_env_t + >::type + left_t; + + // right traversal environment and resulting parser type + typedef traverse_post_order_env< + inclevel, rightnum, leafnum, lastleft + > right_sub_env_t; + typedef typename traverse_post_order_return< + MetaT, RightT, right_sub_env_t + >::type + right_t; + + // actual traversal environment and resulting parser type + typedef traverse_post_order_env< + EnvT::level, thisnum, EnvT::index, EnvT::lastleft + > return_env_t; + typedef typename impl::parser_traversal_binary_result_wrapper + ::template result_::type nexttype; + + typedef typename impl::parser_traversal_binary_result_wrapper + ::template result_::type type; +}; + +#else + +/////////////////////////////////////////////////////////////////////////////// +template +struct parser_traversal_plain_result { + + typedef typename MetaT::template plain_result::type nexttype; + typedef typename MetaT::template plain_result::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +template +struct parser_traversal_unary_result { + + // traversal environment and parser return type for the subject parser + typedef traverse_post_order_env< + (EnvT::level+1), (EnvT::node-1), (EnvT::index), (EnvT::lastleft) + > + subject_env_t; + typedef typename traverse_post_order_return< + MetaT, SubjectT, subject_env_t + >::type + subject_t; + + typedef typename MetaT + ::template unary_result::type nexttype; + typedef typename MetaT + ::template unary_result::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +template +struct parser_traversal_action_result { + + // traversal environment and parser return type for the subject parser + typedef traverse_post_order_env< + (EnvT::level+1), (EnvT::node-1), (EnvT::index), (EnvT::lastleft) + > + subject_env_t; + typedef typename traverse_post_order_return< + MetaT, SubjectT, subject_env_t + >::type + subject_t; + + typedef typename MetaT + ::template action_result::type nexttype; + typedef typename MetaT + ::template action_result::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +template < + typename MetaT, typename BinaryT, typename LeftT, + typename RightT, typename EnvT +> +struct parser_traversal_binary_result { + + BOOST_STATIC_CONSTANT(int, + thisnum = (node_count::value + EnvT::lastleft-1)); + BOOST_STATIC_CONSTANT(int, + leftnum = (node_count::value + EnvT::lastleft-1)); + BOOST_STATIC_CONSTANT(int, + leafnum = (leaf_count::value + EnvT::index)); + + typedef parser_traversal_binary_result self_t; + + // left traversal environment and resulting parser type + typedef traverse_post_order_env< + (EnvT::level+1), (self_t::leftnum), (EnvT::index), (EnvT::lastleft) + > left_sub_env_t; + typedef typename traverse_post_order_return< + MetaT, LeftT, left_sub_env_t + >::type + left_t; + + // right traversal environment and resulting parser type + typedef traverse_post_order_env< + (EnvT::level+1), (self_t::thisnum-1), (self_t::leafnum), (self_t::leftnum+1) + > right_sub_env_t; + typedef typename traverse_post_order_return< + MetaT, RightT, right_sub_env_t + >::type + right_t; + + // actual traversal environment and resulting parser type + typedef traverse_post_order_env< + (EnvT::level), (self_t::thisnum), (EnvT::index), (EnvT::lastleft) + > return_env_t; + typedef typename MetaT::template binary_result< + BinaryT, left_t, right_t, return_env_t + >::type + nexttype; + + typedef typename MetaT::template binary_result< + BinaryT, left_t, right_t, EnvT + >::type + type; +}; + +#endif // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +/////////////////////////////////////////////////////////////////////////////// +namespace impl +{ + /////////////////////////////////////////////////////////////////////////// + // + // Meta functions, which dispatch the calculation of the return type of + // of the post_order traverse function to the result template of the + // corresponding parser_category based metafunction template. + // + /////////////////////////////////////////////////////////////////////////// + + template + struct traverse_post_order_return_category; + + template <> + struct traverse_post_order_return_category { + + template + struct result { + + typedef typename parser_traversal_plain_result< + MetaT, ParserT, EnvT + >::type + type; + }; + }; + + template <> + struct traverse_post_order_return_category { + + template + struct result { + + typedef typename parser_traversal_unary_result< + MetaT, ParserT, typename ParserT::subject_t, EnvT + >::type + type; + }; + }; + + template <> + struct traverse_post_order_return_category { + + template + struct result { + + typedef typename parser_traversal_action_result< + MetaT, ParserT, typename ParserT::subject_t, EnvT + >::type + type; + }; + }; + + template <> + struct traverse_post_order_return_category { + + template + struct result { + + typedef typename parser_traversal_binary_result< + MetaT, ParserT, typename ParserT::left_t, + typename ParserT::right_t, EnvT + >::type + type; + }; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // Post-order parser traversal + // + // The following templates contain the parser_category based code for + // + // - calculating the type of the resulting parser, which is to be + // returned from a level of traversal + // - traversing down the composite parser structure, this traversal + // returnes a new parser object + // + // Both tasks are delegated to the MetaT metafunction supplied by the + // user. + // + /////////////////////////////////////////////////////////////////////////// + + template + struct traverse_post_order; + + template <> + struct traverse_post_order { + + template + struct result { + + typedef + typename parser_traversal_plain_result::type + type; + }; + + template + static + typename parser_traversal_plain_result::nexttype + generate(MetaT const &meta_, ParserT const &parser_, EnvT const &env) + { + return meta_.generate_plain(parser_, env); + } + }; + + template <> + struct traverse_post_order { + + template < + typename MetaT, typename ParserT, typename SubjectT, typename EnvT + > + struct result { + + typedef typename parser_traversal_unary_result< + MetaT, ParserT, SubjectT, EnvT + >::type + type; + }; + + template + static + typename parser_traversal_unary_result< + MetaT, ParserT, typename ParserT::subject_t, EnvT + >::nexttype + generate(MetaT const &meta_, ParserT const &unary_, EnvT const &env) + { + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + return meta_.generate_unary( + unary_, + traverse_post_order::generate(meta_, + unary_.subject(), + traverse_post_order_env< + EnvT::level+1, EnvT::node-1, EnvT::index, EnvT::lastleft + >() + ), + env + ); + } + }; + + template <> + struct traverse_post_order { + + template < + typename MetaT, typename ParserT, typename SubjectT, typename EnvT + > + struct result { + + typedef typename parser_traversal_action_result< + MetaT, ParserT, SubjectT, EnvT + >::type + type; + }; + + template + static + typename parser_traversal_action_result< + MetaT, ParserT, typename ParserT::subject_t, EnvT + >::nexttype + generate(MetaT const &meta_, ParserT const &action_, EnvT const &env) + { + typedef typename ParserT::subject_t subject_t; + typedef typename subject_t::parser_category_t subject_category_t; + + return meta_.generate_action( + action_, + traverse_post_order::generate(meta_, + action_.subject(), + traverse_post_order_env< + EnvT::level+1, EnvT::node-1, EnvT::index, EnvT::lastleft + >() + ), + env + ); + } + }; + + template <> + struct traverse_post_order { + + template < + typename MetaT, typename ParserT, typename LeftT, + typename RightT, typename EnvT + > + struct result { + + typedef typename parser_traversal_binary_result< + MetaT, ParserT, LeftT, RightT, EnvT + >::type + type; + }; + + template + static + typename parser_traversal_binary_result< + MetaT, ParserT, typename ParserT::left_t, + typename ParserT::right_t, EnvT + >::nexttype + generate(MetaT const &meta_, ParserT const &binary_, EnvT const &env) + { + typedef typename ParserT::left_t left_t; + typedef typename ParserT::right_t right_t; + typedef typename left_t::parser_category_t left_category_t; + typedef typename right_t::parser_category_t right_category_t; + + enum { + leftnum = (node_count::value + EnvT::lastleft-1), + thisnum = (node_count::value + EnvT::lastleft-1), + rightnum = (thisnum-1), + leafnum = (leaf_count::value + EnvT::index) + }; + + return meta_.generate_binary( + binary_, + traverse_post_order::generate( + meta_, binary_.left(), + traverse_post_order_env< + EnvT::level+1, leftnum, EnvT::index, EnvT::lastleft + >() + ), + traverse_post_order::generate( + meta_, binary_.right(), + traverse_post_order_env< + EnvT::level+1, rightnum, leafnum, leftnum+1 + >() + ), + traverse_post_order_env< + EnvT::level, thisnum, EnvT::index, EnvT::lastleft + >() + ); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // !defined(BOOST_SPIRIT_TRAVERSE_IPP) diff --git a/include/boost/spirit/core/meta/parser_traits.hpp b/include/boost/spirit/core/meta/parser_traits.hpp new file mode 100644 index 000000000..efaf8e907 --- /dev/null +++ b/include/boost/spirit/core/meta/parser_traits.hpp @@ -0,0 +1,318 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_TRAITS_HPP) +#define BOOST_SPIRIT_PARSER_TRAITS_HPP + +#include "boost/type_traits.hpp" +#include "boost/static_assert.hpp" + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/meta/impl/parser_traits.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// Parser traits templates +// +// Used to determine the type and several other characteristics of a given +// parser type. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// The is_parser traits template can be used to tell wether a given +// class is a parser. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct is_parser +{ + typedef CandidateT *cptr; + + BOOST_STATIC_CONSTANT(bool, value = + (sizeof(impl::is_parser_helper::test(cptr(0))) == + sizeof(impl::is_parser_helper::yes))); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The is_unary_composite traits template can be used to tell if a given +// parser is a unary parser as for instance kleene_star or optional. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct is_unary_composite { + + BOOST_STATIC_CONSTANT(bool, value = (::boost::is_convertible< + typename UnaryT::parser_category_t, unary_parser_category>::value)); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The is_acction_parser traits template can be used to tell if a given +// parser is a action parser, i.e. it is a composite consisting of a +// auxilliary parser and an attached semantic action. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct is_action_parser { + + BOOST_STATIC_CONSTANT(bool, value = (::boost::is_convertible< + typename ActionT::parser_category_t, action_parser_category>::value)); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The is_binary_composite traits template can be used to tell if a given +// parser is a binary parser as for instance sequence or difference. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct is_binary_composite { + + BOOST_STATIC_CONSTANT(bool, value = (::boost::is_convertible< + typename BinaryT::parser_category_t, binary_parser_category>::value)); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The is_composite_parser traits template can be used to tell if a given +// parser is a unary or a binary parser composite type. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct is_composite_parser { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::is_unary_composite::value || + ::boost::spirit::is_binary_composite::value)); +}; + +/////////////////////////////////////////////////////////////////////////////// +template +struct is_alternative { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_alternative)); +}; + +template +struct is_sequence { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_sequence)); +}; + +template +struct is_sequential_or { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_sequential_or)); +}; + +template +struct is_intersection { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_intersection)); +}; + +template +struct is_difference { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_difference)); +}; + +template +struct is_exclusive_or { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_exclusive_or)); +}; + +template +struct is_optional { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_optional)); +}; + +template +struct is_kleene_star { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_kleene_star)); +}; + +template +struct is_positive { + + BOOST_STATIC_CONSTANT(bool, value = ( + ::boost::spirit::impl::parser_type_traits::is_positive)); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Parser extraction templates +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// The unary_subject template can be used to return the type of the +// parser used as the subject of an unary parser. +// If the parser under inspection is not an unary type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct unary_subject { + + BOOST_STATIC_ASSERT(::boost::spirit::is_unary_composite::value); + typedef typename UnaryT::subject_t type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The get_unary_subject template function returns the parser object, which +// is used as the subject of an unary parser. +// If the parser under inspection is not an unary type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +inline typename unary_subject::type const & +get_unary_subject(UnaryT const &unary_) +{ + BOOST_STATIC_ASSERT(::boost::spirit::is_unary_composite::value); + return unary_.subject(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// The binary_left_subject and binary_right_subject templates can be used to +// return the types of the parsers used as the left and right subject of an +// binary parser. +// If the parser under inspection is not a binary type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct binary_left_subject { + + BOOST_STATIC_ASSERT(::boost::spirit::is_binary_composite::value); + typedef typename BinaryT::left_t type; +}; + +template +struct binary_right_subject { + + BOOST_STATIC_ASSERT(::boost::spirit::is_binary_composite::value); + typedef typename BinaryT::right_t type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The get_binary_left_subject and get_binary_right_subject template functions +// return the parser object, which is used as the left or right subject of a +// binary parser. +// If the parser under inspection is not a binary type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +inline typename binary_left_subject::type const & +get_binary_left_subject(BinaryT const &binary_) +{ + BOOST_STATIC_ASSERT(::boost::spirit::is_binary_composite::value); + return binary_.left(); +} + +template +inline typename binary_right_subject::type const & +get_binary_right_subject(BinaryT const &binary_) +{ + BOOST_STATIC_ASSERT(::boost::spirit::is_binary_composite::value); + return binary_.right(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// The action_subject template can be used to return the type of the +// parser used as the subject of an action parser. +// If the parser under inspection is not an action type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct action_subject { + + BOOST_STATIC_ASSERT(::boost::spirit::is_action_parser::value); + typedef typename ActionT::subject_t type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The get_action_subject template function returns the parser object, which +// is used as the subject of an action parser. +// If the parser under inspection is not an action type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +inline typename action_subject::type const & +get_action_subject(ActionT const &action_) +{ + BOOST_STATIC_ASSERT(::boost::spirit::is_action_parser::value); + return action_.subject(); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// The semantic_action template can be used to return the type of the +// attached semantic action of an action parser. +// If the parser under inspection is not an action type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct semantic_action { + + BOOST_STATIC_ASSERT(::boost::spirit::is_action_parser::value); + typedef typename ActionT::predicate_t type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// The get_semantic_action template function returns the attached semantic +// action of an action parser. +// If the parser under inspection is not an action type parser the compilation +// will fail. +// +/////////////////////////////////////////////////////////////////////////////// +template +inline typename semantic_action::type const & +get_semantic_action(ActionT const &action_) +{ + BOOST_STATIC_ASSERT(::boost::spirit::is_action_parser::value); + return action_.predicate(); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // !defined(BOOST_SPIRIT_PARSER_TRAITS_HPP) diff --git a/include/boost/spirit/core/meta/traverse.hpp b/include/boost/spirit/core/meta/traverse.hpp new file mode 100644 index 000000000..ea7d0b10a --- /dev/null +++ b/include/boost/spirit/core/meta/traverse.hpp @@ -0,0 +1,255 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_TRAVERSE_HPP) +#define BOOST_SPIRIT_TRAVERSE_HPP + +/////////////////////////////////////////////////////////////////////////////// +// traverse code isn't supported on the VC6 platform (yet) +#if (!defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)) + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/core/meta/impl/traverse.ipp" + +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// Post-order traversal of auxilliary parsers. +// +/////////////////////////////////////////////////////////////////////////////// + +struct post_order { + + // Return the parser type, which is generated as the result of the + // traverse function below. + + template + struct result { + + typedef typename traverse_post_order_return< + MetaT, ParserT, traverse_post_order_env<0, 0, 0, 0> + >::type + type; + }; + + // Traverse a given parser and refactor it with the help of the given + // MetaT metafunction template. + + template + static typename result::type + traverse(MetaT const &meta_, ParserT const &parser_) + { + typedef typename ParserT::parser_category_t parser_category_t; + return impl::traverse_post_order::generate( + meta_, parser_, traverse_post_order_env<0, 0, 0, 0>()); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Transform policies +// +// The following policy classes could be used to assemble some new +// transformation metafunction which uses identity transformations for +// some parser_category type parsers. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// transform plain parsers +template +struct plain_identity_policy { + + template + struct plain_result { + + // plain parsers should be embedded and returned correctly + typedef typename ParserT::embed_t type; +// typedef ParserT type; + }; + + template + typename parser_traversal_plain_result::type + generate_plain(ParserT const &parser_, EnvT const &env) const + { + return parser_; + } +}; + +////////////////////////////////// +// transform unary parsers +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER( + unary_identity_policy_return_wrapper, result); + +template +struct unary_identity_policy_return { + + typedef typename UnaryT::parser_generator_t parser_generator_t; + typedef typename impl::unary_identity_policy_return_wrapper + ::template result_::type type; +}; + +#else + +template +struct unary_identity_policy_return { + + typedef typename UnaryT::parser_generator_t parser_generator_t; + typedef typename parser_generator_t::template result::type type; +}; + +#endif // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +template +struct unary_identity_policy { + + template + struct unary_result { + + typedef + typename unary_identity_policy_return::type + type; + }; + + template + typename parser_traversal_unary_result< + TransformT, UnaryT, SubjectT, EnvT + >::type + generate_unary(UnaryT const &, SubjectT const &subject_, EnvT const &env) const + { + typedef typename UnaryT::parser_generator_t parser_generator_t; + return parser_generator_t::template generate(subject_); + } +}; + +////////////////////////////////// +// transform action parsers +template +struct action_identity_policy { + + template + struct action_result { + + typedef action type; + }; + + template + typename parser_traversal_action_result< + TransformT, ActionT, SubjectT, EnvT + >::type + generate_action(ActionT const &action_, SubjectT const &subject_, + EnvT const &env) const + { + return subject_[action_.predicate()]; + } +}; + +////////////////////////////////// +// transform binary parsers +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER2( + binary_identity_policy_return_wrapper, result); + +template +struct binary_identity_policy_return { + + typedef typename BinaryT::parser_generator_t parser_generator_t; + typedef + typename impl::binary_identity_policy_return_wrapper + ::template result_::type type; +}; + +#else + +template +struct binary_identity_policy_return { + + typedef typename BinaryT::parser_generator_t parser_generator_t; + typedef typename parser_generator_t + ::template result::type type; +}; + +#endif // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +template +struct binary_identity_policy { + + template + struct binary_result { + + typedef + typename binary_identity_policy_return::type + type; + }; + + template + typename parser_traversal_binary_result< + TransformT, BinaryT, LeftT, RightT, EnvT + >::type + generate_binary(BinaryT const &, LeftT const& left_, RightT const& right_, + EnvT const &env) const + { + typedef typename BinaryT::parser_generator_t parser_generator_t; + return parser_generator_t:: + template generate(left_, right_); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// transform_policies template +// +// The transform_policies template metafunction could serve as a base +// class for new metafunctions to be passed to the traverse meta template +// (see above), where only minimal parts have to be overwritten. +// +/////////////////////////////////////////////////////////////////////////////// + +template < + typename TransformT, + typename PlainPolicyT = plain_identity_policy, + typename UnaryPolicyT = unary_identity_policy, + typename ActionPolicyT = action_identity_policy, + typename BinaryPolicyT = binary_identity_policy +> +struct transform_policies : + public PlainPolicyT, + public UnaryPolicyT, + public ActionPolicyT, + public BinaryPolicyT +{ +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Identity transformation +// +// The identity_transform metafunction supplied to the traverse template +// will generate a new parser, which will be exactly identical to the +// parser given as the parameter to the traverse metafunction. I.e. the +// following conceptual 'equation' will be always true: +// +// some_parser == post_order::traverse(identity_transform(), some_parser) +// +/////////////////////////////////////////////////////////////////////////////// + +struct identity_transform : public transform_policies {}; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // (!defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)) + +#endif // !defined(BOOST_SPIRIT_TRAVERSE_HPP) diff --git a/include/boost/spirit/core/non_terminal/Makefile.am b/include/boost/spirit/core/non_terminal/Makefile.am new file mode 100644 index 000000000..e6d40a782 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = grammar.hpp parser_context.hpp parser_id.hpp rule.hpp subrule.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/non_terminal diff --git a/include/boost/spirit/core/non_terminal/grammar.hpp b/include/boost/spirit/core/non_terminal/grammar.hpp new file mode 100644 index 000000000..4fde52e35 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/grammar.hpp @@ -0,0 +1,76 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_GRAMMAR_HPP) +#define BOOST_SPIRIT_GRAMMAR_HPP + +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_SPIRIT_THREADSAFE) && defined(SPIRIT_SINGLE_GRAMMAR_INSTANCE) +#undef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE +#endif + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/non_terminal/parser_context.hpp" +#include "boost/spirit/core/non_terminal/impl/grammar.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// grammar class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct grammar + : public parser + , public ContextT::base_t + BOOST_SPIRIT_GRAMMAR_ID +{ + typedef grammar self_t; + typedef DerivedT const& embed_t; + typedef parser_context_linker context_t; + typedef typename context_t::attr_t attr_t; + + template + struct result + { + typedef typename match_result::type type; + }; + + grammar() {} + ~grammar() { impl::grammar_destruct(this); } + + template + typename parser_result::type + parse_main(ScannerT const& scan) const + { return impl::grammar_parser_parse(this, scan); } + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef parser_scanner_linker scanner_t; + BOOST_SPIRIT_CONTEXT_PARSE(scan, *this, scanner_t, context_t, result_t) + } + + BOOST_SPIRIT_GRAMMAR_STATE +}; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#undef BOOST_SPIRIT_GRAMMAR_ID +#undef BOOST_SPIRIT_GRAMMAR_ACCESS +#undef BOOST_SPIRIT_GRAMMAR_STATE +#endif + diff --git a/include/boost/spirit/core/non_terminal/impl/Makefile.am b/include/boost/spirit/core/non_terminal/impl/Makefile.am new file mode 100644 index 000000000..961fcbc83 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = grammar.ipp object_with_id.ipp rule.ipp subrule.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/non_terminal/impl diff --git a/include/boost/spirit/core/non_terminal/impl/grammar.ipp b/include/boost/spirit/core/non_terminal/impl/grammar.ipp new file mode 100644 index 000000000..d17e2c3b1 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/impl/grammar.ipp @@ -0,0 +1,301 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined BOOST_SPIRIT_GRAMMAR_IPP +#define BOOST_SPIRIT_GRAMMAR_IPP + +#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) +#include "boost/spirit/core/non_terminal/impl/object_with_id.ipp" +#include +#include +#include // for std::auto_ptr +#include +#endif + +#ifdef BOOST_SPIRIT_THREADSAFE +#include "boost/thread/tss.hpp" +#include "boost/thread/mutex.hpp" +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +template +struct grammar; + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1200) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER(grammar_definition_wrapper, definition); + +////////////////////////////////// +template +struct grammar_definition +{ + typedef typename impl::grammar_definition_wrapper + ::template result_::param_t type; +}; + +#else + +////////////////////////////////// +template +struct grammar_definition +{ + typedef typename GrammarT::template definition type; +}; + +#endif + + namespace impl + { + +#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) + struct grammar_tag {}; + + ////////////////////////////////// + template + struct grammar_helper_base + { + virtual int undefine(GrammarT *) = 0; + virtual ~grammar_helper_base() {} + }; + + ////////////////////////////////// + template + struct grammar_helper_list + { + typedef GrammarT grammar_t; + typedef grammar_helper_base helper_t; + typedef std::vector vector_t; + + grammar_helper_list() {} + grammar_helper_list(grammar_helper_list const& x) + { // Does _not_ copy the helpers member ! + } + + grammar_helper_list& operator=(grammar_helper_list const& x) + { // Does _not_ copy the helpers member ! + return *this; + } + + void push_back(helper_t *helper) + { helpers.push_back(helper); } + + void pop_back() + { helpers.pop_back(); } + + typename vector_t::size_type + size() const + { return helpers.size(); } + + typename vector_t::reverse_iterator + rbegin() + { return helpers.rbegin(); } + + typename vector_t::reverse_iterator + rend() + { return helpers.rend(); } + +#ifdef BOOST_SPIRIT_THREADSAFE + boost::mutex & mutex() + { return m; } +#endif + + private: + + vector_t helpers; +#ifdef BOOST_SPIRIT_THREADSAFE + boost::mutex m; +#endif + }; + + ////////////////////////////////// + struct grammar_extract_helper_list; + +#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) \ + && (!defined(__GNUC__) || (__GNUC__ > 2)) + + struct grammar_extract_helper_list + { + template + static grammar_helper_list& + do_(GrammarT const* g) + { + return g->helpers; + } + }; + +#endif + + ////////////////////////////////// + template + struct grammar_helper : private grammar_helper_base + { + typedef GrammarT grammar_t; + typedef ScannerT scanner_t; + typedef DerivedT derived_t; + typedef typename grammar_definition::type definition_t; + + typedef grammar_helper helper_t; + typedef boost::shared_ptr helper_ptr_t; + typedef boost::weak_ptr helper_weak_ptr_t; + + grammar_helper* + this_() { return this; } + + grammar_helper(helper_weak_ptr_t& p) + : definitions_cnt(0) + , self(this_()) + { p = self; } + + definition_t& + define(grammar_t const* grammar) + { + grammar_helper_list &helpers = +#if !defined(__GNUC__) || (__GNUC__ > 2) + grammar_extract_helper_list::do_(grammar); +#else + grammar->helpers; +#endif + typename grammar_t::object_id id = grammar->get_object_id(); + + if (definitions.size()<=id) + definitions.resize(id*3/2+1); + if (definitions[id]!=0) + return *definitions[id]; + + std::auto_ptr + result(new definition_t(grammar->derived())); + +#ifdef BOOST_SPIRIT_THREADSAFE + boost::mutex::scoped_lock(helpers.mutex()); +#endif + helpers.push_back(this); + + ++definitions_cnt; + definitions[id] = result.get(); + return *(result.release()); + } + + int + undefine(grammar_t* grammar) + { + typename grammar_t::object_id id = grammar->get_object_id(); + + if (definitions.size()<=id) + return 0; + delete definitions[id]; + definitions[id] = 0; + if (--definitions_cnt==0) + self.reset(); + return 0; + } + + private: + + std::vector definitions; + unsigned long definitions_cnt; + helper_ptr_t self; + }; + +#endif /* defined(BOOST_SPIRIT_NO_MULTIPLE_GRAMMAR_INSTANCES) */ + + ////////////////////////////////// + template + inline typename parser_result, ScannerT>::type + grammar_parser_parse( + grammar const* self, + ScannerT const &scan) + { + typedef grammar self_t; + typedef typename parser_result::type result_t; + typedef typename DerivedT::template definition definition; + +#if defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) + static definition def(self->derived()); +#else + typedef impl::grammar_helper helper_t; + typedef typename helper_t::helper_weak_ptr_t ptr_t; + +# ifdef BOOST_SPIRIT_THREADSAFE + static boost::thread_specific_ptr tld_helper; + if (!tld_helper.get()) + tld_helper.reset(new ptr_t); + ptr_t &helper = *tld_helper; +# else + static ptr_t helper; +# endif + if (!boost::make_shared(helper).get()) + new helper_t(helper); + definition &def = boost::make_shared(helper)->define(self); +#endif + return def.start().parse(scan); + } + + ////////////////////////////////// + template + inline void + grammar_destruct(GrammarT* self) + { +#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) + typedef impl::grammar_helper_base helper_base_t; + typedef grammar_helper_list helper_list_t; + typedef typename helper_list_t::vector_t::reverse_iterator iterator_t; + + helper_list_t& helpers = +# if !defined(__GNUC__) || (__GNUC__ > 2) + grammar_extract_helper_list::do_(self); +# else + self->helpers; +# endif + +# if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1200)) \ + || defined(BOOST_INTEL_CXX_VERSION) + for (iterator_t i = helpers.rbegin(); i != helpers.rend(); ++i) + (*i)->undefine(self); +# else + std::for_each(helpers.rbegin(), helpers.rend(), + std::bind2nd(std::mem_fun(&helper_base_t::undefine), self)); +# endif + +#endif + } + + } // namespace impl + +/////////////////////////////////////// +#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) +#define BOOST_SPIRIT_GRAMMAR_ID , public impl::object_with_id +#else +#define BOOST_SPIRIT_GRAMMAR_ID +#endif + +/////////////////////////////////////// +#if !defined(__GNUC__) || (__GNUC__ > 2) +#define BOOST_SPIRIT_GRAMMAR_ACCESS private: +#else +#define BOOST_SPIRIT_GRAMMAR_ACCESS +#endif + +/////////////////////////////////////// +#if !defined(BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE) +#define BOOST_SPIRIT_GRAMMAR_STATE \ + BOOST_SPIRIT_GRAMMAR_ACCESS \ + friend struct impl::grammar_extract_helper_list; \ + mutable impl::grammar_helper_list helpers; +#else +#define BOOST_SPIRIT_GRAMMAR_STATE +#endif + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/non_terminal/impl/object_with_id.ipp b/include/boost/spirit/core/non_terminal/impl/object_with_id.ipp new file mode 100644 index 000000000..19b5d005a --- /dev/null +++ b/include/boost/spirit/core/non_terminal/impl/object_with_id.ipp @@ -0,0 +1,159 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined BOOST_SPIRIT_OBJECT_WITH_ID_IPP +#define BOOST_SPIRIT_OBJECT_WITH_ID_IPP + +#include +#include + +#ifdef BOOST_SPIRIT_THREADSAFE +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl { + + ////////////////////////////////// + template + struct object_with_id_base_supply + { + typedef IdT object_id; + typedef std::vector id_vector; + + object_with_id_base_supply() : max_id(object_id()) {} + +#ifdef BOOST_SPIRIT_THREADSAFE + boost::mutex mutex; +#endif + object_id max_id; + id_vector free_ids; + + object_id acquire(); + void release(object_id); + }; + + ////////////////////////////////// + template + struct object_with_id_base + { + typedef TagT tag_t; + typedef IdT object_id; + + protected: + + object_id acquire_object_id(); + void release_object_id(object_id); + + private: + + boost::shared_ptr > id_supply; + }; + + ////////////////////////////////// + template + struct object_with_id : private object_with_id_base + { + typedef object_with_id self_t; + typedef object_with_id_base base_t; + typedef IdT object_id; + + object_with_id() : id(base_t::acquire_object_id()) {} + object_with_id(self_t const &other) + : base_t(other) + , id(base_t::acquire_object_id()) + {} // don't copy id + self_t &operator = (self_t const &other) + { // don't assign id + base_t::operator=(other); + return *this; + } + ~object_with_id() { base_t::release_object_id(id); } + object_id get_object_id() const { return id; } + + private: + + object_id const id; + }; + + ////////////////////////////////// + template + inline IdT + object_with_id_base_supply::acquire() + { +#ifdef BOOST_SPIRIT_THREADSAFE + boost::mutex::scoped_lock lock(mutex); +#endif + if (free_ids.size()) + { + object_id id = *free_ids.rbegin(); + free_ids.pop_back(); + return id; + } + else + { + if (free_ids.capacity()<=max_id) + free_ids.reserve(max_id*3/2+1); + return ++max_id; + } + } + + ////////////////////////////////// + template + inline void + object_with_id_base_supply::release(IdT id) + { +#ifdef BOOST_SPIRIT_THREADSAFE + boost::mutex::scoped_lock lock(mutex); +#endif + if (max_id == id) + max_id--; + else + free_ids.push_back(id); // doesn't throw + } + + ////////////////////////////////// + template + inline IdT + object_with_id_base::acquire_object_id() + { + { +#ifdef BOOST_SPIRIT_THREADSAFE + static boost::mutex mutex; + boost::mutex::scoped_lock lock(mutex); +#endif + static boost::shared_ptr > + static_supply; + + if (!static_supply.get()) + static_supply.reset(new object_with_id_base_supply()); + id_supply = static_supply; + } + + return id_supply->acquire(); + } + + ////////////////////////////////// + template + inline void + object_with_id_base::release_object_id(IdT id) + { + id_supply->release(id); + } + + } // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/non_terminal/impl/rule.ipp b/include/boost/spirit/core/non_terminal/impl/rule.ipp new file mode 100644 index 000000000..4ba466e66 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/impl/rule.ipp @@ -0,0 +1,101 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_RULE_IPP) +#define BOOST_SPIRIT_RULE_IPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + namespace impl + { + /////////////////////////////////////////////////////////////////////// + // + // abstract_parser class + // + /////////////////////////////////////////////////////////////////////// + template + struct abstract_parser + { + abstract_parser() {} + virtual ~abstract_parser() {} + + virtual RT + do_parse_virtual(ScannerT const& scan) const = 0; + }; + + /////////////////////////////////////////////////////////////////////// + // + // concrete_parser class + // + /////////////////////////////////////////////////////////////////////// + template + struct concrete_parser : public abstract_parser + { + concrete_parser(ParserT const& p_) : p(p_) {} + virtual ~concrete_parser() {} + + virtual RT + do_parse_virtual(ScannerT const& scan) const + { return p.parse(scan); } + + typename ParserT::embed_t p; + }; + + } // namespace impl + + ////////////////////////////////// + template + inline rule::rule() + : ptr() {} + + ////////////////////////////////// + template + inline rule::~rule() {} + + ////////////////////////////////// + template + inline typename rule::result_t + rule::parse(ScannerT const& scan) const + { + BOOST_SPIRIT_CONTEXT_PARSE(scan, *this, scanner_t, context_t, result_t) + } + + ////////////////////////////////// + template + inline typename rule::result_t + rule::parse_main(ScannerT const& scan) const + { + result_t hit; + if (ptr.get()) + { + typename ScannerT::iterator_t s(scan.first); + hit = ptr->do_parse_virtual(scan); + scan.group_match(hit, id(), s, scan.first); + } + else + { + hit = scan.no_match(); + } + return hit; + } + + ////////////////////////////////// + template + inline parser_id + rule::id() const + { + return TagT::id(*this); + } + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/non_terminal/impl/subrule.ipp b/include/boost/spirit/core/non_terminal/impl/subrule.ipp new file mode 100644 index 000000000..bdc601075 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/impl/subrule.ipp @@ -0,0 +1,208 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_SUBRULE_IPP) +#define BOOST_SPIRIT_SUBRULE_IPP + +namespace boost { namespace spirit { + + template + struct subrule_list; + + template + struct subrule_parser; + + namespace impl { + + #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template + struct get_subrule; + + template + struct get_subrule_chooser + { + static ListT t(); + static char test(nil_t); + static int test(...); + + // Set value to + // 0: ListT is empty + // 1: ListT's first item has same ID + // 2: ListT's first item has a different ID + + enum + { + id = ListT::first_t::id, + is_same_id = N == id, + is_nil_t = sizeof(char) == sizeof(test(t())), + value = is_nil_t ? 0 : (is_same_id ? 1 : 2) + }; + }; + + template + struct subrule_chooser; + + template <> + struct subrule_chooser<0> + { + // First case. ListT is empty + + template + struct result + { typedef nil_t type; }; + }; + + template <> + struct subrule_chooser<1> + { + // Second case. ListT is non-empty and the list's + // first item has the ID we are looking for. + + template + struct result + { typedef typename ListT::first_t::def_t type; }; + }; + + template <> + struct subrule_chooser<2> + { + // Third case. ListT is non-empty but the list's + // first item does not have the ID we are looking for. + + template + struct result + { typedef typename get_subrule::type type; }; + }; + + template + struct get_subrule + { + enum { n = get_subrule_chooser::value }; + typedef typename subrule_chooser::template + result::type type; + }; + + #else + + template + struct get_subrule + { + // First case. ListT is non-empty but the list's + // first item does not have the ID we are looking for. + + typedef typename get_subrule::type type; + }; + + template + struct get_subrule< + ID, + subrule_list< + subrule_parser, + RestT> > + { + // Second case. ListT is non-empty and the list's + // first item has the ID we are looking for. + + typedef DefT type; + }; + + template + struct get_subrule + { + // Third case. ListT is empty + typedef nil_t type; + }; + + #endif + + template + struct get_result_t { + + // If the result type dictated by the context is nil_t (no closures + // present), then the whole subrule_parser return type is equal to + // the return type of the right hand side of this subrule_parser, + // otherwise it is equal to the dictated return value. + + enum { is_nil_t = (boost::is_same::value) }; + typedef typename if_t< + bool_t, T2, T1 + >::type type; + }; + + template + struct get_subrule_result + { + typedef typename + impl::get_subrule::type + parser_t; + + typedef typename parser_result::type + def_result_t; + + typedef typename match_result::type + context_result_t; + + typedef typename get_result_t::type + type; + }; + + template + struct get_subrule_parser_result + { + typedef typename parser_result::type + def_result_t; + + typedef typename match_result::type + context_result_t; + + typedef typename get_result_t::type + type; + }; + + template + struct same_subrule_id + { + BOOST_STATIC_CONSTANT(bool, value = (SubruleT::id == ID)); + }; + + template + struct parse_subrule + { + template + static void + do_parse(RT& r, ScannerT const& scan, ListT const& list, true_t) + { + r = list.first.rhs.parse(scan); + } + + template + static void + do_parse(RT& r, ScannerT const& scan, ListT const& list, false_t) + { + typedef typename ListT::rest_t::first_t subrule_t; + bool_t::value> same_id; + do_parse(r, scan, list.rest, same_id); + } + + static void + do_(RT& r, ScannerT const& scan) + { + typedef typename ScannerT::list_t::first_t subrule_t; + bool_t::value> same_id; + do_parse(r, scan, scan.list, same_id); + } + }; + +}}} // namespace boost::spirit::impl + +#endif + diff --git a/include/boost/spirit/core/non_terminal/parser_context.hpp b/include/boost/spirit/core/non_terminal/parser_context.hpp new file mode 100644 index 000000000..e9b32e4dd --- /dev/null +++ b/include/boost/spirit/core/non_terminal/parser_context.hpp @@ -0,0 +1,152 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_CONTEXT_HPP) +#define BOOST_SPIRIT_PARSER_CONTEXT_HPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost +{ + namespace spirit + { + + /////////////////////////////////////////////////////////////////////////// + // + // default_parser_context_base class { default context base } + // + /////////////////////////////////////////////////////////////////////////// + struct default_parser_context_base + { + template + struct aux {}; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // parser_context class { default context } + // + /////////////////////////////////////////////////////////////////////////// + struct nil_t; + struct parser_context + { + typedef nil_t attr_t; + typedef default_parser_context_base base_t; + + template + parser_context(ParserT const&) {} + + template + void + pre_parse(ParserT const&, ScannerT const&) {} + + template + ResultT& + post_parse(ResultT& hit, ParserT const&, ScannerT const&) + { return hit; } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // context_aux class + // + // context_aux is a class derived from the + // ContextT's nested base_t::base template class. (see + // default_parser_context_base::aux for an example). + // + // Basically, this class provides ContextT dependent optional + // functionality to the derived class DerivedT through the CRTP + // idiom (Curiously recurring template pattern). + // + /////////////////////////////////////////////////////////////////////////// + #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER(context_base_wrapper, aux); + + ////////////////////////////////// + template + ::template result_ > + struct context_aux : public AuxT {}; + + #else + + template + struct context_aux : public ContextT::base_t::template aux {}; + + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // parser_scanner_linker and parser_scanner_linker classes + // { helper templates for the rule extendability } + // + // This classes can be 'overloaded' (defined elsewhere), to plug + // in additional functionality into the rule parsing process. + // + /////////////////////////////////////////////////////////////////////////// + #if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED) + #define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED + + template + struct parser_scanner_linker : public ScannerT + { + parser_scanner_linker(ScannerT const scan_) : ScannerT(scan_) {} + }; + + #endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED) + + ////////////////////////////////// + #if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED) + #define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED + + template + struct parser_context_linker : public ContextT + { + template + parser_context_linker(ParserT const& p) + : ContextT(p) {} + + template + void pre_parse(ParserT const& p, ScannerT const& scan) + { ContextT::pre_parse(p, scan); } + + template + ResultT& + post_parse(ResultT& hit, ParserT const& p, ScannerT const& scan) + { return ContextT::post_parse(hit, p, scan); } + }; + + #endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED) + + /////////////////////////////////////////////////////////////////////////// + // + // BOOST_SPIRIT_CONTEXT_PARSE helper macro + // + // The original implementation uses a template class. However, we + // need to lessen the template instantiation depth to help inferior + // compilers that sometimes choke on deep template instantiations. + // The objective is to avoid code redundancy. A macro, in this case + // is an obvious solution. Sigh! + // + // WARNING: INTERNAL USE ONLY. NOT FOR PUBLIC CONSUMPTION. + // + /////////////////////////////////////////////////////////////////////////// + #define BOOST_SPIRIT_CONTEXT_PARSE(scan, this_, scanner_t, context_t, result_t) \ + scanner_t scan_wrap(scan); \ + context_t context_wrap(this_); \ + context_wrap.pre_parse(this_, scan_wrap); \ + result_t hit = parse_main(scan); \ + return context_wrap.post_parse(hit, this_, scan_wrap); + + } // namespace spirit +} // namespace boost + +#endif diff --git a/include/boost/spirit/core/non_terminal/parser_id.hpp b/include/boost/spirit/core/non_terminal/parser_id.hpp new file mode 100644 index 000000000..025c5ead7 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/parser_id.hpp @@ -0,0 +1,77 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2001 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_ID_HPP) +#define BOOST_SPIRIT_PARSER_ID_HPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + class parser_id + { + public: + parser_id() : p(0) {} + explicit parser_id(void const* prule) : p(prule) {} + parser_id(long l_) : l(l_) {} + + bool operator==(parser_id const& x) const { return p == x.p; } + bool operator!=(parser_id const& x) const { return !(*this == x); } + bool operator<(parser_id const& x) const { return p < x.p; } + long to_long() const { return l; } + + private: + + union + { + void const* p; + long l; + }; + }; + + #if defined(BOOST_SPIRIT_DEBUG) + inline std::ostream& + operator<<(std::ostream& out, parser_id const& rid) + { + out << rid.to_long(); + return out; + } + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // parser_address_tag class: tags a parser with its address + // + /////////////////////////////////////////////////////////////////////////// + struct parser_address_tag + { + template + static parser_id id(ParserT const& p) + { return parser_id(&p); } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // parser_tag class: tags a parser with an integer ID + // + /////////////////////////////////////////////////////////////////////////// + template + struct parser_tag + { + template + static parser_id id(ParserT const& p) + { return parser_id(long(N)); } + }; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/non_terminal/rule.hpp b/include/boost/spirit/core/non_terminal/rule.hpp new file mode 100644 index 000000000..f747b1456 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/rule.hpp @@ -0,0 +1,117 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_RULE_HPP) +#define BOOST_SPIRIT_RULE_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/shared_ptr.hpp" + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/scanner/scanner.hpp" +#include "boost/spirit/core/non_terminal/parser_context.hpp" +#include "boost/spirit/core/non_terminal/parser_id.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl + { + template + struct abstract_parser; + + template + struct concrete_parser; + } + + /////////////////////////////////////////////////////////////////////////// + // + // rule class + // + // The rule is a polymorphic parser that acts as a named place- + // holder capturing the behavior of an EBNF expression assigned to + // it. The rule is a template class parameterized by the type of the + // scanner (ScannerT, see scanner.hpp), the rule's context + // (ContextT, see parser_context.hpp), and an arbitrary tag (TagT, + // see parser_id.hpp) that allows a rule to be tagged for + // identification. + // + // The definition of the rule (its right hand side, RHS) is + // reference counted and held by the rule through a smart pointer. + // When a rule is seen in the the RHS of an assignment or copy + // construction EBNF expression, the rule is held by the LHS rule by + // reference. + // + /////////////////////////////////////////////////////////////////////////// + template < + typename ScannerT = scanner<>, + typename ContextT = parser_context, + typename TagT = parser_address_tag> + class rule + : public parser > + , public ContextT::base_t + , public context_aux > + { + public: + + typedef rule self_t; + typedef rule const& embed_t; + typedef parser_scanner_linker scanner_t; + typedef parser_context_linker context_t; + + typedef typename context_t::attr_t attr_t; + typedef typename match_result::type result_t; + + template + struct result { typedef result_t type; }; + + rule(); + ~rule(); + + rule(rule const& r) + : ptr(new impl::concrete_parser(r)) {} + + template + rule(ParserT const& p) + : ptr(new impl::concrete_parser(p)) {} + + template + rule& operator=(ParserT const& p) + { + ptr.reset( + new impl::concrete_parser(p)); + return *this; + } + + // If this is placed above the templatized assignment + // operator, VC6 incorrectly complains ambiguity with + // r1 = r2, where r1 and r2 are both rules. + rule& operator=(rule const& r) + { + ptr.reset( + new impl::concrete_parser(r)); + return *this; + } + + result_t parse(ScannerT const& scan) const; + result_t parse_main(ScannerT const& scan) const; + parser_id id() const; + + private: + + typedef impl::abstract_parser abstract_parser_t; + boost::shared_ptr ptr; + }; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#include "boost/spirit/core/non_terminal/impl/rule.ipp" +#endif diff --git a/include/boost/spirit/core/non_terminal/subrule.hpp b/include/boost/spirit/core/non_terminal/subrule.hpp new file mode 100644 index 000000000..5e18cb227 --- /dev/null +++ b/include/boost/spirit/core/non_terminal/subrule.hpp @@ -0,0 +1,316 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_SUBRULE_HPP) +#define BOOST_SPIRIT_SUBRULE_HPP + +#include "boost/type_traits.hpp" +#include "boost/static_assert.hpp" + +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_PARSER_CONTEXT_HPP) +#include "boost/spirit/core/non_terminal/parser_context.hpp" +#endif + +#if !defined(BOOST_SPIRIT_SUBRULE_IPP) +#include "boost/spirit/core/non_terminal/impl/subrule.ipp" +#endif + +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // subrules_scanner class + // + /////////////////////////////////////////////////////////////////////////// + template + struct subrules_scanner : public ScannerT + { + typedef ScannerT scanner_t; + typedef ListT list_t; + typedef subrules_scanner self_t; + + subrules_scanner(ScannerT const& scan, ListT const& list_) + : ScannerT(scan), list(list_) {} + + template + struct rebind_policies + { + typedef typename rebind_scanner_policies::type + rebind_scanner; + typedef subrules_scanner type; + }; + + template + subrules_scanner< + typename rebind_scanner_policies::type, + ListT> + change_policies(PoliciesT const& policies) const + { + typedef subrules_scanner< + BOOST_SPIRIT_TYPENAME + rebind_scanner_policies::type, + ListT> + subrules_scanner_t; + + return subrules_scanner_t( + ScannerT::change_policies(policies), + list); + } + + template + struct rebind_iterator + { + typedef typename rebind_scanner_iterator::type + rebind_scanner; + typedef subrules_scanner type; + }; + + template + subrules_scanner< + typename rebind_scanner_iterator::type, + ListT> + change_iterator(IteratorT const& first, IteratorT const &last) const + { + typedef subrules_scanner< + BOOST_SPIRIT_TYPENAME + rebind_scanner_iterator::type, + ListT> + subrules_scanner_t; + + return subrules_scanner_t( + ScannerT::change_iterator(first, last), + list); + } + + ListT const& list; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // subrule_scanner type computer class + // + // This computer ensures that the scanner will not be recursively + // instantiated if it's not needed. + // + /////////////////////////////////////////////////////////////////////////// + template + struct subrules_scanner_finder + { + typedef subrules_scanner type; + }; + + #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + // + // MSVC doesn't support PTS. The default implementation + // still works. It just generates a whole lot more + // template instantiations. + + template + struct subrules_scanner_finder, ListT> + { + typedef subrules_scanner type; + }; + + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // subrule_list class + // + /////////////////////////////////////////////////////////////////////////// + template + struct subrule_list : public parser > + { + typedef subrule_list self_t; + typedef FirstT first_t; + typedef RestT rest_t; + + subrule_list(FirstT const& first_, RestT const& rest_) + : first(first_), rest(rest_) {} + + template + struct result + { + typedef typename FirstT::def_t parser_t; + typedef typename parser_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename subrules_scanner_finder::type + subrules_scanner_t; + subrules_scanner_t g_arg(scan, *this); + return first.rhs.parse(g_arg); + } + + template + subrule_list< + FirstT, + subrule_list< + subrule_parser, + RestT> > + operator,(subrule_parser const& rhs) + { + return subrule_list< + FirstT, + subrule_list< + subrule_parser, + RestT> >( + first, + subrule_list< + subrule_parser, + RestT>(rhs, rest)); + } + + FirstT first; + RestT rest; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // subrule_parser class + // + /////////////////////////////////////////////////////////////////////////// + template + struct subrule; // Forward declaration + + template + struct subrule_parser + : public parser > + { + typedef subrule_parser self_t; + typedef subrule subrule_t; + typedef DefT def_t; + + BOOST_STATIC_CONSTANT(int, id = ID); + + template + struct result + { + typedef typename + impl::get_subrule_parser_result< + DefT, ScannerT, typename subrule_t::attr_t>::type type; + }; + + subrule_parser(subrule_t const& start_, DefT const& rhs_) + : rhs(rhs_), start(start_) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + // This will only be called when parsing single subrules. + typedef subrule_list list_t; + typedef subrules_scanner scanner_t; + + list_t list(*this, nil_t()); + scanner_t g_arg(scan, list); + return start.parse(g_arg); + } + + template + inline subrule_list< + self_t, + subrule_list< + subrule_parser, + nil_t> > + operator,(subrule_parser const& rhs) const + { + return subrule_list< + self_t, + subrule_list< + subrule_parser, + nil_t> >( + *this, + subrule_list< + subrule_parser, nil_t>( + rhs, nil_t())); + } + + typename DefT::embed_t rhs; + subrule_t const& start; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // subrule class + // + /////////////////////////////////////////////////////////////////////////// + template + struct subrule + : public parser > + , public ContextT::base_t + { + typedef subrule self_t; + typedef subrule const& embed_t; + + typedef parser_context_linker context_t; + typedef typename context_t::attr_t attr_t; + + BOOST_STATIC_CONSTANT(int, id = ID); + + template + struct result + { + typedef typename + impl::get_subrule_result::type type; + }; + + template + typename parser_result::type + parse_main(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + result_t result; + impl::parse_subrule:: + do_(result, scan); + return result; + } + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef parser_scanner_linker scanner_t; + BOOST_SPIRIT_CONTEXT_PARSE( + scan, *this, scanner_t, context_t, result_t); + } + + template + subrule_parser + operator=(parser const& rhs) const + { + return subrule_parser(*this, rhs.derived()); + } + + private: + + // assignment of subrules is not allowed. Use subrules + // with identical IDs if you want to have aliases. + + #if !defined(BOOST_MSVC) && (BOOST_MSVC > 1200) + subrule& operator=(subrule const&); + #endif + template + subrule& operator=(subrule const&); + }; + +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/parser.hpp b/include/boost/spirit/core/parser.hpp new file mode 100644 index 000000000..f2c22a6c3 --- /dev/null +++ b/include/boost/spirit/core/parser.hpp @@ -0,0 +1,247 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#define BOOST_SPIRIT_PARSER_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/config.hpp" +#include "boost/spirit/core/scanner/scanner.hpp" + +#if defined(BOOST_MSVC) +#include "boost/spirit/core/impl/msvc.hpp" +#endif + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +#define BOOST_SPIRIT_PARSER_RESULT_ARGS typename ScannerT, typename Pizza = nil_t +#else +#define BOOST_SPIRIT_PARSER_RESULT_ARGS typename ScannerT +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost +{ + namespace spirit + { + + template + class action; // forward declaration + + /////////////////////////////////////////////////////////////////////////// + // + // Parser categories + // + // Helper template classes to distinguish different types of + // parsers. The following categories are the most generic. More + // specific types may inherit from these. Each parser has a typedef + // parser_category_t that defines its category. By default, if one + // is not specified, it will inherit from the base parser class + // which typedefs its parser_category_t as plain_parser_category. + // + // - plain parser has nothing special + // - binary parser has subject a and b (e.g. alternative) + // - unary parser has single subject (e.g. kleene star) + // - action parser has an attached action parser + // + /////////////////////////////////////////////////////////////////////////// + struct plain_parser_category {}; + struct binary_parser_category : plain_parser_category {}; + struct unary_parser_category : plain_parser_category {}; + struct action_parser_category : unary_parser_category {}; + + /////////////////////////////////////////////////////////////////////////// + // + // parser_result metafunction + // + // Given a scanner type ScannerT and a parser type ParserT, the + // parser_result metafunction provides the actual result of the + // parser. + // + // Usage: + // + // typename parser_result::type + // + /////////////////////////////////////////////////////////////////////////// + #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + + BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER(parser_result_wrapper, result); + + ////////////////////////////////// + template + struct parser_result + { + typedef typename impl::parser_result_wrapper + ::template result_::type type; + }; + + #else + + ////////////////////////////////// + template + struct parser_result + { + typedef typename ParserT::template result::type type; + }; + + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // parser class + // + // This class is a protocol base class for all parsers. This is + // essentially an interface contract. The parser class does not + // really know how to parse anything but instead relies on the + // template parameter DerivedT (which obviously is assumed to be a + // subclass) to do the actual parsing. + // + // Concrete sub-classes inheriting from parser must have a + // corresponding member function parse(...) compatible with the + // conceptual Interface: + // + // template + // RT parse(ScannerT const& scan) const; + // + // where RT is the desired return type of the parser and ScannerT + // scan is the scanner (see scanner.hpp). + // + // Concrete sub-classes inheriting from parser in most cases need to + // have a nested meta-function result that returns the result type + // of the parser's parse member function, given a scanner type. The + // meta- function has the form: + // + // template + // struct result + // { + // typedef RT type; + // }; + // + // where RT is the desired return type of the parser. This is + // usually, but not always, dependent on the template parameter + // ScannerT. If a parser does not supply a result metafunction, a + // default is provided by the base parser class. + // + // The parser's derived() member function returns a reference to the + // parser as its derived object. + // + // An operator[] is provided. The operator returns a semantic action + // handler (see actions.hpp). + // + // Each parser has a typedef embed_t. This typedef specifies how a + // parser is embedded in a composite (see composite.hpp). By + // default, if one is not specified, the parser will be embedded by + // value. That is, a copy of the parser is placed as a member + // variable of the composite. Most parsers are embedded by value. In + // certain situations however, this is not desirable or possible. + // + /////////////////////////////////////////////////////////////////////////// + template + struct parser + { + typedef DerivedT embed_t; + typedef DerivedT derived_t; + typedef plain_parser_category parser_category_t; + + template + struct result + { + typedef typename match_result::type type; + }; + + DerivedT& derived() + { return *static_cast(this); } + + DerivedT const& derived() const + { return *static_cast(this); } + + template + action + operator[](ActionT const& actor) const + { return action(derived(), actor); } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // parse_info + // + // Results returned by the free parse functions: + // + // stop: points to the final parse position (i.e parsing + // processed the input up to this point). + // + // hit: true if parsing is successful. This may be full: + // the parser consumed all the input, or partial: + // the parser consumed only a portion of the input. + // + // full: true when we have a full hit (i.e the parser + // consumed all the input. + // + // length: The number of characters consumed by the parser. + // This is valid only if we have a successful hit + // (either partial or full). A negative value means + // that the hit is unsucessful. + // + /////////////////////////////////////////////////////////////////////////// + template + struct parse_info + { + IteratorT stop; + bool hit; + bool full; + unsigned length; + + parse_info( + IteratorT const& stop_ = IteratorT(), + bool hit_ = false, + bool full_ = false, + unsigned length_ = 0) + : stop(stop_) + , hit(hit_) + , full(full_) + , length(length_) {} + + template + parse_info(ParseInfoT const& pi) + : stop(pi.stop) + , hit(pi.hit) + , full(pi.full) + , length(pi.length) {} + }; + + /////////////////////////////////////////////////////////////////////////// + // + // Generic parse function + // + /////////////////////////////////////////////////////////////////////////// + template + parse_info + parse( + IteratorT const& first, + IteratorT const& last, + parser const& p); + + /////////////////////////////////////////////////////////////////////////// + // + // Parse function for null terminated strings + // + /////////////////////////////////////////////////////////////////////////// + template + parse_info + parse( + CharT const* str, + parser const& p); + + } // namespace spirit +} // namespace boost + +#endif + +#include "boost/spirit/core/impl/parser.ipp" +#undef BOOST_SPIRIT_PARSER_RESULT_ARGS diff --git a/include/boost/spirit/core/primitives/Makefile.am b/include/boost/spirit/core/primitives/Makefile.am new file mode 100644 index 000000000..2ef18267a --- /dev/null +++ b/include/boost/spirit/core/primitives/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = numerics.hpp primitives.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/primitives diff --git a/include/boost/spirit/core/primitives/impl/Makefile.am b/include/boost/spirit/core/primitives/impl/Makefile.am new file mode 100644 index 000000000..fa45e0386 --- /dev/null +++ b/include/boost/spirit/core/primitives/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = numerics.ipp primitives.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/primitives/impl diff --git a/include/boost/spirit/core/primitives/impl/numerics.ipp b/include/boost/spirit/core/primitives/impl/numerics.ipp new file mode 100644 index 000000000..ae8fbd6f9 --- /dev/null +++ b/include/boost/spirit/core/primitives/impl/numerics.ipp @@ -0,0 +1,480 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_NUMERICS_IPP +#define BOOST_SPIRIT_NUMERICS_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#if defined(BOOST_NO_STDC_NAMESPACE) +#define BOOST_SPIRIT_IMPL_STD_NS +#else +#define BOOST_SPIRIT_IMPL_STD_NS std +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl + { + /////////////////////////////////////////////////////////////////////// + // + // Extract the prefix sign (- or +) + // + /////////////////////////////////////////////////////////////////////// + template + bool + extract_sign(ScannerT const& scan, unsigned& count) + { + // Extract the sign + count = 0; + bool neg = *scan == '-'; + if (neg || (*scan == '+')) + { + ++scan; + ++count; + return neg; + } + + return false; + } + + /////////////////////////////////////////////////////////////////////// + // + // Traits class for radix specific number conversion + // + // Test the validity of a single character: + // + // template static bool is_valid(CharT ch); + // + // Convert a digit from character representation to binary + // representation: + // + // template static int digit(CharT ch); + // + /////////////////////////////////////////////////////////////////////// + template + struct radix_traits; + + ////////////////////////////////// Binary + template<> + struct radix_traits<2> + { + template + static bool is_valid(CharT ch) { return ('0' == ch || '1' == ch); } + + template + static int digit(CharT ch) { return ch - '0'; } + }; + + ////////////////////////////////// Octal + template<> + struct radix_traits<8> + { + template + static bool is_valid(CharT ch) { return ('0' <= ch && ch <= '7'); } + + template + static int digit(CharT ch) { return ch - '0'; } + }; + + ////////////////////////////////// Decimal + template<> + struct radix_traits<10> + { + template + static bool is_valid(CharT ch) { return impl::isdigit_(ch); } + + template + static int digit(CharT ch) { return ch - '0'; } + }; + + ////////////////////////////////// Hexadecimal + template<> + struct radix_traits<16> + { + template + static bool is_valid(CharT ch) { return impl::isxdigit_(ch); } + + template + static int digit(CharT ch) + { + if (impl::isdigit_(ch)) + return ch - '0'; + return impl::tolower_(ch) - 'a' + 10; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // Helper templates for encapsulation of radix specific conversion + // of an input string to an integral value. + // + // main entry point: + // + // extract_int + // ::f(first, last, n, count); + // + // The template parameter Radix represents the radix of the + // number contained in the parsed string. The template + // parameter MinDigits specifies the minimum digits to accept. + // The template parameter MaxDigits specifies the maximum + // digits to parse. A -1 value for MaxDigits will make it parse + // an arbitrarilly large number as long as the numeric type can + // hold it. Accumulate is either positive_accumulate + // (default) for parsing positive numbers or + // negative_accumulate otherwise. + // + // scan.first and scan.last are iterators as usual (i.e. first + // is mutable and is moved forward when a match is found), n is + // a variable that holds the number (passed by reference). The + // number of parsed characters is added to count (also passed + // by reference) + // + // NOTE: + // Returns a non-match, if the number to parse + // overflows (or underflows) the used integral type. + // Overflow (or underflow) is detected when an + // operation wraps a value from its maximum to its + // minimum (or vice-versa). For example, overflow + // occurs when the result of the expression n * x is + // less than n (assuming n is positive and x is greater + // than 1). + // + // BEWARE: + // the parameters 'n' and 'count' should be properly + // initialized before calling this function. + // + ///////////////////////////////////////////////////////////////////////////// + template + struct positive_accumulate + { + // Use this accumulator if number is positive + + template + static bool check(T const& n, T const& prev) + { return n < prev; } + + template + static void add(T& n, CharT ch) + { n += radix_traits::digit(ch); } + }; + + ////////////////////////////////// + template + struct negative_accumulate + { + // Use this accumulator if number is negative + + template + static bool check(T const& n, T const& prev) + { return n > prev; } + + template + static void add(T& n, CharT ch) + { n -= radix_traits::digit(ch); } + }; + + ////////////////////////////////// + template + struct extract_int_base + { + // Common code for extract_int specializations + template + static bool + f(ScannerT& scan, T& n) + { + T prev = n; + n *= Radix; + if (Accumulate::check(n, prev)) + return false; // over/underflow! + prev = n; + Accumulate::add(n, *scan); + if (Accumulate::check(n, prev)) + return false; // over/underflow! + return true; + } + }; + + ////////////////////////////////// + template + struct extract_int_ + { + template < + int Radix, + unsigned MinDigits, + int MaxDigits, + typename Accumulate + > + struct apply + { + typedef extract_int_base base; + typedef radix_traits check; + + template + static bool + f(ScannerT& scan, T& n, unsigned& count) + { + unsigned i = 0; + for (; (i < MaxDigits) && !scan.at_end() + && check::is_valid(*scan); + ++i, ++scan, ++count) + { + if (!base::f(scan, n)) + return false; // over/underflow! + } + return i >= MinDigits; + } + }; + }; + + ////////////////////////////////// + template <> + struct extract_int_ + { + template < + int Radix, + unsigned MinDigits, + int MaxDigits, + typename Accumulate + > + struct apply + { + typedef extract_int_base base; + typedef radix_traits check; + + template + static bool + f(ScannerT& scan, T& n, unsigned& count) + { + unsigned i = 0; + for (; !scan.at_end() && check::is_valid(*scan); + ++i, ++scan, ++count) + { + if (!base::f(scan, n)) + return false; // over/underflow! + } + return i >= MinDigits; + } + }; + }; + + ////////////////////////////////// + template < + int Radix, unsigned MinDigits, int MaxDigits, + typename Accumulate = positive_accumulate + > + struct extract_int + { + template + static bool + f(ScannerT& scan, T& n, unsigned& count) + { + return extract_int_<(MaxDigits >= 0)>::template + apply:: + f(scan, n, count); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // uint_parser_impl class + // + /////////////////////////////////////////////////////////////////////// + template < + typename T = unsigned, + int Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 + > + struct uint_parser_impl + : public parser > + { + typedef uint_parser_impl self_t; + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + if (!scan.at_end()) + { + T n = 0; + unsigned count = 0; + typename ScannerT::iterator_t save = scan.first; + if (extract_int:: + f(scan, n, count)) + { + return scan.create_match(count, n, save, scan.first); + } + // return non-match if number overflows + } + return scan.no_match(); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // int_parser_impl class + // + /////////////////////////////////////////////////////////////////////// + template < + typename T = unsigned, + int Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 + > + struct int_parser_impl + : public parser > + { + typedef int_parser_impl self_t; + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef extract_int > extract_int_neg_t; + typedef extract_int + extract_int_pos_t; + + if (!scan.at_end()) + { + T n = 0; + unsigned count = 0; + typename ScannerT::iterator_t save = scan.first; + + bool hit = impl::extract_sign(scan, count); + + if (hit) + hit = extract_int_neg_t::f(scan, n, count); + else + hit = extract_int_pos_t::f(scan, n, count); + + if (hit) + return scan.create_match(count, n, save, scan.first); + else + scan.first = save; + // return non-match if number overflows or underflows + } + return scan.no_match(); + } + }; + + /////////////////////////////////////////////////////////////////////// + // + // real_parser_impl class + // + /////////////////////////////////////////////////////////////////////// + template + struct real_parser_impl + { + typedef real_parser_impl self_t; + + template + RT parse_main(ScannerT const& scan) const + { + if (scan.at_end()) + return scan.no_match(); + typename ScannerT::iterator_t save = scan.first; + + match sign_match = RealPoliciesT::parse_sign(scan); + unsigned count = sign_match ? sign_match.length() : 0; + bool neg = sign_match.value(); + + RT n_match = RealPoliciesT::parse_n(scan); + T n = n_match.value(); + bool got_a_number = n_match; + + if (!got_a_number && !RealPoliciesT::allow_trailing_left_dot) + return scan.no_match(); + else + count += n_match.length(); + + if (neg) + n = -n; + + if (RealPoliciesT::parse_dot(scan)) + { + // We got the decimal point. Now we will try to parse + // the fraction if it is there. If not, it defaults + // to zero (0) only if we already got a number. + + if (RT hit = RealPoliciesT::parse_frac_n(scan)) + { + hit.value() *= + BOOST_SPIRIT_IMPL_STD_NS::pow(T(10), T(-hit.length())); + if (neg) + n -= hit.value(); + else + n += hit.value(); + count += hit.length() + 1; + + } + + else if (!got_a_number || + !RealPoliciesT::allow_trailing_right_dot) + return scan.no_match(); + } + else + { + if (!got_a_number) + return scan.no_match(); + // We have reached a point where we + // still haven't seen a number at all. + // We return early with a no-match. + } + + if (match<> e_hit = RealPoliciesT::parse_exp(scan)) + { + // We got the exponent prefix. Now we will try to parse the + // actual exponent. It is an error if it is not there. + if (RT e_n_hit = RealPoliciesT::parse_exp_n(scan)) + { + n *= BOOST_SPIRIT_IMPL_STD_NS::pow(T(10), T(e_n_hit.value())); + count += e_n_hit.length() + e_hit.length(); + } + else + { + // Oops, no exponent, return a no-match + return scan.no_match(); + } + } + return scan.create_match(count, n, save, scan.first); + } + + template + static RT parse(ScannerT const& scan) + { + static self_t this_; + return impl::implicit_lexeme_parse(this_, scan, scan); + } + }; + + } // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif +#undef BOOST_SPIRIT_IMPL_STD_NS diff --git a/include/boost/spirit/core/primitives/impl/primitives.ipp b/include/boost/spirit/core/primitives/impl/primitives.ipp new file mode 100644 index 000000000..0d4a1ad62 --- /dev/null +++ b/include/boost/spirit/core/primitives/impl/primitives.ipp @@ -0,0 +1,179 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PRIMITIVES_IPP) +#define BOOST_SPIRIT_PRIMITIVES_IPP + +#include +#if !defined(BOOST_NO_CWCTYPE) +#include +#endif + +#if defined(BOOST_MSVC) +#pragma warning(disable:4800) +#endif + +namespace boost { namespace spirit { + + template struct char_parser; + + namespace impl { + + template + inline IteratorT + get_last(IteratorT first) + { + while (*first) + first++; + return first; + } + + template< + typename RT, + typename IteratorT, + typename ScannerT> + inline RT + string_parser_parse( + IteratorT str_first, + IteratorT str_last, + ScannerT& scan) + { + typedef typename ScannerT::iterator_t iterator_t; + iterator_t saved = scan.first; + int slen = str_last - str_first; + + while (str_first != str_last) + { + if (scan.at_end() || (*str_first != *scan)) + return scan.no_match(); + ++str_first; + ++scan; + } + + return scan.create_match(slen, nil_t(), saved, scan.first); + } + + /////////////////////////////////////////////////////////////////////////// + // + // Convenience functions + // + /////////////////////////////////////////////////////////////////////////// + inline bool + isalnum_(int c) + { using namespace std; return isalnum(c); } + + inline bool + isalpha_(int c) + { using namespace std; return isalpha(c); } + + inline bool + iscntrl_(int c) + { using namespace std; return iscntrl(c); } + + inline bool + isdigit_(int c) + { using namespace std; return isdigit(c); } + + inline bool + isgraph_(int c) + { using namespace std; return isgraph(c); } + + inline bool + islower_(int c) + { using namespace std; return islower(c); } + + inline bool + isprint_(int c) + { using namespace std; return isprint(c); } + + inline bool + ispunct_(int c) + { using namespace std; return ispunct(c); } + + inline bool + isspace_(int c) + { using namespace std; return isspace(c); } + + inline bool + isupper_(int c) + { using namespace std; return isupper(c); } + + inline bool + isxdigit_(int c) + { using namespace std; return isxdigit(c); } + + inline char + tolower_(int c) + { using namespace std; return static_cast(tolower(c)); } + + inline char + toupper_(int c) + { using namespace std; return static_cast(toupper(c)); } + +#if !defined(BOOST_NO_CWCTYPE) + + inline bool + isalnum_(wchar_t c) + { using namespace std; return iswalnum(c); } + + inline bool + isalpha_(wchar_t c) + { using namespace std; return iswalpha(c); } + + inline bool + iscntrl_(wchar_t c) + { using namespace std; return iswcntrl(c); } + + inline bool + isdigit_(wchar_t c) + { using namespace std; return iswdigit(c); } + + inline bool + isgraph_(wchar_t c) + { using namespace std; return iswgraph(c); } + + inline bool + islower_(wchar_t c) + { using namespace std; return iswlower(c); } + + inline bool + isprint_(wchar_t c) + { using namespace std; return iswprint(c); } + + inline bool + ispunct_(wchar_t c) + { using namespace std; return iswpunct(c); } + + inline bool + isspace_(wchar_t c) + { using namespace std; return iswspace(c); } + + inline bool + isupper_(wchar_t c) + { using namespace std; return iswupper(c); } + + inline bool + isxdigit_(wchar_t c) + { using namespace std; return iswxdigit(c); } + + inline wchar_t + tolower_(wchar_t c) + { using namespace std; return towlower(c); } + + inline wchar_t + toupper_(wchar_t c) + { using namespace std; return towupper(c); } + +#endif // !defined(BOOST_NO_CWCTYPE) + +}}} // namespace boost::spirit::impl + +#endif diff --git a/include/boost/spirit/core/primitives/numerics.hpp b/include/boost/spirit/core/primitives/numerics.hpp new file mode 100644 index 000000000..6f7d7f69e --- /dev/null +++ b/include/boost/spirit/core/primitives/numerics.hpp @@ -0,0 +1,279 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2001-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_NUMERICS_HPP +#define BOOST_SPIRIT_NUMERICS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/config.hpp" + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/composite/directives.hpp" +#include "boost/spirit/core/primitives/impl/numerics.ipp" + +// VC++6 chokes and ICEs with parser_result on the real parser traits when +// the real parser is used inside a grammar. This workaround solves the +// problem +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1200) +#define BOOST_SPIRIT_NUMP_RESULT(parser_t, scanner_t, T) \ + typename match_result::type +#else +#define BOOST_SPIRIT_NUMP_RESULT(parser_t, scanner_t, T) \ + typename parser_result::type +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// uint_parser class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename T = unsigned, + int Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 +> +struct uint_parser +: public parser > +{ + typedef uint_parser self_t; + + template + struct result + { + typedef typename match_result::type type; + }; + +// Don't take the #if out. VC6 will hate it! +#if defined(__MWERKS__) && (__MWERKS__ <= 0x2407) +// Don't take the empty constructor out line CW7.2 will hate it! + uint_parser() {} +#endif + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef impl::uint_parser_impl impl_t; + typedef typename parser_result::type result_t; + return impl::contiguous_parser_parse(impl_t(), scan, scan); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// int_parser class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename T = unsigned, + int Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 +> +struct int_parser +: public parser > +{ + typedef int_parser self_t; + + template + struct result + { + typedef typename match_result::type type; + }; + +// Don't take the #if out. VC6 will hate it! +#if defined(__MWERKS__) && (__MWERKS__ <= 0x2407) +// Don't take the empty constructor out line CW7.2 will hate it! + int_parser() {} +#endif + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef impl::int_parser_impl impl_t; + typedef typename parser_result::type result_t; + return impl::contiguous_parser_parse(impl_t(), scan, scan); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// uint_parser/int_parser instantiations +// +/////////////////////////////////////////////////////////////////////////////// +int_parser const + int_p = int_parser(); + +uint_parser const + uint_p = uint_parser(); + +uint_parser const + bin_p = uint_parser(); + +uint_parser const + oct_p = uint_parser(); + +uint_parser const + hex_p = uint_parser(); + +// Borland 5.5 again gets confused if the default template parameters +// are not spelled out explicitly above. Sigh, Borland... + +/////////////////////////////////////////////////////////////////////////////// +// +// sign_parser class +// +/////////////////////////////////////////////////////////////////////////////// + namespace impl + { + // Utility to extract the prefix sign ('-' | '+') + template + bool extract_sign(ScannerT const& scan, unsigned& count); + } + +struct sign_parser : public parser +{ + typedef sign_parser self_t; + template + struct result { + + typedef typename match_result::type type; + }; + + sign_parser() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + if (!scan.at_end()) + { + unsigned length; + typename ScannerT::iterator_t save(scan.first); + bool neg = impl::extract_sign(scan, length); + if (length) + return scan.create_match(1, neg, save, scan.first); + } + return scan.no_match(); + } +}; + +/////////////////////////////////////// +sign_parser const sign_p = sign_parser(); + +/////////////////////////////////////////////////////////////////////////////// +// +// default real number policies +// +/////////////////////////////////////////////////////////////////////////////// +template +struct ureal_parser_policies +{ + // trailing dot policy suggested suggested by Gustavo Guerra + BOOST_STATIC_CONSTANT(bool, allow_trailing_left_dot = true); + BOOST_STATIC_CONSTANT(bool, allow_trailing_right_dot = true); + + typedef uint_parser uint_parser_t; + typedef int_parser int_parser_t; + + template + static typename match_result::type + parse_sign(ScannerT& scan) + { return scan.no_match(); } + + template + static BOOST_SPIRIT_NUMP_RESULT(uint_parser_t, ScannerT, T) + parse_n(ScannerT& scan) + { return uint_parser_t().parse(scan); } + + template + static typename parser_result, ScannerT>::type + parse_dot(ScannerT& scan) + { return ch_p('.').parse(scan); } + + template + static BOOST_SPIRIT_NUMP_RESULT(uint_parser_t, ScannerT, T) + parse_frac_n(ScannerT& scan) + { return uint_parser_t().parse(scan); } + + template + static typename parser_result, ScannerT>::type + parse_exp(ScannerT& scan) + { return nocase_d['e'].parse(scan); } + + template + static BOOST_SPIRIT_NUMP_RESULT(int_parser_t, ScannerT, T) + parse_exp_n(ScannerT& scan) + { return int_parser_t().parse(scan); } +}; + +////////////////////////////////// +template +struct real_parser_policies : public ureal_parser_policies +{ + template + static typename parser_result::type + parse_sign(ScannerT& scan) + { return sign_p.parse(scan); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// real_parser class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename T = double, + typename RealPoliciesT = ureal_parser_policies +> +struct real_parser +: public parser > +{ + typedef real_parser self_t; + + template + struct result + { + typedef typename match_result::type type; + }; + + real_parser() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::real_parser_impl::parse(scan); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// real_parser instantiations +// +/////////////////////////////////////////////////////////////////////////////// +real_parser > const + ureal_p = real_parser >(); + +real_parser > const + real_p = real_parser >(); + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#undef BOOST_SPIRIT_NUMP_RESULT +#endif diff --git a/include/boost/spirit/core/primitives/primitives.hpp b/include/boost/spirit/core/primitives/primitives.hpp new file mode 100644 index 000000000..cf3b11ea9 --- /dev/null +++ b/include/boost/spirit/core/primitives/primitives.hpp @@ -0,0 +1,567 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PRIMITIVES_HPP) +#define BOOST_SPIRIT_PRIMITIVES_HPP + +#if !defined(BOOST_REF_HPP_INCLUDED) +#include "boost/ref.hpp" +#endif + +#if !defined(BOOST_SPIRIT_DEBUG_ASSERT_HPP) +#include "boost/spirit/debug/assert.hpp" +#endif + +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_DIRECTIVES_HPP) +#include "boost/spirit/core/composite/impl/directives.ipp" +#endif + +#if !defined(BOOST_SPIRIT_PRIMITIVES_IPP) +#include "boost/spirit/core/primitives/impl/primitives.ipp" +#endif + +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // char_parser class + // + /////////////////////////////////////////////////////////////////////////// + template + struct char_parser : public parser + { + typedef DerivedT self_t; + template + struct result { + + typedef typename match_result< + ScannerT, + typename ScannerT::value_t + >::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::value_t value_t; + typedef typename ScannerT::iterator_t iterator_t; + + if (!scan.at_end()) + { + value_t ch = *scan; + if (this->derived().test(ch)) + { + iterator_t save(scan.first); + ++scan; + return scan.create_match(1, ch, save, scan.first); + } + } + return scan.no_match(); + } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // negation of char_parsers + // + /////////////////////////////////////////////////////////////////////////// + template + struct negated_char_parser + : public char_parser > + { + typedef negated_char_parser self_t; + typedef PositiveT positive_t; + + negated_char_parser(positive_t const& p) + : positive(p.derived()) {} + + template + bool test(T ch) const + { return !positive.test(ch); } + + positive_t const positive; + }; + + template + inline negated_char_parser + operator~(char_parser const& p) + { + return negated_char_parser(p.derived()); + } + + template + inline ParserT + operator~(negated_char_parser const& n) + { + return n.positive; + } + + /////////////////////////////////////////////////////////////////////////// + // + // chlit class + // + /////////////////////////////////////////////////////////////////////////// + template + struct chlit : public char_parser > + { + chlit(CharT ch_) + : ch(ch_) {} + + template + bool test(T ch_) const + { return ch_ == ch; } + + CharT ch; + }; + + template + inline chlit + ch_p(CharT ch) + { return chlit(ch); } + + /////////////////////////////////////////////////////////////////////////// + // + // range class + // + /////////////////////////////////////////////////////////////////////////// + template + struct range : public char_parser > + { + range(CharT first_, CharT last_) + : first(first_), last(last_) + { BOOST_SPIRIT_ASSERT(first <= last); } + + template + bool test(T ch) const + { return (CharT(ch) >= first) && (CharT(ch) <= last); } + + CharT first; + CharT last; + }; + + template + inline range + range_p(CharT first, CharT last) + { return range(first, last); } + + /////////////////////////////////////////////////////////////////////////// + // + // chseq class + // + /////////////////////////////////////////////////////////////////////////// + template + class chseq : public parser > + { + public: + + typedef chseq self_t; + + chseq(IteratorT first_, IteratorT last_) + : first(first_), last(last_) {} + + chseq(IteratorT first_) + : first(first_), last(impl::get_last(first_)) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename boost::unwrap_reference::type striter_t; + typedef typename parser_result::type result_t; + return impl::string_parser_parse( + striter_t(first), + striter_t(last), + scan); + } + + private: + + IteratorT first; + IteratorT last; + }; + + template + inline chseq + chseq_p(CharT const* str) + { return chseq(str); } + + template + inline chseq + chseq_p(IteratorT first, IteratorT last) + { return chseq(first, last); } + + /////////////////////////////////////////////////////////////////////////// + // + // strlit class + // + /////////////////////////////////////////////////////////////////////////// + template + class strlit : public parser > + { + public: + + typedef strlit self_t; + + strlit(IteratorT first, IteratorT last) + : seq(first, last) {} + + strlit(IteratorT first) + : seq(first) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::contiguous_parser_parse + (seq, scan, scan); + } + + private: + + chseq seq; + }; + + template + inline strlit + str_p(CharT const* str) + { return strlit(str); } + + template + inline strlit + str_p(IteratorT first, IteratorT last) + { return strlit(first, last); } + + /////////////////////////////////////////////////////////////////////////// + // + // nothing_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct nothing_parser : public parser + { + typedef nothing_parser self_t; + + nothing_parser() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { return scan.no_match(); } + }; + + nothing_parser const nothing_p = nothing_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // anychar_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct anychar_parser : public char_parser + { + typedef anychar_parser self_t; + + anychar_parser() {} + + template + bool test(CharT) const + { return true; } + }; + + anychar_parser const anychar_p = anychar_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // alnum_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct alnum_parser : public char_parser + { + typedef alnum_parser self_t; + + alnum_parser() {} + + template + bool test(CharT ch) const + { return impl::isalnum_(ch); } + }; + + alnum_parser const alnum_p = alnum_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // alpha_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct alpha_parser : public char_parser + { + typedef alpha_parser self_t; + + alpha_parser() {} + + template + bool test(CharT ch) const + { return impl::isalpha_(ch); } + }; + + alpha_parser const alpha_p = alpha_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // cntrl_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct cntrl_parser : public char_parser + { + typedef cntrl_parser self_t; + + cntrl_parser() {} + + template + bool test(CharT ch) const + { return impl::iscntrl_(ch); } + }; + + cntrl_parser const cntrl_p = cntrl_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // digit_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct digit_parser : public char_parser + { + typedef digit_parser self_t; + + digit_parser() {} + + template + bool test(CharT ch) const + { return impl::isdigit_(ch); } + }; + + digit_parser const digit_p = digit_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // graph_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct graph_parser : public char_parser + { + typedef graph_parser self_t; + + graph_parser() {} + + template + bool test(CharT ch) const + { return impl::isgraph_(ch); } + }; + + graph_parser const graph_p = graph_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // lower_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct lower_parser : public char_parser + { + typedef lower_parser self_t; + + lower_parser() {} + + template + bool test(CharT ch) const + { return impl::islower_(ch); } + }; + + lower_parser const lower_p = lower_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // print_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct print_parser : public char_parser + { + typedef print_parser self_t; + + print_parser() {} + + template + bool test(CharT ch) const + { return impl::isprint_(ch); } + }; + + print_parser const print_p = print_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // punct_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct punct_parser : public char_parser + { + typedef punct_parser self_t; + + punct_parser() {} + + template + bool test(CharT ch) const + { return impl::ispunct_(ch); } + }; + + punct_parser const punct_p = punct_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // blank_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct blank_parser : public char_parser + { + typedef blank_parser self_t; + + blank_parser() {} + + template + bool test(CharT ch) const + { return ch == ' ' || ch == '\t'; } + // some systems have isblank(), but some don't, so just do it manually. + }; + + ////////////////////////////////// + blank_parser const blank_p = blank_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // space_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct space_parser : public char_parser + { + typedef space_parser self_t; + + space_parser() {} + + template + bool test(CharT ch) const + { return impl::isspace_(ch); } + }; + + space_parser const space_p = space_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // upper_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct upper_parser : public char_parser + { + typedef upper_parser self_t; + + upper_parser() {} + + template + bool test(CharT ch) const + { return impl::isupper_(ch); } + }; + + upper_parser const upper_p = upper_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // xdigit_parser class + // + /////////////////////////////////////////////////////////////////////////// + struct xdigit_parser : public char_parser + { + typedef xdigit_parser self_t; + + xdigit_parser() {} + + template + bool test(CharT ch) const + { return impl::isxdigit_(ch); } + }; + + xdigit_parser const xdigit_p = xdigit_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // eol_parser class (contributed by Martin Wille) + // + /////////////////////////////////////////////////////////////////////////// + struct eol_parser : public parser + { + typedef eol_parser self_t; + + eol_parser() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typename ScannerT::iterator_t save = scan.first; + int len = 0; + + if (!scan.at_end() && *scan == '\r') // CR + { + ++scan; + ++len; + } + + if (!scan.at_end() && *scan == '\n') // LF + { + ++scan; + ++len; + } + + if (len) + return scan.create_match(len, nil_t(), save, scan.first); + return scan.no_match(); + } + }; + + eol_parser const eol_p = eol_parser(); + + /////////////////////////////////////////////////////////////////////////// + // + // end_parser class (suggested by Markus Schöpflin) + // + /////////////////////////////////////////////////////////////////////////// + struct end_parser : public parser + { + typedef end_parser self_t; + + end_parser() {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + if (scan.at_end()) + return scan.empty_match(); + return scan.no_match(); + } + }; + + end_parser const end_p = end_parser(); + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/core/scanner/Makefile.am b/include/boost/spirit/core/scanner/Makefile.am new file mode 100644 index 000000000..461bfcf9f --- /dev/null +++ b/include/boost/spirit/core/scanner/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = scanner.hpp skipper.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/scanner diff --git a/include/boost/spirit/core/scanner/impl/Makefile.am b/include/boost/spirit/core/scanner/impl/Makefile.am new file mode 100644 index 000000000..c28a9d6eb --- /dev/null +++ b/include/boost/spirit/core/scanner/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = skipper.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/core/scanner/impl diff --git a/include/boost/spirit/core/scanner/impl/skipper.ipp b/include/boost/spirit/core/scanner/impl/skipper.ipp new file mode 100644 index 000000000..5857c845a --- /dev/null +++ b/include/boost/spirit/core/scanner/impl/skipper.ipp @@ -0,0 +1,178 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +============================================================================*/ +#if !defined(BOOST_SPIRIT_SKIPPER_IPP) +#define BOOST_SPIRIT_SKIPPER_IPP + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + struct space_parser; + template + struct no_skipper_iteration_policy; + + namespace impl + { + template + inline void + skipper_skip( + ST const& s, + ScannerT const& scan, + skipper_iteration_policy const&) + { + typedef scanner_policies< + no_skipper_iteration_policy< + BOOST_SPIRIT_TYPENAME ScannerT::iteration_policy_t>, + BOOST_SPIRIT_TYPENAME ScannerT::match_policy_t, + BOOST_SPIRIT_TYPENAME ScannerT::action_policy_t + > policies_t; + + scanner + scan2(scan.first, scan.last, policies_t(scan)); + typedef typename ScannerT::iterator_t iterator_t; + + for (;;) + { + iterator_t save = scan.first; + if (!s.parse(scan2)) + { + scan.first = save; + break; + } + } + } + + template + inline void + skipper_skip( + ST const& s, + ScannerT const& scan, + no_skipper_iteration_policy const&) + { + for (;;) + { + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + if (!s.parse(scan)) + { + scan.first = save; + break; + } + } + } + + template + inline void + skipper_skip( + ST const& s, + ScannerT const& scan, + iteration_policy const&) + { + for (;;) + { + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + if (!s.parse(scan)) + { + scan.first = save; + break; + } + } + } + + template + struct phrase_parser + { + template + static parse_info + parse( + IteratorT const& first_, + IteratorT const& last, + ParserT const& p, + SkipT const& skip) + { + typedef skip_parser_iteration_policy iter_policy_t; + typedef scanner_policies scanner_policies_t; + typedef scanner scanner_t; + + iter_policy_t iter_policy(skip); + scanner_policies_t policies(iter_policy); + IteratorT first = first_; + scanner_t scan(first, last, policies); + match hit = p.parse(scan); + return parse_info( + first, hit, hit && (first == last), hit.length()); + } + }; + + template <> + struct phrase_parser + { + template + static parse_info + parse( + IteratorT const& first_, + IteratorT const& last, + ParserT const& p, + space_parser const&) + { + typedef skipper_iteration_policy<> iter_policy_t; + typedef scanner_policies scanner_policies_t; + typedef scanner scanner_t; + + IteratorT first = first_; + scanner_t scan(first, last); + match hit = p.parse(scan); + return parse_info( + first, hit, hit && (first == last), hit.length()); + } + }; + } + +/////////////////////////////////////////////////////////////////////////////// +// +// Free parse functions using the skippers +// +/////////////////////////////////////////////////////////////////////////////// +template +inline parse_info +parse( + IteratorT const& first, + IteratorT const& last, + parser const& p, + parser const& skip) +{ + return impl::phrase_parser:: + parse(first, last, p.derived(), skip.derived()); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Parse function for null terminated strings using the skippers +// +/////////////////////////////////////////////////////////////////////////////// +template +inline parse_info +parse( + CharT const* str, + parser const& p, + parser const& skip) +{ + CharT const* last = str; + while (*last) + last++; + return parse(str, last, p, skip); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/core/scanner/scanner.hpp b/include/boost/spirit/core/scanner/scanner.hpp new file mode 100644 index 000000000..5e4fe52af --- /dev/null +++ b/include/boost/spirit/core/scanner/scanner.hpp @@ -0,0 +1,373 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2002 Spirit-Dev + Copyright (c) 2001 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. + + See spirit.hpp for full copyright notices. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_SCANNER_HPP) +#define BOOST_SPIRIT_SCANNER_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#include "boost/config.hpp" + +#include "boost/spirit/core/match.hpp" +#include "boost/spirit/core/non_terminal/parser_id.hpp" + +#if defined(BOOST_MSVC) +#include "boost/spirit/core/impl/msvc.hpp" +#endif + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +#define BOOST_SPIRIT_IT_NS impl +#define BOOST_SPIRIT_MP_TYPE_COMPUTER_ARGS \ + typename T, typename Pizza = nil_t +#define BOOST_SPIRIT_P_TYPE_COMPUTER_ARGS \ + typename PoliciesT2, typename Pizza = nil_t +#define BOOST_SPIRIT_I_TYPE_COMPUTER_ARGS \ + typename IteratorT2, typename Pizza = nil_t +#else +#define BOOST_SPIRIT_IT_NS std +#define BOOST_SPIRIT_MP_TYPE_COMPUTER_ARGS typename T +#define BOOST_SPIRIT_P_TYPE_COMPUTER_ARGS typename PoliciesT2 +#define BOOST_SPIRIT_I_TYPE_COMPUTER_ARGS typename IteratorT2 +#endif + +#if (defined(BOOST_INTEL_CXX_VERSION) && !defined(_STLPORT_VERSION)) +#undef BOOST_SPIRIT_IT_NS +#define BOOST_SPIRIT_IT_NS impl +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// iteration_policy class +// +/////////////////////////////////////////////////////////////////////////////// +struct iteration_policy +{ + template + void + advance(ScannerT const& scan) const + { ++scan.first; } + + template + bool at_end(ScannerT const& scan) const + { return scan.first == scan.last; } + + template + T filter(T ch) const + { return ch; } + + template + typename ScannerT::ref_t + get(ScannerT const& scan) const + { return *scan.first; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// match_policy class +// +/////////////////////////////////////////////////////////////////////////////// +struct match_policy +{ + template + struct result { typedef match type; }; + + const match + no_match() const + { return match(); } + + const match + empty_match() const + { return match(0, nil_t()); } + + template + match + create_match( + unsigned length, + AttrT const& val, + IteratorT const& /*first*/, + IteratorT const& /*last*/) const + { return match(length, val); } + + template + void + group_match( + MatchT& /*m*/, + parser_id const& /*id*/, + IteratorT const& /*first*/, + IteratorT const& /*last*/) const {} + + template + void + concat_match(Match1T& l, Match2T const& r) const + { l.concat(r); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// match_result class +// +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER(match_result_wrapper, result); + +////////////////////////////////// +template +struct match_result +{ + typedef typename impl::match_result_wrapper + ::template result_::type type; +}; + +#else + +////////////////////////////////// +template +struct match_result +{ + typedef typename MatchPolicyT::template result::type type; +}; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// action_policy class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct attributed_action_policy +{ + template + static void + call( + ActorT const& actor, + AttrT const& val, + IteratorT const&, + IteratorT const&) + { actor(val); } +}; + +////////////////////////////////// +template <> +struct attributed_action_policy +{ + template + static void + call( + ActorT const& actor, + nil_t, + IteratorT const& first, + IteratorT const& last) + { actor(first, last); } +}; + +////////////////////////////////// +struct action_policy +{ + template + void + do_action( + ActorT const& actor, + AttrT const& val, + IteratorT const& first, + IteratorT const& last) const + { attributed_action_policy::call(actor, val, first, last); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// scanner_policies class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename IterationPolicyT = iteration_policy, + typename MatchPolicyT = match_policy, + typename ActionPolicyT = action_policy> +struct scanner_policies : + public IterationPolicyT, + public MatchPolicyT, + public ActionPolicyT +{ + typedef IterationPolicyT iteration_policy_t; + typedef MatchPolicyT match_policy_t; + typedef ActionPolicyT action_policy_t; + + scanner_policies( + IterationPolicyT const& i_policy = IterationPolicyT(), + MatchPolicyT const& m_policy = MatchPolicyT(), + ActionPolicyT const& a_policy = ActionPolicyT()) + : IterationPolicyT(i_policy) + , MatchPolicyT(m_policy) + , ActionPolicyT(a_policy) {} + + template + scanner_policies(ScannerPoliciesT const& policies) + : IterationPolicyT(policies) + , MatchPolicyT(policies) + , ActionPolicyT(policies) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// scanner class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename IteratorT = char const*, + typename PoliciesT = scanner_policies<> > +class scanner : public PoliciesT { + +public: + + typedef IteratorT iterator_t; + typedef PoliciesT policies_t; + + typedef typename BOOST_SPIRIT_IT_NS::iterator_traits::value_type + value_t; + typedef typename BOOST_SPIRIT_IT_NS::iterator_traits::reference + ref_t; + typedef typename boost::call_traits::param_type + iter_param_t; + + scanner( + IteratorT& first_, + iter_param_t last_, + PoliciesT const& policies = PoliciesT()) + : PoliciesT(policies), first(first_), last(last_) { + at_end(); + } + + scanner(scanner const& other) + : PoliciesT(other), first(other.first), last(other.last) {} + + scanner(scanner const& other, IteratorT& first_) + : PoliciesT(other), first(first_), last(other.last) {} + + bool + at_end() const + { + typedef typename PoliciesT::iteration_policy_t iteration_policy_t; + return iteration_policy_t::at_end(*this); + } + + value_t + operator*() const + { + typedef typename PoliciesT::iteration_policy_t iteration_policy_t; + return iteration_policy_t::filter(iteration_policy_t::get(*this)); + } + + scanner const& + operator++() const + { + typedef typename PoliciesT::iteration_policy_t iteration_policy_t; + iteration_policy_t::advance(*this); + return *this; + } + + template + struct rebind_policies { + + typedef scanner type; + }; + + template + scanner + change_policies(PoliciesT2 const& policies) const + { + return scanner(first, last, policies); + } + + template + struct rebind_iterator { + + typedef scanner type; + }; + + template + scanner + change_iterator(IteratorT2 const& first_, IteratorT2 const &last_) const + { + return scanner(first_, last_, *this); + } + + IteratorT& first; + IteratorT const last; + +private: + + scanner& + operator=(scanner const& other); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// rebind_scanner_policies class +// +/////////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) + +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER( + rebind_scanner_policies_wrapper, rebind_policies); + +////////////////////////////////// +template +struct rebind_scanner_policies +{ + typedef typename impl::rebind_scanner_policies_wrapper + ::template result_::type type; +}; + +////////////////////////////////// +BOOST_SPIRIT_DEPENDENT_TEMPLATE_WRAPPER( + rebind_scanner_iterator_wrapper, rebind_iterator); + +template +struct rebind_scanner_iterator +{ + typedef typename impl::rebind_scanner_iterator_wrapper + ::template result_::type type; +}; + +#else + +////////////////////////////////// +template +struct rebind_scanner_policies +{ + typedef typename ScannerT::template + rebind_policies::type type; +}; + +////////////////////////////////// +template +struct rebind_scanner_iterator +{ + typedef typename ScannerT::template + rebind_iterator::type type; +}; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif +#undef BOOST_SPIRIT_IT_NS +#undef BOOST_SPIRIT_MP_TYPE_COMPUTER_ARGS +#undef BOOST_SPIRIT_P_TYPE_COMPUTER_ARGS diff --git a/include/boost/spirit/core/scanner/skipper.hpp b/include/boost/spirit/core/scanner/skipper.hpp new file mode 100644 index 000000000..59c2e90cf --- /dev/null +++ b/include/boost/spirit/core/scanner/skipper.hpp @@ -0,0 +1,171 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 1998-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_SKIPPER_HPP) +#define BOOST_SPIRIT_SKIPPER_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#include "boost/spirit/core/scanner/scanner.hpp" +#include "boost/spirit/core/primitives/impl/primitives.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +template +struct no_skipper_iteration_policy; // forward + +/////////////////////////////////////////////////////////////////////////////// +// +// skipper_iteration_policy class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct skipper_iteration_policy : public BaseT +{ + typedef BaseT base_t; + + skipper_iteration_policy() + : BaseT() {} + + template + skipper_iteration_policy(PolicyT const& other) + : BaseT(other) {} + + template + void + advance(ScannerT const& scan) const + { + BaseT::advance(scan); + scan.skip(scan); + } + + template + bool + at_end(ScannerT const& scan) const + { + scan.skip(scan); + return BaseT::at_end(scan); + } + + template + void + skip(ScannerT const& scan) const + { + while (!BaseT::at_end(scan) && impl::isspace_(BaseT::get(scan))) + BaseT::advance(scan); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// skipper_iteration_policy class +// +/////////////////////////////////////////////////////////////////////////////// + namespace impl + { + template + void + skipper_skip( + ST const& s, + ScannerT const& scan, + skipper_iteration_policy const&); + + template + void + skipper_skip( + ST const& s, + ScannerT const& scan, + no_skipper_iteration_policy const&); + + template + void + skipper_skip( + ST const& s, + ScannerT const& scan, + iteration_policy const&); + } + +template +class skip_parser_iteration_policy : public skipper_iteration_policy +{ +public: + + typedef skipper_iteration_policy base_t; + + skip_parser_iteration_policy( + ParserT const& skip_parser, + base_t const& base = base_t()) + : base_t(base), subject(skip_parser) {} + + template + skip_parser_iteration_policy(PolicyT const& other) + : base_t(other), subject(other.skipper()) {} + + template + void + skip(ScannerT const& scan) const + { + impl::skipper_skip(subject, scan, scan); + } + + ParserT const& + skipper() const + { return subject; } + +private: + + ParserT const& subject; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Free parse functions using the skippers +// +/////////////////////////////////////////////////////////////////////////////// +template +parse_info +parse( + IteratorT const& first, + IteratorT const& last, + parser const& p, + parser const& skip); + +/////////////////////////////////////////////////////////////////////////////// +// +// Parse function for null terminated strings using the skippers +// +/////////////////////////////////////////////////////////////////////////////// +template +parse_info +parse( + CharT const* str, + parser const& p, + parser const& skip); + +/////////////////////////////////////////////////////////////////////////////// +// +// phrase_scanner_t +// +// The most common scanner. Use this typedef when you need +// a scanner that skips white spaces. +// +/////////////////////////////////////////////////////////////////////////////// +typedef skipper_iteration_policy<> iter_policy_t; +typedef scanner_policies scanner_policies_t; +typedef scanner phrase_scanner_t; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#include "boost/spirit/core/scanner/impl/skipper.ipp" +#endif + diff --git a/include/boost/spirit/debug.hpp b/include/boost/spirit/debug.hpp new file mode 100644 index 000000000..a0d276801 --- /dev/null +++ b/include/boost/spirit/debug.hpp @@ -0,0 +1,146 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP) +#define BOOST_SPIRIT_DEBUG_MAIN_HPP + +#include "boost/spirit/debug/assert.hpp" + +/////////////////////////////////////////////////////////////////////////// +#if defined(BOOST_SPIRIT_DEBUG) + +/////////////////////////////////////////////////////////////////////////////// +// +// Spirit.Debug includes and defines +// +/////////////////////////////////////////////////////////////////////////////// + + #include + + /////////////////////////////////////////////////////////////////////////// + // + // The BOOST_SPIRIT_DEBUG_OUT defines the stream object, which should be used + // for debug diagnostics. This defaults to std::cout. + // + /////////////////////////////////////////////////////////////////////////// + #if !defined(BOOST_SPIRIT_DEBUG_OUT) + #define BOOST_SPIRIT_DEBUG_OUT std::cout + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // The BOOST_SPIRIT_DEBUG_PRINT_SOME constant defines the number of characters + // from the stream to be printed for diagnosis. This defaults to the first + // 20 characters. + // + /////////////////////////////////////////////////////////////////////////// + #if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME) + #define BOOST_SPIRIT_DEBUG_PRINT_SOME 20 + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // Additional BOOST_SPIRIT_DEBUG_FLAGS control the level of diagnostics printed + // Basic constants are defined in debug/minimal.hpp. + // + /////////////////////////////////////////////////////////////////////////// + #define BOOST_SPIRIT_DEBUG_FLAGS_NODES 0x0001 // node diagnostics + #define BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR 0x0002 // escape_char_parse diagnostics + #define BOOST_SPIRIT_DEBUG_FLAGS_TREES 0x0004 // parse tree/ast diagnostics + #define BOOST_SPIRIT_DEBUG_FLAGS_SLEX 0x8000 // slex diagnostics + + #define BOOST_SPIRIT_DEBUG_FLAGS_MAX 0xFFFF // print maximal diagnostics + + #if !defined(BOOST_SPIRIT_DEBUG_FLAGS) + #define BOOST_SPIRIT_DEBUG_FLAGS BOOST_SPIRIT_DEBUG_FLAGS_MAX + #endif + + /////////////////////////////////////////////////////////////////////////// + // + // By default all nodes are traced (even those, not registered with + // BOOST_SPIRIT_DEBUG_RULE et.al. - see below). The following constant may be + // used to redefine this default. + // + /////////////////////////////////////////////////////////////////////////// + #if !defined(BOOST_SPIRIT_DEBUG_TRACENODE) + #define BOOST_SPIRIT_DEBUG_TRACENODE (true) + #endif // !defined(BOOST_SPIRIT_DEBUG_TRACENODE) + + /////////////////////////////////////////////////////////////////////////// + // + // Helper macros for giving rules and subrules a name accessible through + // parser_name() functions (see parser_names.hpp). + // + // Additionally, the macros BOOST_SPIRIT_DEBUG_RULE, SPIRIT_DEBUG_NODE and + // BOOST_SPIRIT_DEBUG_GRAMMAR enable/disable the tracing of the corresponding + // node accordingly to the PP constant BOOST_SPIRIT_DEBUG_TRACENODE. + // + // The macros BOOST_SPIRIT_TRACE_RULE, SPIRIT_TRACE_NODE and + // BOOST_SPIRIT_TRACE_GRAMMAR allow to specify a flag to define, if the + // corresponding node is to be traced or not. + // + /////////////////////////////////////////////////////////////////////////// + #if !defined(BOOST_SPIRIT_DEBUG_RULE) + #define BOOST_SPIRIT_DEBUG_RULE(r) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, #r, BOOST_SPIRIT_DEBUG_TRACENODE) + #endif // !defined(BOOST_SPIRIT_DEBUG_RULE) + + #if !defined(BOOST_SPIRIT_DEBUG_NODE) + #define BOOST_SPIRIT_DEBUG_NODE(r) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, #r, BOOST_SPIRIT_DEBUG_TRACENODE) + #endif // !defined(BOOST_SPIRIT_DEBUG_NODE) + + #if !defined(BOOST_SPIRIT_DEBUG_GRAMMAR) + #define BOOST_SPIRIT_DEBUG_GRAMMAR(r) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, #r, BOOST_SPIRIT_DEBUG_TRACENODE) + #endif // !defined(BOOST_SPIRIT_DEBUG_GRAMMAR) + + #if !defined(BOOST_SPIRIT_TRACE_RULE) + #define BOOST_SPIRIT_TRACE_RULE(r, t) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, #r, (t)) + #endif // !defined(BOOST_SPIRIT_TRACE_RULE) + + #if !defined(BOOST_SPIRIT_TRACE_NODE) + #define BOOST_SPIRIT_TRACE_NODE(r, t) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, #r, (t)) + #endif // !defined(BOOST_SPIRIT_TRACE_NODE) + + #if !defined(BOOST_SPIRIT_TRACE_GRAMMAR) + #define BOOST_SPIRIT_TRACE_GRAMMAR(r, t) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, #r, (t)) + #endif // !defined(BOOST_SPIRIT_TRACE_GRAMMAR) + + #if !defined(BOOST_SPIRIT_TRACE_RULE_NAME) + #define BOOST_SPIRIT_TRACE_RULE_NAME(r, n, t) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, (n), (t)) + #endif // !defined(BOOST_SPIRIT_TRACE_RULE_NAME) + + #if !defined(BOOST_SPIRIT_TRACE_NODE_NAME) + #define BOOST_SPIRIT_TRACE_NODE_NAME(r, n, t) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, (n), (t)) + #endif // !defined(BOOST_SPIRIT_TRACE_NODE_NAME) + + #if !defined(BOOST_SPIRIT_TRACE_GRAMMAR_NAME) + #define BOOST_SPIRIT_TRACE_GRAMMAR_NAME(r, t) \ + ::boost::spirit::impl::get_node_registry().register_node(&r, (n), (t)) + #endif // !defined(BOOST_SPIRIT_TRACE_GRAMMAR_NAME) + + ////////////////////////////////// + #include "boost/spirit/debug/debug_node.hpp" + +#else + ////////////////////////////////// + #include "boost/spirit/debug/minimal.hpp" + +#endif // BOOST_SPIRIT_DEBUG + +#endif + diff --git a/include/boost/spirit/debug/Makefile.am b/include/boost/spirit/debug/Makefile.am new file mode 100644 index 000000000..39ecb8ec0 --- /dev/null +++ b/include/boost/spirit/debug/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = debug_node.hpp minimal.hpp parser_names.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/debug diff --git a/include/boost/spirit/debug/assert.hpp b/include/boost/spirit/debug/assert.hpp new file mode 100644 index 000000000..5e072584f --- /dev/null +++ b/include/boost/spirit/debug/assert.hpp @@ -0,0 +1,36 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ + +#if !defined(BOOST_SPIRIT_DEBUG_ASSERT_HPP) +#define BOOST_SPIRIT_DEBUG_ASSERT_HPP + +/////////////////////////////////////////////////////////////////////////// +// +// BOOST_SPIRIT_ASSERT is used throughout the framework. It can be overridden +// by the user. If BOOST_SPIRIT_ASSERT_EXCEPTION is defined, then that will +// be thrown, otherwise, BOOST_SPIRIT_ASSERT simply turns into a plain assert() +// +/////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_ASSERT) +#if defined(NDEBUG) + #define BOOST_SPIRIT_ASSERT(x) +#elif defined (BOOST_SPIRIT_ASSERT_EXCEPTION) + #define BOOST_SPIRIT_ASSERT_AUX(f, l, x) \ + do{ if (!(x)) throw BOOST_SPIRIT_ASSERT_EXCEPTION(f "(" #l "): " #x); } while(0) + #define BOOST_SPIRIT_ASSERT(x) SPIRIT_ASSERT_AUX(__FILE__, __LINE__, x) +#else + #include + #define BOOST_SPIRIT_ASSERT(x) assert(x) +#endif +#endif // !defined(BOOST_SPIRIT_ASSERT) + +#endif // BOOST_SPIRIT_DEBUG_ASSERT_HPP diff --git a/include/boost/spirit/debug/debug_node.hpp b/include/boost/spirit/debug/debug_node.hpp new file mode 100644 index 000000000..fcf2afecb --- /dev/null +++ b/include/boost/spirit/debug/debug_node.hpp @@ -0,0 +1,181 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP) +#define BOOST_SPIRIT_DEBUG_NODE_HPP + +#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP) +#error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp" +#endif + +#if defined(BOOST_SPIRIT_DEBUG) + +#include + +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// Debug helper classes for rules, which ensure maximum non-intrusiveness of +// the Spirit debug support +// +/////////////////////////////////////////////////////////////////////////////// + +namespace impl { +/////////////////////////////////////////////////////////////////////////////// +// +// Dump infos about the parsing state of a rule +// +/////////////////////////////////////////////////////////////////////////////// + +#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES + template + inline void + print_node_info(bool hit, int level, bool close, std::string const& name, + IteratorT first, IteratorT last) + { + if (!name.empty()) + { + for (int i = 0; i < level; ++i) + BOOST_SPIRIT_DEBUG_OUT << " "; + if (close) + { + if (hit) + BOOST_SPIRIT_DEBUG_OUT << "/"; + else + BOOST_SPIRIT_DEBUG_OUT << "#"; + } + BOOST_SPIRIT_DEBUG_OUT << name << ":\t\""; + IteratorT iter = first; + IteratorT ilast = last; + for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j) + { + if (iter == ilast) + break; + + switch (*iter) { + + case '\r': BOOST_SPIRIT_DEBUG_OUT << "\\r"; break; + case '\n': BOOST_SPIRIT_DEBUG_OUT << "\\n"; break; + case '\0': BOOST_SPIRIT_DEBUG_OUT << "\\0"; break; + default: BOOST_SPIRIT_DEBUG_OUT << *iter; break; + } + ++iter; + } + BOOST_SPIRIT_DEBUG_OUT << " \"\n"; + } + } +#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES + +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Implementation note: The parser_context_linker and parser_scanner_linker +// classes are wrapped by a PP constant to allow redefinition of this class +// outside of Spirit +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED) +#define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED + + /////////////////////////////////////////////////////////////////////////// + // + // parser_context_linker is a debug wrapper for the ContextT template + // parameter of the rule<> class + // + /////////////////////////////////////////////////////////////////////////// + template + struct parser_context_linker : public ContextT + { + typedef ContextT base_t; + + template + parser_context_linker(ParserT const& p) + : ContextT(p) {} + + template + void pre_parse(ParserT const& p, ScannerT &scan) + { + this->base_t::pre_parse(p, scan); + +#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES + if (trace_parser(p)) { + impl::print_node_info( + false, + scan.get_level(), + false, + parser_name(p), + scan.first, + scan.last); + } + scan.get_level()++; +#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES + } + + template + ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan) + { +#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES + --scan.get_level(); + if (trace_parser(p)) { + impl::print_node_info( + hit, + scan.get_level(), + true, + parser_name(p), + scan.first, + scan.last); + } +#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES + + return this->base_t::post_parse(hit, p, scan); + } + }; + +#endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED) + +#if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED) +#define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED + +/////////////////////////////////////////////////////////////////////////////// +// This class is to avoid linker problems and to ensure a real singleton +// 'level' variable + struct debug_support { + + int &get_level() { + static int level = 0; + + return level; + } + }; + + template + struct parser_scanner_linker : public ScannerT { + + parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_) + {} + + int &get_level() + { return debug.get_level(); } + + private: + debug_support debug; + }; + +#endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED) + +}} // namespace boost::spirit + +#endif // defined(BOOST_SPIRIT_DEBUG) + +#endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP) + diff --git a/include/boost/spirit/debug/impl/Makefile.am b/include/boost/spirit/debug/impl/Makefile.am new file mode 100644 index 000000000..296b71844 --- /dev/null +++ b/include/boost/spirit/debug/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = parser_names.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/debug/impl diff --git a/include/boost/spirit/debug/impl/parser_names.ipp b/include/boost/spirit/debug/impl/parser_names.ipp new file mode 100644 index 000000000..542d790c5 --- /dev/null +++ b/include/boost/spirit/debug/impl/parser_names.ipp @@ -0,0 +1,515 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_NAMES_IPP) +#define BOOST_SPIRIT_PARSER_NAMES_IPP + +#if defined(BOOST_SPIRIT_DEBUG) + +#include +#include +#include + +#include "boost/config.hpp" +#ifdef BOOST_NO_STRINGSTREAM +#include +#define BOOST_SPIRIT_SSTREAM std::strstream +std::string BOOST_SPIRIT_GETSTRING(std::strstream& ss) +{ + ss << ends; + std::string rval = ss.str(); + ss.freeze(false); + return rval; +} +#else +#include +#define BOOST_SPIRIT_GETSTRING(ss) ss.str() +#define BOOST_SPIRIT_SSTREAM std::stringstream +#endif + +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// from actions.hpp + template + inline std::string + parser_name(action const& p) + { + return std::string("action") + + std::string("[") + + parser_name(p.subject()) + + std::string("]"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from directives.hpp + template + inline std::string + parser_name(contiguous const& p) + { + return std::string("contiguous") + + std::string("[") + + parser_name(p.subject()) + + std::string("]"); + } + + template + inline std::string + parser_name(inhibit_case const& p) + { + return std::string("inhibit_case") + + std::string("[") + + parser_name(p.subject()) + + std::string("]"); + } + + template + inline std::string + parser_name(longest_alternative const& p) + { + return std::string("longest_alternative") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(shortest_alternative const& p) + { + return std::string("shortest_alternative") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from numerics.hpp + template + inline std::string + parser_name(uint_parser const& p) + { + BOOST_SPIRIT_SSTREAM stream; + stream << Radix << ", " << MinDigits << ", " << MaxDigits; + return std::string("uint_parser<") + + BOOST_SPIRIT_GETSTRING(stream) + + std::string(">"); + } + + template + inline std::string + parser_name(int_parser const& p) + { + BOOST_SPIRIT_SSTREAM stream; + stream << Radix << ", " << MinDigits << ", " << MaxDigits; + return std::string("int_parser<") + + BOOST_SPIRIT_GETSTRING(stream) + + std::string(">"); + } + + template + inline std::string + parser_name(real_parser const& p) + { + return std::string("real_parser"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from operators.hpp + template + inline std::string + parser_name(sequence const& p) + { + return std::string("sequence") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(sequential_or const& p) + { + return std::string("sequential_or") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(alternative const& p) + { + return std::string("alternative") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(intersection const& p) + { + return std::string("intersection") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(difference const& p) + { + return std::string("difference") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(exclusive_or const& p) + { + return std::string("exclusive_or") + + std::string("[") + + parser_name(p.left()) + std::string(", ") + parser_name(p.right()) + + std::string("]"); + } + + template + inline std::string + parser_name(optional const& p) + { + return std::string("optional") + + std::string("[") + + parser_name(p.subject()) + + std::string("]"); + } + + template + inline std::string + parser_name(kleene_star const& p) + { + return std::string("kleene_star") + + std::string("[") + + parser_name(p.subject()) + + std::string("]"); + } + + template + inline std::string + parser_name(positive const& p) + { + return std::string("positive") + + std::string("[") + + parser_name(p.subject()) + + std::string("]"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from parser.hpp + template + inline std::string + parser_name(parser const& p) + { + return std::string("parser"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from primitives.hpp + template + inline std::string + parser_name(char_parser const &p) + { + return std::string("char_parser"); + } + + template + inline std::string + parser_name(chlit const &p) + { + return std::string("chlit(\'") + + std::string(1, p.ch) + + std::string("\')"); + } + + template + inline std::string + parser_name(range const &p) + { + return std::string("range(") + + std::string(1, p.first) + std::string(", ") + std::string(1, p.last) + + std::string(")"); + } + + template + inline std::string + parser_name(chseq const &p) + { + return std::string("chseq(\"") + + std::string(p.first, p.last) + + std::string("\")"); + } + + template + inline std::string + parser_name(strlit const &p) + { + return std::string("strlit(\"") + + std::string(p.seq.first, p.seq.last) + + std::string("\")"); + } + + inline std::string + parser_name(nothing_parser const&) + { + return std::string("nothing"); + } + + inline std::string + parser_name(epsilon_parser const&) + { + return std::string("epsilon"); + } + + inline std::string + parser_name(anychar_parser const&) + { + return std::string("anychar"); + } + + inline std::string + parser_name(alnum_parser const&) + { + return std::string("alnum"); + } + + inline std::string + parser_name(alpha_parser const&) + { + return std::string("alpha"); + } + + inline std::string + parser_name(cntrl_parser const&) + { + return std::string("cntrl"); + } + + inline std::string + parser_name(digit_parser const&) + { + return std::string("digit"); + } + + inline std::string + parser_name(graph_parser const&) + { + return std::string("graph"); + } + + inline std::string + parser_name(lower_parser const&) + { + return std::string("lower"); + } + + inline std::string + parser_name(print_parser const&) + { + return std::string("print"); + } + + inline std::string + parser_name(punct_parser const&) + { + return std::string("punct"); + } + + inline std::string + parser_name(blank_parser const&) + { + return std::string("blank"); + } + + inline std::string + parser_name(space_parser const&) + { + return std::string("space"); + } + + inline std::string + parser_name(upper_parser const&) + { + return std::string("upper"); + } + + inline std::string + parser_name(xdigit_parser const&) + { + return std::string("xdigit"); + } + + inline std::string + parser_name(eol_parser const&) + { + return std::string("eol"); + } + + inline std::string + parser_name(end_parser const&) + { + return std::string("end"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from rule.hpp + namespace impl { + struct node_registry + { + typedef std::pair rule_info; + typedef std::map rule_infos; + + std::string find_node(void const *r) + { + rule_infos::const_iterator cit = infos.find(r); + if (cit != infos.end()) + return (*cit).second.first; + return std::string(""); + } + + bool trace_node(void const *r) + { + rule_infos::const_iterator cit = infos.find(r); + if (cit != infos.end()) + return (*cit).second.second; + return BOOST_SPIRIT_DEBUG_TRACENODE; + } + + bool register_node(void const *r, char const *name_to_register, + bool trace_node) + { + if (infos.find(r) != infos.end()) + return false; + + return infos.insert(rule_infos::value_type(r, + rule_info(std::string(name_to_register), trace_node)) + ).second; + } + + bool unregister_node(void const *r) + { + if (infos.find(r) == infos.end()) + return false; + return (1 == infos.erase(r)); + } + + private: + rule_infos infos; + }; + + inline node_registry & + get_node_registry() + { + static node_registry node_infos; + return node_infos; + } + } // namespace impl + + template + inline std::string + parser_name(rule const& p) + { + return std::string("rule") + + std::string("(") + + impl::get_node_registry().find_node(&p) + + std::string(")"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from subrule.hpp + template + inline std::string + parser_name(subrule_list const &p) + { + return std::string("subrule_list") + + std::string("(") + + impl::get_node_registry().find_node(&p) + + std::string(")"); + } + + template + inline std::string + parser_name(subrule_parser const &p) + { + return std::string("subrule_parser") + + std::string("(") + + impl::get_node_registry().find_node(&p) + + std::string(")"); + } + + template + inline std::string + parser_name(subrule const &p) + { + BOOST_SPIRIT_SSTREAM stream; + stream << ID; + return std::string("subrule<") + + BOOST_SPIRIT_GETSTRING(stream) + + std::string(">(") + + impl::get_node_registry().find_node(&p) + + std::string(")"); + } + +/////////////////////////////////////////////////////////////////////////////// +// from grammar.hpp + template + inline std::string + parser_name(grammar const& p) + { + return std::string("grammar") + + std::string("(") + + impl::get_node_registry().find_node(&p) + + std::string(")"); + } + +/////////////////////////////////////////////////////////////////////////////// +// decide, if a node is to be traced or not + template + inline bool + trace_parser(rule const& p) + { + return impl::get_node_registry().trace_node(&p); + } + + template + inline bool + trace_parser(grammar const& p) + { + return impl::get_node_registry().trace_node(&p); + } + + template + bool + trace_parser(subrule const& p) + { + return impl::get_node_registry().trace_node(&p); + } + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#undef BOOST_SPIRIT_SSTREAM +#undef BOOST_SPIRIT_GETSTRING + +#endif // defined(BOOST_SPIRIT_DEBUG) + +#endif // !defined(BOOST_SPIRIT_PARSER_NAMES_IPP) diff --git a/include/boost/spirit/debug/minimal.hpp b/include/boost/spirit/debug/minimal.hpp new file mode 100644 index 000000000..d22619df0 --- /dev/null +++ b/include/boost/spirit/debug/minimal.hpp @@ -0,0 +1,84 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_MINIMAL_DEBUG_HPP) +#define BOOST_SPIRIT_MINIMAL_DEBUG_HPP + +#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP) +#error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/minimal.hpp" +#endif +/////////////////////////////////////////////////////////////////////////////// +// +// Minimum debugging tools support +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_DEBUG_OUT) +#define BOOST_SPIRIT_DEBUG_OUT std::cout +#endif + +/////////////////////////////////////////////////////////////////////////// +// +// BOOST_SPIRIT_DEBUG_FLAGS controls the level of diagnostics printed +// +/////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_DEBUG_FLAGS_NONE) +#define BOOST_SPIRIT_DEBUG_FLAGS_NONE 0x0000 // no diagnostics at all +#endif + +#if !defined(BOOST_SPIRIT_DEBUG_FLAGS_MAX) +#define BOOST_SPIRIT_DEBUG_FLAGS_MAX 0xFFFF // print maximal diagnostics +#endif + +#if !defined(BOOST_SPIRIT_DEBUG_FLAGS) +#define BOOST_SPIRIT_DEBUG_FLAGS SPIRIT_DEBUG_FLAGS_MAX +#endif + +#if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME) +#define BOOST_SPIRIT_DEBUG_PRINT_SOME 20 +#endif + +#if !defined(BOOST_SPIRIT_DEBUG_RULE) +#define BOOST_SPIRIT_DEBUG_RULE(r) +#endif // !defined(BOOST_SPIRIT_DEBUG_RULE) + +#if !defined(BOOST_SPIRIT_DEBUG_NODE) +#define BOOST_SPIRIT_DEBUG_NODE(r) +#endif // !defined(BOOST_SPIRIT_DEBUG_NODE) + +#if !defined(BOOST_SPIRIT_DEBUG_GRAMMAR) +#define BOOST_SPIRIT_DEBUG_GRAMMAR(r) +#endif // !defined(BOOST_SPIRIT_DEBUG_GRAMMAR) + +#if !defined(BOOST_SPIRIT_TRACE_RULE) +#define BOOST_SPIRIT_TRACE_RULE(r, t) +#endif // !defined(BOOST_SPIRIT_TRACE_RULE) + +#if !defined(BOOST_SPIRIT_TRACE_NODE) +#define BOOST_SPIRIT_TRACE_NODE(r, t) +#endif // !defined(BOOST_SPIRIT_TRACE_NODE) + +#if !defined(BOOST_SPIRIT_TRACE_GRAMMAR) +#define BOOST_SPIRIT_TRACE_GRAMMAR(r, t) +#endif // !defined(BOOST_SPIRIT_TRACE_GRAMMAR) + +#if !defined(BOOST_SPIRIT_TRACE_RULE_NAME) +#define BOOST_SPIRIT_TRACE_RULE_NAME(r, n, t) +#endif // !defined(BOOST_SPIRIT_TRACE_RULE_NAME) + +#if !defined(BOOST_SPIRIT_TRACE_NODE_NAME) +#define BOOST_SPIRIT_TRACE_NODE_NAME(r, n, t) +#endif // !defined(BOOST_SPIRIT_TRACE_NODE_NAME) + +#if !defined(BOOST_SPIRIT_TRACE_GRAMMAR_NAME) +#define BOOST_SPIRIT_TRACE_GRAMMAR_NAME(r, n, t) +#endif // !defined(BOOST_SPIRIT_TRACE_GRAMMAR_NAME) + +#endif // !defined(BOOST_SPIRIT_MINIMAL_DEBUG_HPP) diff --git a/include/boost/spirit/debug/parser_names.hpp b/include/boost/spirit/debug/parser_names.hpp new file mode 100644 index 000000000..308de83f7 --- /dev/null +++ b/include/boost/spirit/debug/parser_names.hpp @@ -0,0 +1,243 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_PARSER_NAMES_HPP) +#define BOOST_SPIRIT_PARSER_NAMES_HPP + +#if defined(BOOST_SPIRIT_DEBUG) + +////////////////////////////////// +#include "boost/spirit/core.hpp" + +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// Declaration of helper functions, which return the name of a concrete +// parser instance. The functions are specialized on the parser types. The +// functions declared in this file are for the predefined parser types from +// the Spirit core library only, so additional functions might be provided as +// needed. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// from actions.hpp + template + std::string + parser_name(action const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from directives.hpp + template + std::string + parser_name(contiguous const& p); + + template + std::string + parser_name(inhibit_case const& p); + + template + std::string + parser_name(longest_alternative const& p); + + template + std::string + parser_name(shortest_alternative const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from grammar.hpp + template + std::string + parser_name(grammar const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from numerics.hpp + template + std::string + parser_name(uint_parser const& p); + + template + std::string + parser_name(int_parser const& p); + + template + std::string + parser_name(real_parser const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from operators.hpp + template + std::string + parser_name(sequence const& p); + + template + std::string + parser_name(sequential_or const& p); + + template + std::string + parser_name(alternative const& p); + + template + std::string + parser_name(intersection const& p); + + template + std::string + parser_name(difference const& p); + + template + std::string + parser_name(exclusive_or const& p); + + template + std::string + parser_name(optional const& p); + + template + std::string + parser_name(kleene_star const& p); + + template + std::string + parser_name(positive const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from parser.hpp + template + std::string + parser_name(parser const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from primitives.hpp + template + std::string + parser_name(char_parser const &p); + + template + std::string + parser_name(chlit const &p); + + template + std::string + parser_name(range const &p); + + template + std::string + parser_name(chseq const &p); + + template + std::string + parser_name(strlit const &p); + + std::string + parser_name(nothing_parser const &p); + + std::string + parser_name(epsilon_parser const &p); + + std::string + parser_name(anychar_parser const &p); + + std::string + parser_name(alnum_parser const &p); + + std::string + parser_name(alpha_parser const &p); + + std::string + parser_name(cntrl_parser const &p); + + std::string + parser_name(digit_parser const &p); + + std::string + parser_name(graph_parser const &p); + + std::string + parser_name(lower_parser const &p); + + std::string + parser_name(print_parser const &p); + + std::string + parser_name(punct_parser const &p); + + std::string + parser_name(blank_parser const &p); + + std::string + parser_name(space_parser const &p); + + std::string + parser_name(upper_parser const &p); + + std::string + parser_name(xdigit_parser const &p); + + std::string + parser_name(eol_parser const &p); + + std::string + parser_name(end_parser const &p); + +/////////////////////////////////////////////////////////////////////////////// +// from rule.hpp + template + std::string + parser_name(rule const& p); + +/////////////////////////////////////////////////////////////////////////////// +// from subrule.hpp + template + std::string + parser_name(subrule_list const &p); + + template + std::string + parser_name(subrule_parser const &p); + + template + std::string + parser_name(subrule const &p); + +/////////////////////////////////////////////////////////////////////////////// +// from chset.hpp + +/////////////////////////////////////////////////////////////////////////////// +// +// Decide, if a node is to be traced or not +// +/////////////////////////////////////////////////////////////////////////////// + template + bool + trace_parser(rule const& p); + + template + bool + trace_parser(grammar const& p); + + template + bool + trace_parser(subrule const& p); + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +////////////////////////////////// +#if !defined(BOOST_SPIRIT_PARSER_NAMES_IPP) +#include "boost/spirit/debug/impl/parser_names.ipp" +#endif + +#endif // defined(BOOST_SPIRIT_DEBUG) + +#endif // !defined(BOOST_SPIRIT_PARSER_NAMES_HPP) diff --git a/include/boost/spirit/dynamic.hpp b/include/boost/spirit/dynamic.hpp new file mode 100644 index 000000000..13ca935a1 --- /dev/null +++ b/include/boost/spirit/dynamic.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002 Juan Carlos Arevalo-Baeza + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_DYNAMIC_HPP +#define BOOST_SPIRIT_DYNAMIC_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// Master header for Spirit.Dynamic +// +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_IF_HPP) +#include "boost/spirit/dynamic/if.hpp" +#endif + +#if !defined(BOOST_SPIRIT_FOR_HPP) +#include "boost/spirit/dynamic/for.hpp" +#endif + +#if !defined(BOOST_SPIRIT_WHILE_HPP) +#include "boost/spirit/dynamic/while.hpp" +#endif + +//////////////////////////////////////////////////////////////////////////////// +#endif // BOOST_SPIRIT_DYNAMIC_HPP diff --git a/include/boost/spirit/dynamic/for.hpp b/include/boost/spirit/dynamic/for.hpp new file mode 100644 index 000000000..57d731d07 --- /dev/null +++ b/include/boost/spirit/dynamic/for.hpp @@ -0,0 +1,203 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_FOR_HPP +#define BOOST_SPIRIT_FOR_HPP +//////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#include "boost/spirit/core/composite/composite.hpp" +#endif + +#if !defined(BOOST_SPIRIT_CONDITIONS_IPP) +#include "boost/spirit/dynamic/impl/conditions.ipp" +#endif +//////////////////////////////////////////////////////////////////////////////// + +namespace boost { namespace spirit +{ + namespace impl + { + + template + struct for_functor : private subject_type::type + { + typedef typename subject_type::type base_t; + typedef typename boost::call_traits::param_type param_t; + typedef typename base_t::return_t return_t; + + for_functor(param_t f) : base_t(f) {} + for_functor() : base_t() {} + return_t get() const { return base_t::get(); } + }; + + template + struct for_init_functor : for_functor + { + typedef for_functor base_t; + typedef typename base_t::param_t param_t; + + for_init_functor(param_t f) : base_t(f) {} + for_init_functor() : base_t() {} + void init() const { return base_t::get()(); } + }; + + template + struct for_step_functor : for_functor + { + typedef for_functor base_t; + typedef typename base_t::param_t param_t; + + for_step_functor(param_t f) : base_t(f) {} + for_step_functor() : base_t() {} + void step() const { return base_t::get()(); } + }; + + ////////////////////////////////// + // for_parser + template + < + typename InitF, typename CondT, typename StepF, + typename ParserT + > + struct for_parser + : private for_init_functor + , private for_step_functor + , private condition_evaluator + , public unary + < + ParserT, + parser< for_parser > + > + { + typedef for_parser< InitF, CondT, StepF, ParserT > self_t; + typedef condition_evaluator eval_t; + typedef unary< ParserT, parser< self_t > > base_t; + + + ////////////////////////////// + // constructor, saves init, condition and step functors + // for later use the parse member function + for_parser + ( + InitF const &i, CondT const &c, StepF const &s, + ParserT const &p + ) + : for_init_functor(i) + , for_step_functor(s) + , eval_t(c) + , base_t(p) + { } + + for_parser() + : for_init_functor() + , for_step_functor() + , eval_t() + , base_t() + {} + + ////////////////////////////// + // parse member function + template + typename parser_result::type + parse(ScannerT const &scan) const + { + typedef typename parser_result::type result_t; + typedef typename parser_result::type sresult_t; + + typename ScannerT::iterator_t save(scan.first); + + int length = 0; + int eval_length = 0; + + init(); + while ((eval_length = evaluate(scan))>=0) + { + length += eval_length; + sresult_t tmp(this->subject().parse(scan)); + if (tmp) + { + length+=tmp.length(); + } + else + { + return scan.no_match(); + } + step(); + } + return scan.create_match(length, nil_t(), save, scan.first); + } + }; + + ////////////////////////////////// + // for_parser_gen generates takes the body parser in brackets + // and returns the for_parser + template + struct for_parser_gen + { + for_parser_gen(InitF const &i, CondT const &c, StepF const &s) + : init(i) + , condition(c) + , step(s) + {} + + typedef ::boost::spirit::as_parser cond_as_parser_t; + typedef typename cond_as_parser_t::type cond_p; + + template + for_parser + < + InitF, cond_p, StepF, + typename ::boost::spirit::as_parser::type + > + operator[](ParserT const &p) const + { + typedef ::boost::spirit::as_parser as_parser_t; + typedef typename as_parser_t::type parser_t; + + typedef char assert_argument_must_be_a_parser + [::boost::spirit::is_parser::value]; + + return for_parser + ( + init, + cond_as_parser_t::convert(condition), + step, + as_parser_t::convert(p) + ); + } + + InitF const &init; + CondT const &condition; + StepF const &step; + }; + } // namespace impl + + ////////////////////////////// + // for_p, returns for-parser generator + // Usage: spirit::for_p(init-ftor, condition, step-ftor)[body] + template + < + typename InitF, typename ConditionT, typename StepF + > + impl::for_parser_gen + for_p(InitF const &init_f, ConditionT const &condition, StepF const &step_f) + { + return impl::for_parser_gen + (init_f, condition, step_f); + } + +}} // namespace boost::spirit + +#endif // BOOST_SPIRIT_FOR_HPP diff --git a/include/boost/spirit/dynamic/if.hpp b/include/boost/spirit/dynamic/if.hpp new file mode 100644 index 000000000..92dc6cb29 --- /dev/null +++ b/include/boost/spirit/dynamic/if.hpp @@ -0,0 +1,207 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002 Juan Carlos Arevalo-Baeza + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_IF_HPP +#define BOOST_SPIRIT_IF_HPP + +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#include "boost/spirit/core/composite/composite.hpp" +#endif + +#if !defined(BOOST_SPIRIT_CONDITIONS_IPP) +#include "boost/spirit/dynamic/impl/conditions.ipp" +#endif + +namespace boost { namespace spirit { + + namespace impl { + + ////////////////////////////////// + // if-else-parser, holds two alternative parsers and a conditional functor + // that selects between them. + template + struct if_else_parser + : public condition_evaluator + , public binary + < + ParserT_true, + ParserT_false, + parser > + > + { + typedef if_else_parser self_t; + typedef condition_evaluator eval_t; + typedef binary >base_t; + typedef CondT condition_t; + + if_else_parser + ( + ParserT_true const& p_true, + ParserT_false const& p_false, + CondT const& cond_ + ) + : eval_t(cond_) + , base_t(p_true, p_false) + { } + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + if (evaluate(scan) >= 0) + { + return this->left().parse(scan); + } + else + { + return this->right().parse(scan); + } + } + }; + + ////////////////////////////////// + // if-else-parser generator, takes the false-parser in brackets + // and returns the if-else-parser. + template + struct if_else_parser_gen + { + if_else_parser_gen(ParserT_true const& p_true_, CondT const& cond_) + : p_true(p_true_) + , cond(cond_) {} + + template + if_else_parser + < + ParserT_true, + typename ::boost::spirit::as_parser::type, + CondT + > + operator[](ParserT_false const& subject) const + { + typedef ::boost::spirit::as_parser as_parser_t; + typedef typename as_parser_t::type parser_t; + + typedef char assert_argument_must_be_a_parser + [::boost::spirit::is_parser::value]; + + return if_else_parser + ( + p_true, + as_parser_t::convert(subject), + cond + ); + } + + //typename ParserT_true::embed_t p_true; + ParserT_true const &p_true; + CondT const &cond; + }; + + ////////////////////////////////// + // if-parser, conditionally runs a parser is a functor condition is true. + // If the condition is fales, it fails the parse. + // It can optionally become an if-else-parser through the member else_p. + template + struct if_parser + : public condition_evaluator + , public unary > > + { + typedef if_parser self_t; + typedef condition_evaluator eval_t; + typedef unary > base_t; + + if_parser(ParserT const& p, CondT const& cond_) + : eval_t(cond_) + , base_t(p) + , else_p(p, cond_) + {} + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + if (evaluate(scan) >= 0) + { + return this->subject().parse(scan); + } + return scan.empty_match(); + } + + if_else_parser_gen else_p; + }; + + ////////////////////////////////// + // if-parser generator, takes the true-parser in brackets and returns the + // if-parser. + template + struct if_parser_gen + { + typedef ::boost::spirit::as_parser c_as_parser_t; + typedef typename c_as_parser_t::type condition_t; + + if_parser_gen(CondT const& cond_) : cond(cond_) {} + + template + if_parser + < + typename ::boost::spirit::as_parser::type, + condition_t + > + operator[](ParserT const& subject) const + { + typedef ::boost::spirit::as_parser p_as_parser_t; + typedef typename p_as_parser_t::type parser_t; + + typedef char assert_argument_must_be_a_parser + [::boost::spirit::is_parser::value]; + + return if_parser + ( + p_as_parser_t::convert(subject), + c_as_parser_t::convert(cond) + ); + } + + CondT const &cond; + }; + +} // namespace impl + +////////////////////////////////// +// if_p function, returns "if" parser generator + +template +impl::if_parser_gen +if_p(CondT const& cond) +{ + return impl::if_parser_gen(cond); +} + +}} // namespace boost::spirit + +#endif // BOOST_SPIRIT_IF_HPP diff --git a/include/boost/spirit/dynamic/impl/conditions.ipp b/include/boost/spirit/dynamic/impl/conditions.ipp new file mode 100644 index 000000000..455172790 --- /dev/null +++ b/include/boost/spirit/dynamic/impl/conditions.ipp @@ -0,0 +1,126 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_CONDITIONS_IPP +#define BOOST_SPIRIT_CONDITIONS_IPP + +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_SPIRIT_PARSER_TRAITS_HPP) +#include "boost/spirit/core/meta/parser_traits.hpp" +#endif + +#if !defined(BOOST_SPIRIT_EPSILON_HPP) +#include "boost/spirit/core/composite/epsilon.hpp" +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl { + +/////////////////////////////////////////////////////////////////////////////// +// +// condition evaluation +// +/////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////// + // condition_parser_selector, decides which parser to use for a condition + // If the template argument is a parser then that parser is used. + // If the template argument is a functor then a condition parser using + // the functor is chosen + struct select_identity + { + template + struct result + { + typedef ConditionT type; + }; + }; + + struct select_condition_parser + { + template + struct result + { + typedef condition_parser type; + }; + }; + + template + struct condition_parser_selector + { + private: + + typedef + typename if_t< + bool_t< ::boost::spirit::is_parser::value >, + select_identity, + select_condition_parser + >::type + func_; + public: + + typedef typename func_::template result::type type; + typedef typename type::embed_t embed_t; + }; + + ////////////////////////////////// + // condition_evaluator, uses a parser to check wether a condition is met + // takes a parser or a functor that can be evaluated in boolean context + // as template parameter. + template + struct condition_evaluator + : private subject_type + < + typename condition_parser_selector::embed_t, + nil_t + >::type + { + typedef condition_parser_selector selector_t; + typedef typename selector_t::type selected_t; + typedef typename selector_t::embed_t cond_embed_t; + typedef typename subject_type::type base_t; + typedef typename base_t::param_t param_t; + typedef typename base_t::return_t return_t; + + condition_evaluator(param_t s) : base_t(s) {} + condition_evaluator() : base_t() {} + + ///////////////////////////// + // evaluate, checks wether condition is met + // returns length of a match or a negative number for no-match + template + int + evaluate(ScannerT const &scan) const + { + typedef typename ScannerT::iterator_t iterator_t; + typedef typename parser_result::type cres_t; + iterator_t save(scan.first); + cres_t result = condition().parse(scan); + if (!result) // reset the position if evaluation + scan.first = save; // fails. + return result.length(); + } + + ///////////////////////////// + // condition + // returns the parser used for the condition + inline return_t condition() const + { + return base_t::get(); + } + }; + +/////////////////////////////////////////////////////////////////////////////// + } // namespace impl + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/dynamic/while.hpp b/include/boost/spirit/dynamic/while.hpp new file mode 100644 index 000000000..b9a240451 --- /dev/null +++ b/include/boost/spirit/dynamic/while.hpp @@ -0,0 +1,229 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002-2003 Joel de Guzman + Copyright (c) 2002-2003 Martin Wille + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_WHILE_HPP +#define BOOST_SPIRIT_WHILE_HPP + +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#include "boost/spirit/core/composite/composite.hpp" +#endif + +#if !defined(BOOST_SPIRIT_CONDITIONS_IPP) +#include "boost/spirit/dynamic/impl/conditions.ipp" +#endif + +//////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl { + + ////////////////////////////////// + // while parser + // object are created by while_parser_gen and do_parser_gen + template + struct while_parser + : public condition_evaluator + , public unary // the parent stores a copy of the body parser + < + ParserT, + parser > + > + { + typedef unary + < + ParserT, + parser > + > parent_t; + + typedef while_parser self_t; + typedef condition_evaluator cond_t; + typedef CondT condition_t; + + + ////////////////////////////// + // constructor, saves condition and body parser + while_parser(ParserT const &p_body, CondT const &cond_) + : cond_t(cond_) + , parent_t(p_body) + {} + + ////////////////////////////// + // result type computer. + template + struct result + { + typedef typename match_result + ::type type; + }; + + ////////////////////////////// + // parse member function + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type sresult_t; + typedef typename ScannerT::iterator_t iterator_t; + + iterator_t save(scan.first); + int length = 0; + int eval_length = 0; + + bool dont_check_condition = is_do_parser; + + while (dont_check_condition || (eval_length=evaluate(scan))>=0) + { + dont_check_condition = false; + length += eval_length; + sresult_t tmp(this->subject().parse(scan)); + if (tmp) + { + length+=tmp.length(); + } + else + { + return scan.no_match(); + } + } + return scan.create_match(length, nil_t(), save, scan.first); + } + }; + + ////////////////////////////////// + // while-parser generator, takes the body-parser in brackets + // and returns the actual while-parser. + template + struct while_parser_gen + { + typedef typename ::boost::spirit::as_parser::type condition_t; + + ////////////////////////////// + // constructor, saves the condition for use by operator[] + while_parser_gen(CondT const& cond_) : cond(cond_) {} + + ////////////////////////////// + // operator[] returns the actual while-parser object + template + while_parser + < + typename ::boost::spirit::as_parser::type, + condition_t, + false + > + operator[](ParserT const &subject) const + { + typedef typename ::boost::spirit::as_parser::type parser_t; + + typedef char assert_argument_must_be_a_parser + [::boost::spirit::is_parser::value]; + + return while_parser + ( + ::boost::spirit::as_parser::convert(subject), + ::boost::spirit::as_parser::convert(cond) + ); + } + private: + + ////////////////////////////// + // the condition is stored by reference here. + // this should not cause any harm since object of type + // while_parser_gen<> are only used as temporaries + // the while-parser object constructed by the operator[] + // stores a copy of the condition. + CondT const &cond; + }; + + ////////////////////////////////// + // do-while-parser generator, takes the condition as + // parameter to while_p member function and returns the + // actual do-while-parser. + template + struct do_while_parser_gen + { + ////////////////////////////// + // constructor. saves the body parser for use by while_p. + explicit do_while_parser_gen(ParserT const &body_parser) + : body(body_parser) + {} + + ////////////////////////////// + // while_p returns the actual while-parser object + template + while_parser + < + ParserT, + typename ::boost::spirit::as_parser::type, + true + > + while_p(CondT cond) const + { + typedef typename ::boost::spirit::as_parser cond_as_parser_t; + typedef typename cond_as_parser_t::type condition_t; + + return while_parser + (body, ::boost::spirit::as_parser::convert(cond)); + } + private: + + ////////////////////////////// + // the body is stored by reference here + // this should not cause any harm since object of type + // do_while_parser_gen<> are only used as temporaries + // the while-parser object constructed by the while_p + // member function stores a copy of the body parser. + ParserT const &body; + }; + + struct do_parser_gen + { + inline do_parser_gen() {} + + template + impl::do_while_parser_gen + < + typename ::boost::spirit::as_parser::type + > + operator[](ParserT const& body) const + { + typedef typename ::boost::spirit::as_parser::type parser_t; + + typedef char assert_argument_must_be_a_parser + [::boost::spirit::is_parser::value]; + + return impl::do_while_parser_gen + (::boost::spirit::as_parser::convert(body)); + } + }; +} // namespace impl + +////////////////////////////////// +// while_p function, while-parser generator +// Usage: spirit::while_p(Condition)[Body] +template +impl::while_parser_gen +while_p(CondT const& cond) +{ + return impl::while_parser_gen(cond); +} + +////////////////////////////////// +// do_p functor, do-while-parser generator +// Usage: spirit::do_p[Body].while_p(Condition) +impl::do_parser_gen const do_p = impl::do_parser_gen(); + +}} // namespace boost::spirit + +#endif // BOOST_SPIRIT_WHILE_HPP diff --git a/include/boost/spirit/error_handling.hpp b/include/boost/spirit/error_handling.hpp new file mode 100644 index 000000000..8de762cbc --- /dev/null +++ b/include/boost/spirit/error_handling.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_ERROR_HANDLING_MAIN_HPP) +#define BOOST_SPIRIT_ERROR_HANDLING_MAIN_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// Master header for Spirit.ErrorHandling +// +/////////////////////////////////////////////////////////////////////////////// + +#include "boost/spirit/error_handling/exceptions.hpp" + +#endif // !defined(BOOST_SPIRIT_ERROR_HANDLING_MAIN_HPP) diff --git a/include/boost/spirit/error_handling/Makefile.am b/include/boost/spirit/error_handling/Makefile.am new file mode 100644 index 000000000..2c807df4d --- /dev/null +++ b/include/boost/spirit/error_handling/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = exceptions.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/error_handling diff --git a/include/boost/spirit/error_handling/exceptions.hpp b/include/boost/spirit/error_handling/exceptions.hpp new file mode 100644 index 000000000..72edaf1e7 --- /dev/null +++ b/include/boost/spirit/error_handling/exceptions.hpp @@ -0,0 +1,345 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_EXCEPTIONS_HPP +#define BOOST_SPIRIT_EXCEPTIONS_HPP + +#if !defined(BOOST_SPIRIT_PARSER_HPP) +#include "boost/spirit/core/parser.hpp" +#endif + +#if !defined(BOOST_SPIRIT_COMPOSITE_HPP) +#include "boost/spirit/core/composite/composite.hpp" +#endif + +#include + +namespace boost { namespace spirit { + + /////////////////////////////////////////////////////////////////////////// + // + // parser_error_base class + // + // This is the base class of parser_error (see below). This may be + // used to catch any type of parser error. + // + // This exception shouldn't propagate outside the parser. However to + // avoid quirks of many platforms/implementations which fall outside + // the C++ standard, we derive parser_error_base from std::exception + // to allow a single catch handler to catch all exceptions. + // + /////////////////////////////////////////////////////////////////////////// + class parser_error_base : public std::exception + { + protected: + + parser_error_base() {} + virtual ~parser_error_base() throw() {} + parser_error_base(parser_error_base const&) {} + parser_error_base& operator=(parser_error_base const&) + { return *this; } + }; + + /////////////////////////////////////////////////////////////////////////// + // + // parser_error class + // + // Generic parser exception class. This is the base class for all + // parser exceptions. The exception holds the iterator position + // where the error was encountered in its member variable "where". + // The parser_error also holds information regarding the error + // (error descriptor) in its member variable "descriptor". + // + // The throw_ function creates and throws a parser_error given + // an iterator and an error descriptor. + // + /////////////////////////////////////////////////////////////////////////// + template + struct parser_error : public parser_error_base + { + typedef ErrorDescrT error_descr_t; + typedef IteratorT iterator_t; + + parser_error(IteratorT where_, ErrorDescrT descriptor_) + : where(where_), descriptor(descriptor_) {} + + virtual + ~parser_error() throw() {} + + virtual const char* + what() const throw() + { return "boost::spirit::parser_error"; } + + IteratorT const where; + ErrorDescrT const descriptor; + }; + + ////////////////////////////////// + template + inline void + throw_(IteratorT where, ErrorDescrT descriptor) + { + throw parser_error(where, descriptor); + } + + /////////////////////////////////////////////////////////////////////////// + // + // assertive_parser class + // + // An assertive_parser class is a parser that throws an exception + // in response to a parsing failure. The assertive_parser throws a + // parser_error exception rather than returning an unsuccessful + // match to signal that the parser failed to match the input. + // + /////////////////////////////////////////////////////////////////////////// + template + struct assertive_parser + : public unary > > + { + typedef assertive_parser self_t; + typedef unary > base_t; + typedef unary_parser_category parser_category_t; + + assertive_parser(ParserT const& parser, ErrorDescrT descriptor) + : base_t(parser), descriptor(descriptor) {} + + template + struct result + { typedef typename parser_result::type type; }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + typedef typename ScannerT::iterator_t iterator_t; + + result_t hit = this->subject().parse(scan); + if (!hit) + { + #ifndef __BORLANDC__ + throw_(scan.first, descriptor); + #else + throw_(scan.first, const_cast(descriptor)); + #endif + } + return hit; + } + + ErrorDescrT descriptor; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // assertion class + // + // assertive_parsers are never instantiated directly. The assertion + // class is used to indirectly create an assertive_parser object. + // Before declaring the grammar, we declare some assertion objects. + // Examples: + // + // enum Errors + // { + // program_expected, begin_expected, end_expected + // }; + // + // assertion expect_program(program_expected); + // assertion expect_begin(begin_expected); + // assertion expect_end(end_expected); + // + // Now, we can use these assertions as wrappers around parsers: + // + // expect_end(str_p("end")) + // + // Take note that although the example uses enums to hold the + // information regarding the error (error desccriptor), we are free + // to use other types such as integers and strings. Enums are + // convenient for error handlers to easily catch since C++ treats + // enums as unique types. + // + /////////////////////////////////////////////////////////////////////////// + template + struct assertion + { + assertion(ErrorDescrT descriptor_) + : descriptor(descriptor_) {} + + template + assertive_parser + operator()(ParserT const& parser) const + { return assertive_parser(parser, descriptor); } + + ErrorDescrT descriptor; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // error_status + // + // Where T is an attribute type compatible with the match attribute + // of the fallback_parser's subject (defaults to nil_t). The class + // error_status reports the result of an error handler (see + // fallback_parser). result can be one of: + // + // fail: quit and fail (return a no_match) + // retry: attempt error recovery, possibly moving the scanner + // accept: force success returning a matching length, moving + // the scanner appropriately and returning an attribute + // value + // rethrow: rethrows the error. + // + /////////////////////////////////////////////////////////////////////////// + template + struct error_status + { + enum result_t { fail, retry, accept, rethrow }; + + error_status( + result_t result_ = fail, + int length = -1, + T const& value_ = T()) + : result(result_), length(length), value(value_) {} + + result_t result; + int length; + T value; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // fallback_parser class + // + // Handles exceptions of type parser_error + // thrown somewhere inside its embedded ParserT object. The class + // sets up a try block before delegating parsing to its subject. + // When an exception is caught, the catch block then calls the + // HandlerT object. HandlerT may be a function or a functor (with + // an operator() member function) compatible with the interface: + // + // error_status + // handler(ScannerT const& scan, ErrorT error); + // + // Where scan points to the scanner state prior to parsing and error + // is the error that arose (see parser_error). The handler must + // return an error_status object (see above). + // + /////////////////////////////////////////////////////////////////////////// + namespace impl + { + template + RT fallback_parser_parse(ParserT const& p, ScannerT const& scan); + } + + template + struct fallback_parser + : public unary > > + { + typedef fallback_parser + self_t; + typedef ErrorDescrT + error_descr_t; + typedef unary > + base_t; + typedef unary_parser_category + parser_category_t; + + fallback_parser(ParserT const& parser, HandlerT const& handler_) + : base_t(parser), handler(handler_) {} + + template + struct result + { typedef typename parser_result::type type; }; + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::fallback_parser_parse(*this, scan); + } + + HandlerT handler; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // guard class + // + // fallback_parser objects are not instantiated directly. The guard + // class is used to indirectly create a fallback_parser object. + // guards are typically predeclared just like assertions (see the + // assertion class above; the example extends the previous example + // introduced in the assertion class above): + // + // guard my_guard; + // + // Errors, in this example is the error descriptor type we want to + // detect; This is essentially the ErrorDescrT template parameter + // of the fallback_parser class. + // + // my_guard may now be used in a grammar declaration as: + // + // my_guard(p)[h] + // + // where p is a parser, h is a function or functor compatible with + // fallback_parser's HandlerT (see above). + // + /////////////////////////////////////////////////////////////////////////// + template + struct guard; + + template + struct guard_gen : public unary + { + typedef guard parser_generator_t; + typedef unary_parser_category parser_category_t; + + guard_gen(ParserT const& p) + : unary(p) {} + + template + fallback_parser + operator[](HandlerT const& handler) const + { + return fallback_parser + (this->subject(), handler); + } + }; + + template + struct guard + { + template + struct result { + + typedef guard_gen type; + }; + + template + static guard_gen + generate(ParserT const& parser) + { + return guard_gen(parser); + } + + template + guard_gen + operator()(ParserT const& parser) const + { + return guard_gen(parser); + } + }; + +}} // namespace boost::spirit + +#include "boost/spirit/error_handling/impl/exceptions.ipp" +#endif + diff --git a/include/boost/spirit/error_handling/impl/Makefile.am b/include/boost/spirit/error_handling/impl/Makefile.am new file mode 100644 index 000000000..1bda669e6 --- /dev/null +++ b/include/boost/spirit/error_handling/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = exceptions.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/error_handling/impl diff --git a/include/boost/spirit/error_handling/impl/exceptions.ipp b/include/boost/spirit/error_handling/impl/exceptions.ipp new file mode 100644 index 000000000..8c9778bea --- /dev/null +++ b/include/boost/spirit/error_handling/impl/exceptions.ipp @@ -0,0 +1,85 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_EXCEPTIONS_IPP +#define BOOST_SPIRIT_EXCEPTIONS_IPP + +namespace boost { namespace spirit { namespace impl { + +#ifdef __BORLANDC__ + template + typename parser_result::type + fallback_parser_helper(ParserT const& subject, ScannerT const& scan); +#endif + + template + RT fallback_parser_parse(ParserT const& p, ScannerT const& scan) + { + typedef typename ScannerT::iterator_t iterator_t; + typedef typename RT::attr_t attr_t; + typedef error_status error_status_t; + typedef typename ParserT::error_descr_t error_descr_t; + + iterator_t save = scan.first; + error_status_t hr(error_status_t::retry); + + while (hr.result == error_status_t::retry) + { + try + { + #ifndef __BORLANDC__ + return p.subject().parse(scan); + #else + return impl::fallback_parser_helper(p, scan); + #endif + } + + catch (parser_error error) + { + scan.first = save; + hr = p.handler(scan, error); + switch (hr.result) + { + case error_status_t::fail: + return scan.no_match(); + case error_status_t::accept: + return scan.create_match + (hr.length, hr.value, save, scan.first); + case error_status_t::rethrow: + throw; + default: + continue; + } + } + } + return scan.no_match(); + } + +/////////////////////////////////////////////////////////////////////////// +// +// Borland does not like calling the subject directly in the try block. +// Removing the #ifdef __BORLANDC__ code makes Borland complain that +// some variables and types cannot be found in the catch block. Weird! +// +/////////////////////////////////////////////////////////////////////////// +#ifdef __BORLANDC__ + + template + typename parser_result::type + fallback_parser_helper(ParserT const& p, ScannerT const& scan) + { return p.subject().parse(scan); } + +#endif + +}}} // namespace boost::spirit::impl + +/////////////////////////////////////////////////////////////////////////////// +#endif + diff --git a/include/boost/spirit/iterator.hpp b/include/boost/spirit/iterator.hpp new file mode 100644 index 000000000..d14466c26 --- /dev/null +++ b/include/boost/spirit/iterator.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Daniel Nuffer + Copyright (c) 2002 Jeff Westfahl + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_ITERATOR_MAIN_HPP) +#define BOOST_SPIRIT_ITERATOR_MAIN_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// Master header for Spirit.Iterators +// +/////////////////////////////////////////////////////////////////////////////// + +#include "boost/spirit/iterator/file_iterator.hpp" +#include "boost/spirit/iterator/fixed_size_queue.hpp" +#include "boost/spirit/iterator/position_iterator.hpp" + +#include "boost/config.hpp" +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300) +#include "boost/spirit/iterator/multi_pass.hpp" +#endif + +#endif // !defined(BOOST_SPIRIT_ITERATOR_MAIN_HPP) diff --git a/include/boost/spirit/iterator/Makefile.am b/include/boost/spirit/iterator/Makefile.am new file mode 100644 index 000000000..5b871c92b --- /dev/null +++ b/include/boost/spirit/iterator/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = file_iterator.hpp fixed_size_queue.hpp multi_pass.hpp position_iterator.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/iterator diff --git a/include/boost/spirit/iterator/file_iterator.hpp b/include/boost/spirit/iterator/file_iterator.hpp new file mode 100644 index 000000000..c9877441d --- /dev/null +++ b/include/boost/spirit/iterator/file_iterator.hpp @@ -0,0 +1,304 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002 Jeff Westfahl + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ + +// This code is inspired by FILEiter.h by Stephen Cleary, and is basically a +// superset of the functionality provided there. FILEiter.h is available from +// http://groups.yahoo.com/group/boost/files/2000/IOGlue/IOGlue.zip and has +// the following copyright notice: + +// FILEiter: Input and Output iterators for FILE * objects + +// (C) Copyright Stephen Cleary 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// +// Notes on 64-bit file access: +// +// The following systems are known to have 64-bit lseek support. Note that on +// Linux, you must define _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE. This +// should be done on the compiler command line so that it is used globally. +// +// MSVC (tested on VC6 SP4) +// MINGW (tested on recent CYGWIN) +// Linux (recent, tested on Mandrake Linux 8.2 X86 and PPC) +// Intel C++ (untested, but it uses system headers and libraries) +// +// The following systems are known to not have 64-bit lseek support, and do +// not seem to export any 64-bit file access functions. This may or may not +// be a problem for you. I know that I don't have a lot of files larger than +// 2GB laying around on my hard drives, except for testing. But, you never +// can tell how people might want to use your software. +// +// Borland 5.5.1 +// CYGWIN +// +// Basically, this iterator should work fine on any files < 2GB in size on any +// system. + +#if !defined FILE_ITERATOR_HPP +#define FILE_ITERATOR_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +namespace impl { + +// Systems that don't have a 64-bit off_t, but do have a 64-bit lseek +#if defined BOOST_MSVC \ + || defined __MINGW32_VERSION \ + || defined BOOST_INTEL_CXX_VERSION + + // Always use 64-bit file access + typedef __int64 off_t; + +#else + + // Use the system defined offset size + using ::off_t; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// warning C4284: return type for 'boost::spirit::file_iterator::operator ->' +// is 'const char *' +#if defined BOOST_MSVC +#pragma warning ( push ) +#pragma warning ( disable : 4284 ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +template +class file_iterator + : public boost::iterator < + std::random_access_iterator_tag, + CharT, + impl::off_t, + CharT const *, + CharT const & + > +{ + public: + + // Iterator traits + typedef impl::off_t difference_type; + typedef CharT value_type; + typedef CharT const * pointer; + typedef CharT const & reference; + + // Standard constructor. Opens the specified file. + explicit file_iterator (char const * pFilename); + + // Destructor + ~file_iterator (); + + // Make an end of file iterator for the current file + file_iterator make_end (); + + // Returns false if no file is associated with this iterator + operator bool () const; + + // Returns file size in bytes + difference_type size () const; + + // + // Default Constructible + // + + // Default constructor + file_iterator (); + + // + // Assignable + // + + // Copy constructor + file_iterator (file_iterator const & rCopyMe); + + // Assignment operator + file_iterator & operator = (file_iterator const & rAssignMe); + + // Swap + void swap (file_iterator & rA, file_iterator & rB); + + // + // Trivial Iterator + // + + // Dereference + // + // Note: Assigning to this will not fail, but is pointless as this + // iterator is only meant to be read from. + reference operator * () const; + + // Member access + pointer operator -> () const; + + // + // Input and Forward Iterator + // + + // Preincrement + file_iterator const & operator ++ () const; + + // Postincrement + file_iterator const operator ++ (int) const; + + // + // Bidirectional Iterator + // + + // Predecrement + file_iterator const & operator -- () const; + + // Postdecrement + file_iterator const operator -- (int) const; + + // + // Random Access Iterator + // + + // Iterator addition (i += n) + file_iterator const & operator += (difference_type Distance) const; + + // Iterator addition (i + n) + file_iterator const operator + (difference_type Distance) const; + + // Iterator subtraction (i -= n) + file_iterator const & operator -= (difference_type Distance) const; + + // Iterator subtraction (i - n) + file_iterator const operator - (difference_type Distance) const; + + // Difference (i - j) + difference_type operator - (file_iterator const & rIterator) const; + + // Element + value_type operator [] (difference_type Index) const; + + // + // Equality Comparable + // + + bool operator_equal_to (file_iterator const & rOther) const; + + // + // LessThan Comparable + // + + bool operator_less_than (file_iterator const & rOther) const; + + bool operator_greater_than (file_iterator const & rOther) const; + + private: + + // Character size + BOOST_STATIC_CONSTANT (int, kCharSize = sizeof (CharT)); + + // Length of the file in bytes + difference_type m_Filesize; + + // File descriptor + int m_File; + + // Current offset into the file + mutable difference_type m_Offset; + + // The next character to be returned + mutable CharT m_NextChar; + + // True if this instance is responsible for closing the file + bool m_CloseFile; +}; + +// Iterator addition (n + i) +template +file_iterator const operator + ( + typename file_iterator ::difference_type Distance, + file_iterator const & rIterator + ); + +// +// Equality Comparable +// + +// Equality +template +bool operator == ( + file_iterator const & rA, + file_iterator const & rB + ); + +// Inequality +template +bool operator != ( + file_iterator const & rA, + file_iterator const & rB + ); + +// +// LessThan Comparable +// + +// Less +template +bool operator < ( + file_iterator const & rA, + file_iterator const & rB + ); + +// Greater +template +bool operator > ( + file_iterator const & rA, + file_iterator const & rB + ); + +// Less or equal +template +bool operator <= ( + file_iterator const & rA, + file_iterator const & rB + ); + +// Greater or equal +template +bool operator >= ( + file_iterator const & rA, + file_iterator const & rB + ); + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +/////////////////////////////////////////////////////////////////////////////// +#if defined BOOST_MSVC +#pragma warning ( pop ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#endif // #if !defined FILE_ITERATOR_HPP + +/////////////////////////////////////////////////////////////////////////////// +#if !defined FILE_ITERATOR_IPP + #include "boost/spirit/iterator/impl/file_iterator.ipp" +#endif diff --git a/include/boost/spirit/iterator/fixed_size_queue.hpp b/include/boost/spirit/iterator/fixed_size_queue.hpp new file mode 100644 index 000000000..4ae705c62 --- /dev/null +++ b/include/boost/spirit/iterator/fixed_size_queue.hpp @@ -0,0 +1,306 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001, Daniel C. Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef FIXED_SIZE_QUEUE +#define FIXED_SIZE_QUEUE + +#include +#include +#include + +#include "boost/spirit/debug/assert.hpp" // for BOOST_SPIRIT_ASSERT + +// FIXES for broken compilers +#include + +//// fix for cygwin +//#ifdef size_t +//#undef size_t +//namespace std { typedef unsigned size_t; } +//#endif + +#define BOOST_SPIRIT_ASSERT_FSQ_SIZE \ + BOOST_SPIRIT_ASSERT(((m_tail + N + 1) - m_head) % (N+1) == m_size % (N+1)) \ + /**/ + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +template +class fixed_size_queue_iterator; + +template +class fixed_size_queue +{ +public: + fixed_size_queue(); + fixed_size_queue(const fixed_size_queue& x); + fixed_size_queue& operator=(const fixed_size_queue& x); + ~fixed_size_queue(); + + void push_back(const T& e); + void push_front(const T& e); + void serve(T& e); + void pop_front(); + + bool empty() + { + return m_size == 0; + } + + bool full() + { + return m_size == N; + } + + + typedef fixed_size_queue_iterator iterator; + + iterator begin() + { + return iterator(this, m_head); + } + + iterator end() + { + return iterator(this, m_tail); + } + + std::size_t size() + { + return m_size; + } + + T& front() + { + return m_queue[m_head]; + } + +private: + + //friend class iterator; + friend class fixed_size_queue_iterator; + + std::size_t m_head; + std::size_t m_tail; + std::size_t m_size; + T m_queue[N+1]; + +}; + + +template +class fixed_size_queue_iterator +{ +public: + + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + typedef fixed_size_queue queue; + + fixed_size_queue_iterator(queue* q, std::size_t p) + : m_queue(q) + , pos(p) + {} + + fixed_size_queue_iterator& operator++() + { + ++pos; + if (pos == N+1) + pos = 0; + + return *this; + } + + fixed_size_queue_iterator operator++(int) + { + fixed_size_queue_iterator tmp = *this; + ++*this; + return tmp; + } + + T& operator*() + { + return m_queue->m_queue[pos]; + } + + bool operator==(const fixed_size_queue_iterator& x) + { + return pos == x.pos && m_queue == x.m_queue; + } + + bool operator<(const fixed_size_queue_iterator& x) + { + std::size_t p1 = pos < m_queue->m_head ? pos + N : pos; + std::size_t p2 = x.pos < x.m_queue->m_head ? x.pos + N : x.pos; + return p1 < p2; + } + + bool operator!=(const fixed_size_queue_iterator& x) + { + return !(*this == x); + } + +private: + queue* m_queue; + std::size_t pos; +}; + +template +inline +fixed_size_queue::fixed_size_queue() + : m_head(0) + , m_tail(0) + , m_size(0) +{ + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); +} + +template +inline +fixed_size_queue::fixed_size_queue(const fixed_size_queue& x) + : m_head(x.m_head) + , m_tail(x.m_tail) + , m_size(x.m_size) +{ + copy(x.begin(), x.end(), begin()); + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); +} + +template +inline fixed_size_queue& +fixed_size_queue::operator=(const fixed_size_queue& x) +{ + if (this != &x) + { + m_head = x.m_head; + m_tail = x.m_tail; + m_size = x.m_size; + copy(x.begin(), x.end(), begin()); + } + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); + + return *this; +} + +template +inline +fixed_size_queue::~fixed_size_queue() +{ + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); +} + +template +inline void +fixed_size_queue::push_back(const T& e) +{ + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); + + BOOST_SPIRIT_ASSERT(!full()); + + m_queue[m_tail] = e; + ++m_size; + ++m_tail; + if (m_tail == N+1) + m_tail = 0; + + + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); +} + +template +inline void +fixed_size_queue::push_front(const T& e) +{ + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); + + BOOST_SPIRIT_ASSERT(!full()); + + if (m_head == 0) + m_head = N; + else + --m_head; + + m_queue[m_head] = e; + ++m_size; + + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); +} + + +template +inline void +fixed_size_queue::serve(T& e) +{ + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); + + e = m_queue[m_head]; + pop_front(); +} + + + +template +inline void +fixed_size_queue::pop_front() +{ + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); + + ++m_head; + if (m_head == N+1) + m_head = 0; + --m_size; + + BOOST_SPIRIT_ASSERT(m_size <= N+1); + BOOST_SPIRIT_ASSERT_FSQ_SIZE; + BOOST_SPIRIT_ASSERT(m_head <= N+1); + BOOST_SPIRIT_ASSERT(m_tail <= N+1); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#undef BOOST_SPIRIT_ASSERT_FSQ_SIZE + +#endif diff --git a/include/boost/spirit/iterator/impl/Makefile.am b/include/boost/spirit/iterator/impl/Makefile.am new file mode 100644 index 000000000..919d7ab7e --- /dev/null +++ b/include/boost/spirit/iterator/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = file_iterator.ipp msvc_ps_helper.hpp multi_pass_msvc.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/iterator/impl diff --git a/include/boost/spirit/iterator/impl/file_iterator.ipp b/include/boost/spirit/iterator/impl/file_iterator.ipp new file mode 100644 index 000000000..e2f5b9e9c --- /dev/null +++ b/include/boost/spirit/iterator/impl/file_iterator.ipp @@ -0,0 +1,514 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002 Jeff Westfahl + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ + +// This code is inspired by FILEiter.h by Stephen Cleary, and is basically a +// superset of the functionality provided there. FILEiter.h is available from +// http://groups.yahoo.com/group/boost/files/2000/IOGlue/IOGlue.zip and has +// the following copyright notice: + +// FILEiter: Input and Output iterators for FILE * objects + +// (C) Copyright Stephen Cleary 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#if !defined FILE_ITERATOR_IPP +#define FILE_ITERATOR_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include +#include + +#if (defined (__COMO_VERSION__) && defined (BOOST_MSVC)) \ + || defined __BORLANDC__ || defined BOOST_INTEL_CXX_VERSION \ + || defined BOOST_MSVC + #include +#elif defined (__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3) + + #include + +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +namespace impl { + +// Systems that have _lseeki64, such as Win32. +#if defined BOOST_MSVC \ + || defined __MINGW32_VERSION \ + || defined BOOST_INTEL_CXX_VERSION + + // These systems default to CR-LF translation for opened files. Using + // O_BINARY turns off this translation. + static const int kOpenFlags = O_RDONLY | O_BINARY; + + // Import _lseeki64 into this namespace under the name lseek + inline off_t lseek (int File, off_t Offset, int Whence) + { + return _lseeki64 (File, Offset, Whence); + } + +// Systems that have lseek, whether it is 64-bit or 32-bit +#else + + // Some non-POSIX systems default to CR-LF translation for opened + // files. Using O_BINARY turns off this translation. + #if defined __CYGWIN__ || defined __BORLANDC__ + + static const int kOpenFlags = O_RDONLY | O_BINARY; + + // POSIX systems don't do any CR-LF translation, and don't have an + // O_BINARY flag. POSIX systems don't do this because it is ignored + // on all POSIX conforming systems, according to the Linux man page + // for fopen. + #else + + static const int kOpenFlags = O_RDONLY; + + #endif + + // Import lseek into this namespace + using ::lseek; + +#endif + +/////////////////////////////////////////////////////////////////////////////// +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator ::file_iterator (char const * pFilename) + : m_Filesize (0), + m_File (-1), + m_Offset (0), + m_NextChar (), + m_CloseFile (false) +{ + assert (NULL != pFilename); + + m_File = open (pFilename, impl::kOpenFlags); + + if (-1 != m_File) + { + // This instance is responsible for closing the file + m_CloseFile = true; + + // Get the file size in bytes + m_Filesize = impl::lseek (m_File, 0, SEEK_END); + + // The above shouldn't fail, but you never know... + if (0 > m_Filesize) + { + close (m_File); + + m_CloseFile = false; + + m_File = -1; + } + + // Move the file pointer back to the beginning + impl::lseek (m_File, 0, SEEK_SET); + + // Read the first character + read (m_File, &m_NextChar, kCharSize); + } +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator ::~file_iterator () +{ + if ( + m_CloseFile + && (-1 != m_File) + ) + { + close (m_File); + } +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator file_iterator ::make_end () +{ + file_iterator _Iterator (*this); + + // Make sure the offset is correctly aligned + _Iterator.m_Offset = m_Filesize - (m_Filesize % kCharSize); + + return _Iterator; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator ::operator bool () const +{ + return (-1 != m_File); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline typename file_iterator ::difference_type + file_iterator ::size () const +{ + return m_Filesize; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator ::file_iterator () + : m_Filesize (0), + m_File (-1), + m_Offset (-1), + m_NextChar (), + m_CloseFile (false) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator ::file_iterator ( + file_iterator const & rCopyMe + ) + : m_Filesize (rCopyMe.m_Filesize), + m_File (rCopyMe.m_File), + m_Offset (rCopyMe.m_Offset), + m_NextChar (rCopyMe.m_NextChar), + m_CloseFile (false) +{ +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator & file_iterator ::operator = ( + file_iterator const & rAssignMe + ) +{ + // Clean up previous file if necessary + if ( + m_CloseFile + && (-1 != m_File) + && (m_File != rAssignMe.m_File) + ) + { + close (m_File); + } + + m_File = rAssignMe.m_File; + m_Offset = rAssignMe.m_Offset; + m_Filesize = rAssignMe.m_Filesize; + m_NextChar = rAssignMe.m_NextChar; + + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline void file_iterator ::swap ( + file_iterator & rA, + file_iterator & rB + ) +{ + file_iterator _Temp (rA); + + rA = rB; + + rB = _Temp; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline typename file_iterator ::reference + file_iterator ::operator * () const +{ + assert (-1 != m_File); + + return m_NextChar; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline typename file_iterator ::pointer + file_iterator ::operator -> () const +{ + assert (-1 != m_File); + + return &m_NextChar; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator const & + file_iterator ::operator ++ () const +{ + assert (-1 != m_File); + + m_Offset += kCharSize; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator const + file_iterator ::operator ++ (int) const +{ + assert (-1 != m_File); + + file_iterator _Temp (*this); + + m_Offset += kCharSize; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return _Temp; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator const & + file_iterator ::operator -- () const +{ + assert (-1 != m_File); + + m_Offset -= kCharSize; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline file_iterator const + file_iterator ::operator -- (int) const +{ + assert (-1 != m_File); + + file_iterator _Temp (*this); + + m_Offset -= kCharSize; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return _Temp; +} + +/////////////////////////////////////////////////////////////////////////////// +template +file_iterator const & file_iterator ::operator += ( + difference_type Distance + ) const +{ + assert (-1 != m_File); + + m_Offset += Distance * kCharSize; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +template +file_iterator const file_iterator ::operator + ( + difference_type Distance + ) const +{ + file_iterator _Temp (*this); + + _Temp += Distance; + + return _Temp; +} + +/////////////////////////////////////////////////////////////////////////////// +template +file_iterator const & file_iterator ::operator -= ( + difference_type Distance + ) const +{ + assert (-1 != m_File); + + m_Offset -= Distance * kCharSize; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +template +file_iterator const file_iterator ::operator - ( + difference_type Distance + ) const +{ + file_iterator _Temp (*this); + + _Temp -= Distance; + + return _Temp; +} + +/////////////////////////////////////////////////////////////////////////////// +template +typename file_iterator ::difference_type + file_iterator ::operator - ( + file_iterator const & rIterator + ) const +{ + return ((m_Offset - rIterator.m_Offset) / kCharSize); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline typename file_iterator ::value_type + file_iterator ::operator [] (difference_type Index) const +{ + assert (-1 != m_File); + + CharT _ReturnValue; + + impl::lseek (m_File, m_Offset, SEEK_SET); + + read (m_File, &m_NextChar, kCharSize); + + return _ReturnValue; +} + +/////////////////////////////////////////////////////////////////////////////// +template +file_iterator const operator + ( + typename file_iterator ::difference_type Distance, + file_iterator const & rIterator + ) +{ + file_iterator _Temp (rIterator); + + _Temp += Distance; + + return _Temp; +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool file_iterator ::operator_equal_to ( + const file_iterator & rOther + ) const +{ +// assert (m_File == rOther.m_File); + + return (m_Offset == rOther.m_Offset); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool operator == ( + file_iterator const & rA, + file_iterator const & rB + ) +{ + return rA.operator_equal_to (rB); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool operator != ( + file_iterator const & rA, + file_iterator const & rB + ) +{ + return !(rA.operator_equal_to (rB)); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool file_iterator ::operator_less_than ( + file_iterator const & rOther + ) const +{ + assert (m_File == rOther.m_File); + + return (m_Offset < rOther.m_Offset); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool operator < ( + file_iterator const & rA, + file_iterator const & rB + ) +{ + return rA.operator_less_than (rB); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool operator >= ( + file_iterator const & rA, + file_iterator const & rB + ) +{ + return !(rA.operator_less_than (rB)); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool file_iterator ::operator_greater_than ( + file_iterator const & rOther + ) const +{ + assert (m_File == rOther.m_File); + + return (m_Offset > rOther.m_Offset); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool operator > ( + file_iterator const & rA, + file_iterator const & rB + ) +{ + return (rA.operator_greater_than (rB)); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline bool operator <= ( + file_iterator const & rA, + file_iterator const & rB + ) +{ + return !(rA.operator_greater_than (rB)); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // #if !defined FILE_ITERATOR_IPP diff --git a/include/boost/spirit/iterator/multi_pass.hpp b/include/boost/spirit/iterator/multi_pass.hpp new file mode 100644 index 000000000..3ca1370dc --- /dev/null +++ b/include/boost/spirit/iterator/multi_pass.hpp @@ -0,0 +1,1224 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001, Daniel C. Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP +#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP + +#include "boost/config.hpp" + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +// The multi_pass for VC++ is currently broken +#else +// the newer version of multi_pass + +#include +#include +#include +#include // for std::swap +#include // for std::exception + +#include + +#include "fixed_size_queue.hpp" +#include "boost/spirit/debug/assert.hpp" // for BOOST_SPIRIT_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +namespace impl { + template + inline void mp_swap(T& t1, T& t2); +} + +namespace multi_pass_policies +{ + +/////////////////////////////////////////////////////////////////////////////// +// class ref_counted +// Implementation of an OwnershipPolicy used by multi_pass. +// +// Implementation modified from RefCounted class from the Loki library by +// Andrei Alexandrescu +/////////////////////////////////////////////////////////////////////////////// +class ref_counted +{ + protected: + ref_counted() + : count(new unsigned int(1)) + {} + + ref_counted(ref_counted const& x) + : count(x.count) + {} + + // clone is called when a copy of the iterator is made, so increment + // the ref-count. + void clone() + { + ++*count; + } + + // called when a copy is deleted. Decrement the ref-count. Return + // value of true indicates that the last copy has been released. + bool release() + { + if (!--*count) + { + delete count; + count = 0; + return true; + } + return false; + } + + void swap(ref_counted& x) + { + impl::mp_swap(count, x.count); + } + + public: + // returns true if there is only one iterator in existence. + // std_dequeu StoragePolicy will free it's buffered data if this + // returns true. + bool unique() const + { + return *count == 1; + } + + private: + unsigned int* count; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class first_owner +// Implementation of an OwnershipPolicy used by multi_pass +// This ownership policy dictates that the first iterator created will +// determine the lifespan of the shared components. This works well for +// spirit, since no dynamic allocation of iterators is done, and all copies +// are make on the stack. +// +// There is a caveat about using this policy together with the std_deque +// StoragePolicy. Since first_owner always returns false from unique(), +// std_deque will only release the queued data if clear_queue() is called. +/////////////////////////////////////////////////////////////////////////////// +class first_owner +{ + protected: + first_owner() + : first(true) + {} + + first_owner(first_owner const&) + : first(false) + {} + + void clone() + { + } + + // return true to indicate deletion of resources + bool release() + { + return first; + } + + void swap(first_owner&) + { + // if we're the first, we still remain the first, even if assigned + // to, so don't swap first_. swap is only called from operator= + } + + public: + bool unique() const + { + return false; // no way to know, so always return false + } + + private: + bool first; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class illegal_backtracking +// thrown by buf_id_check CheckingPolicy if an instance of an iterator is +// used after another one has invalidated the queue +/////////////////////////////////////////////////////////////////////////////// +class illegal_backtracking : public std::exception +{ +public: + + illegal_backtracking() throw() {} + ~illegal_backtracking() throw() {} + + virtual const char* + what() const throw() + { return "boost::spirit::illegal_backtracking"; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// class buf_id_check +// Implementation of the CheckingPolicy used by multi_pass +// This policy is most effective when used together with the std_deque +// StoragePolicy. +// If used with the fixed_size_queue StoragePolicy, it will not detect +// iterator derefereces that are out of the range of the queue. +/////////////////////////////////////////////////////////////////////////////// +class buf_id_check +{ + protected: + buf_id_check() + : shared_buf_id(new unsigned long(0)) + , buf_id(0) + {} + + buf_id_check(buf_id_check const& x) + : shared_buf_id(x.shared_buf_id) + , buf_id(x.buf_id) + {} + + // will be called from the destructor of the last iterator. + void destroy() + { + delete shared_buf_id; + shared_buf_id = 0; + } + + void swap(buf_id_check& x) + { + impl::mp_swap(shared_buf_id, x.shared_buf_id); + impl::mp_swap(buf_id, x.buf_id); + } + + // called to verify that everything is okay. + void check() const + { + if (buf_id != *shared_buf_id) + { + throw illegal_backtracking(); + } + } + + // called from multi_pass::clear_queue, so we can increment the count + void clear_queue() + { + ++*shared_buf_id; + ++buf_id; + } + + private: + unsigned long* shared_buf_id; + unsigned long buf_id; +}; + +/////////////////////////////////////////////////////////////////////////////// +// class no_check +// Implementation of the CheckingPolicy used by multi_pass +// It does not do anything :-) +/////////////////////////////////////////////////////////////////////////////// +class no_check +{ + protected: + no_check() {} + no_check(no_check const&) {} + void destroy() {} + void swap(no_check&) {} + void check() const {} + void clear_queue() {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// class std_deque +// Implementation of the StoragePolicy used by multi_pass +// This stores all data in a std::deque, and keeps an offset to the current +// position. It stores all the data unless there is only one +// iterator using the queue. +// Note: a position is used instead of an iterator, because a push_back on +// a deque can invalidate any iterators. +/////////////////////////////////////////////////////////////////////////////// +class std_deque +{ + public: + +template +class inner +{ +#ifdef __BORLANDC__ + public: +#else + private: +#endif + typedef std::deque queue_type; + queue_type* queuedElements; + mutable typename queue_type::size_type queuePosition; + + protected: + inner() + : queuedElements(new queue_type) + , queuePosition(0) + {} + + inner(inner const& x) + : queuedElements(x.queuedElements) + , queuePosition(x.queuePosition) + {} + + // will be called from the destructor of the last iterator. + void destroy() + { + BOOST_SPIRIT_ASSERT(queuedElements); + delete queuedElements; + queuedElements = 0; + } + + void swap(inner& x) + { + impl::mp_swap(queuedElements, x.queuedElements); + impl::mp_swap(queuePosition, x.queuePosition); + } + + // This is called when the iterator is dereferenced. It's a template + // method so we can recover the type of the multi_pass iterator + // and call unique and access the m_input data member. + template + static typename MultiPassT::reference dereference(MultiPassT const& mp) + { + if (mp.queuePosition == mp.queuedElements->size()) + { + // check if this is the only iterator + if (mp.unique()) + { + // free up the memory used by the queue. + if (mp.queuedElements->size() > 0) + { + mp.queuedElements->clear(); + mp.queuePosition = 0; + } + } + return mp.get_input(); + } + else + { + return (*mp.queuedElements)[mp.queuePosition]; + } + } + + // This is called when the iterator is incremented. It's a template + // method so we can recover the type of the multi_pass iterator + // and call unique and access the m_input data member. + template + static void increment(MultiPassT& mp) + { + if (mp.queuePosition == mp.queuedElements->size()) + { + // check if this is the only iterator + if (mp.unique()) + { + // free up the memory used by the queue. + if (mp.queuedElements->size() > 0) + { + mp.queuedElements->clear(); + mp.queuePosition = 0; + } + } + else + { + mp.queuedElements->push_back(mp.get_input()); + ++mp.queuePosition; + } + mp.advance_input(); + } + else + { + ++mp.queuePosition; + } + + } + + // called to forcibly clear the queue + void clear_queue() + { + queuedElements->clear(); + queuePosition = 0; + } + + // called to determine whether the iterator is an eof iterator + template + static bool is_eof(MultiPassT const& mp) + { + return mp.queuePosition == mp.queuedElements->size() && + mp.input_at_eof(); + } + + // called by operator== + bool equal_to(inner const& x) const + { + return queuePosition == x.queuePosition; + } + + // called by operator< + bool less_than(inner const& x) const + { + return queuePosition < x.queuePosition; + } +}; // class inner + +}; // class std_deque + + +/////////////////////////////////////////////////////////////////////////////// +// class fixed_size_queue +// Implementation of the StoragePolicy used by multi_pass +// fixed_size_queue keeps a circular buffer (implemented by +// boost::spirit::fixed_size_queue class) that is size N+1 and stores N elements. +// It is up to the user to ensure that there is enough look ahead for their +// grammar. Currently there is no way to tell if an iterator is pointing +// to forgotten data. The leading iterator will put an item in the queue +// and remove one when it is incremented. No dynamic allocation is done, +// except on creation of the queue (fixed_size_queue constructor). +/////////////////////////////////////////////////////////////////////////////// +template < std::size_t N> +class fixed_size_queue +{ + public: + +template +class inner +{ +#ifdef __BORLANDC__ + public: +#else + private: +#endif + typedef boost::spirit::fixed_size_queue queue_type; + queue_type * queuedElements; + mutable typename queue_type::iterator queuePosition; + + protected: + inner() + : queuedElements(new queue_type) + , queuePosition(queuedElements->begin()) + {} + + inner(inner const& x) + : queuedElements(x.queuedElements) + , queuePosition(x.queuePosition) + {} + + // will be called from the destructor of the last iterator. + void destroy() + { + BOOST_SPIRIT_ASSERT(queuedElements); + delete queuedElements; + queuedElements = 0; + } + + void swap(inner& x) + { + impl::mp_swap(queuedElements, x.queuedElements); + impl::mp_swap(queuePosition, x.queuePosition); + } + + // This is called when the iterator is dereferenced. It's a template + // method so we can recover the type of the multi_pass iterator + // and access the m_input data member. + template + static typename MultiPassT::reference dereference(MultiPassT const& mp) + { + if (mp.queuePosition == mp.queuedElements->end()) + { + return mp.get_input(); + } + else + { + return *mp.queuePosition; + } + } + + // This is called when the iterator is incremented. It's a template + // method so we can recover the type of the multi_pass iterator + // and access the m_input data member. + template + static void increment(MultiPassT& mp) + { + if (mp.queuePosition == mp.queuedElements->end()) + { + // don't let the queue get larger than N + if (mp.queuedElements->size() >= N) + mp.queuedElements->pop_front(); + + mp.queuedElements->push_back(mp.get_input()); + mp.advance_input(); + } + ++mp.queuePosition; + } + + // no-op + void clear_queue() + {} + + // called to determine whether the iterator is an eof iterator + template + static bool is_eof(MultiPassT const& mp) + { + return mp.queuePosition == mp.queuedElements->end() && + mp.input_at_eof(); + } + + // called by operator== + bool equal_to(inner const& x) const + { + return queuePosition == x.queuePosition; + } + + // called by operator< + bool less_than(inner const& x) const + { + return queuePosition < x.queuePosition; + } +}; // class inner + +}; // class fixed_size_queue + + +/////////////////////////////////////////////////////////////////////////////// +// class input_iterator +// Implementation of the InputPolicy used by multi_pass +// input_iterator encapsulates an input iterator of type InputT +/////////////////////////////////////////////////////////////////////////////// +class input_iterator +{ + public: + +template +class inner +{ + public: + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type + difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + + protected: + inner() + : input(new InputT()) + , val(new value_type) + {} + + inner(InputT x) + : input(new InputT(x)) + , val(new value_type(**input)) + {} + + inner(inner const& x) + : input(x.input) + , val(x.val) + {} + + void destroy() + { + delete input; + input = 0; + delete val; + val = 0; + } + + bool same_input(inner const& x) const + { + return input == x.input; + } + + typedef typename std::iterator_traits::value_type value_t; + void swap(inner& x) + { + impl::mp_swap(input, x.input); + impl::mp_swap(val, x.val); + } + + public: + reference get_input() const + { + return *val; + } + + void advance_input() + { + ++*input; + *val = **input; + } + + bool input_at_eof() const + { + return *input == InputT(); + } + + private: + InputT* input; + value_type* val; + +}; + +}; + +/////////////////////////////////////////////////////////////////////////////// +// class lex_input +// Implementation of the InputPolicy used by multi_pass +// lex_input gets tokens (ints) from yylex() +/////////////////////////////////////////////////////////////////////////////// +class lex_input +{ + public: + +template +class inner +{ + public: + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + + protected: + inner() + : curtok(new int(0)) + {} + + inner(InputT x) + : curtok(new int(x)) + {} + + inner(inner const& x) + : curtok(x.curtok) + {} + + void destroy() + { + delete curtok; + curtok = 0; + } + + bool same_input(inner const& x) const + { + return curtok == x.curtok; + } + + void swap(inner& x) + { + impl::mp_swap(curtok, x.curtok); + } + + public: + reference get_input() const + { + return *curtok; + } + + void advance_input() + { + extern int yylex(); + *curtok = yylex(); + } + + bool input_at_eof() const + { + return *curtok == 0; + } + + private: + int* curtok; + +}; + +}; + +/////////////////////////////////////////////////////////////////////////////// +// class functor_input +// Implementation of the InputPolicy used by multi_pass +// functor_input gets tokens from a functor +// Note: the functor must have a typedef for result_type +// It also must have a static variable of type result_type defined to +// represent eof that is called eof. +/////////////////////////////////////////////////////////////////////////////// +class functor_input +{ + public: + +template +class inner +{ + typedef typename FunctorT::result_type result_type; + public: + typedef result_type value_type; + typedef std::ptrdiff_t difference_type; + typedef result_type* pointer; + typedef result_type& reference; + + protected: + inner() + : ftor(0) + , curtok(0) + {} + + inner(FunctorT const& x) + : ftor(new FunctorT(x)) + , curtok(new result_type((*ftor)())) + {} + + inner(inner const& x) + : ftor(x.ftor) + , curtok(x.curtok) + {} + + void destroy() + { + delete ftor; + ftor = 0; + delete curtok; + curtok = 0; + } + + bool same_input(inner const& x) const + { + return ftor == x.ftor; + } + + void swap(inner& x) + { + impl::mp_swap(curtok, x.curtok); + impl::mp_swap(ftor, x.ftor); + } + + public: + reference get_input() const + { + return *curtok; + } + + void advance_input() + { + if (curtok) { + *curtok = (*ftor)(); + } + } + + bool input_at_eof() const + { + return !curtok || *curtok == ftor->eof; + } + + FunctorT& get_functor() const + { + return *ftor; + } + + + private: + FunctorT* ftor; + result_type* curtok; + +}; + +}; + +} // namespace multi_pass_policies + +/////////////////////////////////////////////////////////////////////////////// +// class template multi_pass (declaration) +/////////////////////////////////////////////////////////////////////////////// +template +< + typename InputT, + typename InputPolicy = multi_pass_policies::input_iterator, + typename OwnershipPolicy = multi_pass_policies::ref_counted, + typename CheckingPolicy = multi_pass_policies::buf_id_check, + typename StoragePolicy = multi_pass_policies::std_deque +> +class multi_pass; + +// The default multi_pass instantiation uses a ref-counted std_deque scheme. + +/////////////////////////////////////////////////////////////////////////////// +// class template multi_pass (definition) +/////////////////////////////////////////////////////////////////////////////// +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +class multi_pass + : public OwnershipPolicy + , public CheckingPolicy + , public StoragePolicy::template inner< + typename InputPolicy::template inner::value_type> + , public InputPolicy::template inner +{ + typedef OwnershipPolicy OP; + typedef CheckingPolicy CHP; + typedef typename StoragePolicy::template inner< + typename InputPolicy::template inner::value_type> SP; + typedef typename InputPolicy::template inner IP; + + public: + typedef std::forward_iterator_tag iterator_category; + typedef typename IP::value_type value_type; + typedef typename IP::difference_type difference_type; + typedef typename IP::pointer pointer; + typedef typename IP::reference reference; + + typedef InputT iterator_type; + + multi_pass(); + explicit multi_pass(InputT input); + + ~multi_pass(); + + multi_pass(multi_pass const&); + multi_pass& operator=(multi_pass const&); + + void swap(multi_pass& x); + + reference operator*() const; + pointer operator->() const; + multi_pass& operator++(); + multi_pass operator++(int); + + void clear_queue(); + + bool operator==(const multi_pass& y) const; + bool operator<(const multi_pass& y) const; + + private: // helper functions + bool is_eof() const; +}; + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass:: +multi_pass() + : OP() + , CHP() + , SP() + , IP() +{ +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass:: +multi_pass(InputT input) + : OP() + , CHP() + , SP() + , IP(input) +{ +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass:: +~multi_pass() +{ + if (OP::release()) + { + CHP::destroy(); + SP::destroy(); + IP::destroy(); + } +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass:: +multi_pass( + multi_pass const& x) + : OP(x) + , CHP(x) + , SP(x) + , IP(x) +{ + OP::clone(); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass& +multi_pass:: +operator=( + multi_pass const& x) +{ + multi_pass temp(x); + temp.swap(*this); + return *this; +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline void +multi_pass:: +swap(multi_pass& x) +{ + OP::swap(x); + CHP::swap(x); + SP::swap(x); + IP::swap(x); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +typename multi_pass:: +reference +multi_pass:: +operator*() const +{ + CHP::check(); + return SP::dereference(*this); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +typename multi_pass:: +pointer +multi_pass:: +operator->() const +{ + return &(operator*()); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass& +multi_pass:: +operator++() +{ + CHP::check(); + SP::increment(*this); + return *this; +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +multi_pass +multi_pass:: +operator++(int) +{ + multi_pass + < + InputT, + InputPolicy, + OwnershipPolicy, + CheckingPolicy, + StoragePolicy + > tmp(*this); + + ++*this; + + return tmp; +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline void +multi_pass:: +clear_queue() +{ + SP::clear_queue(); + CHP::clear_queue(); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline bool +multi_pass:: +is_eof() const +{ + return SP::is_eof(*this); +} + +///// Comparisons +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline bool +multi_pass:: +operator==(const multi_pass& y) const +{ + if (is_eof() && y.is_eof()) + { + return true; // both are EOF + } + else if (is_eof() ^ y.is_eof()) + { + return false; // one is EOF, one isn't + } + else if (!IP::same_input(y)) + { + return false; + } + else + { + return SP::equal_to(y); + } +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline bool +multi_pass:: +operator<(const multi_pass& y) const +{ + return SP::less_than(y); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +bool operator!=( + const multi_pass& x, + const multi_pass& y) +{ + return !(x == y); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +bool operator>( + const multi_pass& x, + const multi_pass& y) +{ + return y < x; +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +bool operator>=( + const multi_pass& x, + const multi_pass& y) +{ + return !(x < y); +} + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +inline +bool operator<=( + const multi_pass& x, + const multi_pass& y) +{ + return !(y < x); +} + +///// Generator function +template +inline multi_pass +make_multi_pass(InputT i) +{ + return multi_pass(i); +} + +// this could be a template typedef, since such a thing doesn't +// exist in C++, we'll use inheritance to accomplish the same thing. + +template +class look_ahead : + public multi_pass< + InputT, + multi_pass_policies::input_iterator, + multi_pass_policies::first_owner, + multi_pass_policies::no_check, + multi_pass_policies::fixed_size_queue > +{ + typedef multi_pass< + InputT, + multi_pass_policies::input_iterator, + multi_pass_policies::first_owner, + multi_pass_policies::no_check, + multi_pass_policies::fixed_size_queue > base_t; + public: + look_ahead() + : base_t() {} + + explicit look_ahead(InputT x) + : base_t(x) {} + + look_ahead(look_ahead const& x) + : base_t(x) {} + + // default generated operators destructor and assignment operator are okay. +}; + +template +< + typename InputT, + typename InputPolicy, + typename OwnershipPolicy, + typename CheckingPolicy, + typename StoragePolicy +> +void swap( + multi_pass< + InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy + > &x, + multi_pass< + InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy + > &y) +{ + x.swap(y); +} + +namespace impl { +#if __GNUC__ == 2 + using std::swap; +#endif + template + inline void mp_swap(T& t1, T& t2) + { + using std::swap; + using boost::spirit::swap; + swap(t1, t2); + } +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif // defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +#endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP + diff --git a/include/boost/spirit/iterator/position_iterator.hpp b/include/boost/spirit/iterator/position_iterator.hpp new file mode 100644 index 000000000..c1bae36c2 --- /dev/null +++ b/include/boost/spirit/iterator/position_iterator.hpp @@ -0,0 +1,195 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2002 Juan Carlos Arevalo-Baeza + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. + + See spirit.hpp for full copyright notices. +=============================================================================*/ +#ifndef BOOST_SPIRIT_POSITION_ITERATOR_HPP +#define BOOST_SPIRIT_POSITION_ITERATOR_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include +#include + +#include "boost/config.hpp" + +#include "boost/spirit/core/impl/msvc.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// file_position +// +// A structure to hold positional information. This includes the file, +// line and column +// +/////////////////////////////////////////////////////////////////////////////// + +struct file_position { + std::string file; + int line; + int column; + + file_position(std::string const& file_ = std::string(), + int line_ = 1, int column_ = 1): + file (file_), + line (line_), + column (column_) + {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// position_iterator +// +// It wraps an iterator, and keeps track of the current position in the input, +// as it gets incremented. +// +// The default tab size is 4. You can change this with the set_tabchars member +// function. +// +// In order to have begin/end iterators constructed, the end iterator must be +// empty constructed. Similar to what happens with stream iterators. Note that, +// if the wrapped iterator is a forward iterator, this one will work as a +// forward iterator too. The begin iterator must be constructed from both, the +// begin and end iterators of the wrapped iterator type. This is necessary to +// implement the lookahead of characters necessary to parse CRLF sequences. +// +// In order to extract the current positional data from the iterator, you may +// use the get_position member function. +// +// You can also use the set_position member function to reset the current +// position to something new. +// +/////////////////////////////////////////////////////////////////////////////// + +template < class IteratorT > +class position_iterator { +#if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)) \ + || (defined(BOOST_INTEL_CXX_VERSION) && !defined(_STLPORT_VERSION)) + typedef impl::iterator_traits traits_t; +#else + typedef std::iterator_traits traits_t; +#endif +public: + typedef typename traits_t::value_type value_type; + typedef typename traits_t::pointer pointer; + typedef typename traits_t::reference reference; + + typedef typename traits_t::difference_type difference_type; + +// regardless of the underlying iterator type the position_iterator is a +// forward iterator only + typedef typename std::forward_iterator_tag iterator_category; + + position_iterator(): m_CharsPerTab(4), m_IsAtEnd(true) {} + position_iterator(IteratorT const& iter, IteratorT const& iterend, + std::string const& file, int line = 1, int column = 1): + m_Iter(iter), + m_IterEnd(iterend), + m_Pos(file, line, column), + m_CharsPerTab(4), + m_IsAtEnd(m_Iter == m_IterEnd) + { + } + reference operator *() const { return *m_Iter; } + pointer operator ->() const { return &*m_Iter; } + bool is_equal(const position_iterator& i2) const { + return (m_IsAtEnd && i2.m_IsAtEnd) || + (!m_IsAtEnd && !i2.m_IsAtEnd && m_Iter == i2.m_Iter); + } + void set_position(file_position const& newpos) { + m_Pos = newpos; + } + file_position& get_position() { + return m_Pos; + } + file_position const& get_position() const { + return m_Pos; + } + position_iterator& operator ++() { + inc_current(); + return *this; + } + position_iterator operator ++(int) { + const position_iterator result = *this; + inc_current(); + return result; + } + friend difference_type operator -(const position_iterator& i1, + const position_iterator& i2) { + return i1.m_Iter - i2.m_Iter; + } + + void set_tabchars(unsigned int chars) { + m_CharsPerTab = chars; + } + +private: + IteratorT m_Iter; + IteratorT m_IterEnd; + + file_position m_Pos; + unsigned int m_CharsPerTab; + bool m_IsAtEnd; + + void inc_current() { + if (!m_IsAtEnd) { + value_type val = *m_Iter; + if (val == '\n' || val == '\r') { + ++m_Pos.line; + m_Pos.column = 1; + ++m_Iter; + if (m_Iter != m_IterEnd) { + value_type val2 = *m_Iter; + if ((val == '\n' && val2 == '\r') + || (val == '\r' && val2 == '\n')) { + ++m_Iter; + } + } + } else if (val == '\t') { + m_Pos.column += m_CharsPerTab - (m_Pos.column - 1) % m_CharsPerTab; + ++m_Iter; + } else { + ++m_Pos.column; + ++m_Iter; + } + if (m_Iter == m_IterEnd) { + m_IsAtEnd = true; + } + } + } +}; + +template < class IteratorT > +class position_iterator; + + +template < class IteratorT > +inline bool operator ==( + const position_iterator& i1, + const position_iterator& i2) +{ + return i1.is_equal(i2); +} + +template < class IteratorT > +inline bool operator !=( + const position_iterator& i1, + const position_iterator& i2) +{ + return !(i1 == i2); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/phoenix/Makefile.am b/include/boost/spirit/phoenix/Makefile.am new file mode 100644 index 000000000..104d3ec80 --- /dev/null +++ b/include/boost/spirit/phoenix/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = actor.hpp binders.hpp casts.hpp closures.hpp composite.hpp functions.hpp operators.hpp primitives.hpp special_ops.hpp statements.hpp tuple_helpers.hpp tuples.hpp +spiritincludedir = $(includedir)/spirit/boost/phoenix diff --git a/include/boost/spirit/phoenix/actor.hpp b/include/boost/spirit/phoenix/actor.hpp new file mode 100644 index 000000000..aa674899e --- /dev/null +++ b/include/boost/spirit/phoenix/actor.hpp @@ -0,0 +1,614 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_ACTOR_HPP +#define PHOENIX_ACTOR_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/tuples.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +// These are forward declared here because we cannot include impl.hpp +// or operators.hpp yet but the actor's assignment operator and index +// operator are required to be members. + +////////////////////////////////// +struct assign_op; +struct index_op; + +////////////////////////////////// +namespace impl { + + template + struct make_binary1; +} + +namespace impl { + + /////////////////////////////////////////////////////////////////////////// + // + // if_t selects type A or B depending on the condition C If C is of + // type char[2], B is selected, otherwise A + // + // TODO: This should be part of a common meta-library + // + /////////////////////////////////////////////////////////////////////////// + template + struct if_t { typedef A type; }; + + template + struct if_t { typedef B type; }; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// unpack_tuple class +// +// This class is used to unpack a supplied tuple such, that the members of +// this tuple will be handled as if they would be supplied separately. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct unpack_tuple : public TupleT { + + typedef TupleT tuple_t; + + unpack_tuple() {} + unpack_tuple(tuple_t const &tuple_) : TupleT(tuple_) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// actor class +// +// This class is a protocol class for all actors. This class is +// essentially an interface contract. The actor class does not +// really know how how to act on anything but instead relies on the +// template parameter BaseT (from which the actor will derive from) +// to do the actual action. +// +// An actor is a functor that is capable of accepting arguments up +// to a predefined maximum. It is up to the base class to do the +// actual processing or possibly to limit the arity (no. of +// arguments) passed in. Upon invocation of the functor through a +// supplied operator(), the actor funnels the arguments passed in +// by the client into a tuple and calls the base eval member +// function. +// +// Schematically: +// +// arg0 ---------| +// arg1 ---------| +// arg3 ---------|---> tupled_args ---> base.eval +// ... | +// argN ---------| +// +// actor::operator()(arg0, arg1... argN) +// ---> BaseT::eval(tupled_args); +// +// Actor base classes from which this class inherits from are +// expected to have a corresponding member function eval compatible +// with the conceptual Interface: +// +// template +// actor_return_type +// eval(TupleT const& args) const; +// +// where args are the actual arguments passed in by the client +// funneled into a tuple (see tuple.hpp for details). +// +// The actor_return_type can be anything. Base classes are free to +// return any type, even argument dependent types (types that are +// deduced from the types of the arguments). After evaluating the +// parameters and doing some computations or actions, the eval +// member function concludes by returning something back to the +// client. To do this, the forwarding function (the actor's +// operator()) needs to know the return type of the eval member +// function that it is calling. For this purpose, actor base +// classes are required to provide a nested template class: +// +// template +// struct result; +// +// This auxiliary class provides the result type information +// returned by the eval member function of a base actor class. The +// nested template class result should have a typedef 'type' that +// reflects the return type of its member function eval. It is +// basically a type computer that answers the question "given +// arguments packed into a TupleT type, what will be the result +// type of the eval member function of ActorT?". The template class +// actor_result queries this to extract the return type of an +// actor. Example: +// +// typedef typename actor_result::type +// actor_return_type; +// +// where actor_return_type is the actual type returned by ActorT's +// eval member function given some arguments in a TupleT. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct actor_result { + + typedef typename ActorT::template result::type type; + typedef typename remove_reference::type plain_type; +}; + +////////////////////////////////// +template +struct actor : public BaseT { + + actor(); + actor(BaseT const& base); + + typename actor_result >::type + operator()() const; + + template + typename actor_result >::type + operator()(A& a) const; + + template + typename actor_result >::type + operator()(A& a, B& b) const; + + template + typename actor_result >::type + operator()(A& a, B& b, C& c) const; + +#if PHOENIX_LIMIT > 3 + template + typename actor_result >::type + operator()(A& a, B& b, C& c, D& d) const; + + template + typename actor_result >::type + operator()(A& a, B& b, C& c, D& d, E& e) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F> + typename actor_result >::type + operator()(A& a, B& b, C& c, D& d, E& e, F& f) const; + +#if PHOENIX_LIMIT > 6 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G> + typename actor_result >::type + operator()(A& a, B& b, C& c, D& d, E& e, F& f, G& g) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H> + typename actor_result + >::type + operator()(A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I> + typename actor_result + >::type + operator()(A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i) const; + +#if PHOENIX_LIMIT > 9 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J> + typename actor_result + >::type + operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K> + typename actor_result + >::type + operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L> + typename actor_result + >::type + operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l) const; + +#if PHOENIX_LIMIT > 12 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M> + typename actor_result + >::type + operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l, M& m) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N> + typename actor_result + >::type + operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l, M& m, N& n) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O> + typename actor_result + >::type + operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l, M& m, N& n, O& o) const; + +#endif +#endif +#endif +#endif + + template + typename actor_result >::type + operator()(unpack_tuple const &t) const; + + template + typename impl::make_binary1::type + operator=(B const& b) const; + + template + typename impl::make_binary1::type + operator[](B const& b) const; +}; + +/////////////////////////////////////////////////////////////////////////// +// +// as_actor +// +// as_actor is a meta-program that converts an arbitrary type into +// an actor. All participants in the framework must be first-class +// actors. This meta-program is used all throughout the framework +// whenever an unknown type needs to be converted to an actor. +// as_actor specializations are expected to have a typedef 'type'. +// This is the destination actor type. A static member function +// 'convert' converts an object to this target type. +// +// The meta-program does no conversion if the object to be +// converted is already an actor. +// +/////////////////////////////////////////////////////////////////////////// +template +struct as_actor; + +////////////////////////////////// +template +struct as_actor > { + + typedef actor type; + static type convert(actor const& x) { return x; } +}; + +////////////////////////////////// +template <> +struct as_actor { + + typedef nil_t type; + static nil_t convert(nil_t /*x*/) + { return nil_t(); } +}; + +////////////////////////////////// +template <> +struct as_actor { + + typedef void type; + // ERROR!!! +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// actor class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +actor::actor() +: BaseT() {} + +////////////////////////////////// +template +actor::actor(BaseT const& base) +: BaseT(base) {} + +////////////////////////////////// +template +inline typename actor_result >::type +actor::operator()() const +{ + return BaseT::eval(tuple<>()); +} + +////////////////////////////////// +template +template +inline typename actor_result >::type +actor::operator()(A& a) const +{ + return BaseT::eval(tuple(a)); +} + +////////////////////////////////// +template +template +inline typename actor_result >::type +actor::operator()(A& a, B& b) const +{ + return BaseT::eval(tuple(a, b)); +} + +////////////////////////////////// +template +template +inline typename actor_result >::type +actor::operator()(A& a, B& b, C& c) const +{ + return BaseT::eval(tuple(a, b, c)); +} + +#if PHOENIX_LIMIT > 3 +////////////////////////////////// +template +template +inline typename actor_result >::type +actor::operator()(A& a, B& b, C& c, D& d) const +{ + return BaseT::eval(tuple(a, b, c, d)); +} + +////////////////////////////////// +template +template +inline typename actor_result >::type +actor::operator()(A& a, B& b, C& c, D& d, E& e) const +{ + return BaseT::eval(tuple(a, b, c, d, e)); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f) + ); +} + +#if PHOENIX_LIMIT > 6 +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i) + ); +} + +#if PHOENIX_LIMIT > 9 +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i, j) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i, j, k) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i, j, k, l) + ); +} + +#if PHOENIX_LIMIT > 12 +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l, M& m +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i, j, k, l, m) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l, M& m, N& n +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i, j, k, l, m, n) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O> +inline typename actor_result +>::type +actor::operator()( + A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, + K& k, L& l, M& m, N& n, O& o +) const +{ + return BaseT::eval( + tuple + (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) + ); +} + +#endif +#endif +#endif +#endif + +////////////////////////////////// +template +template +typename actor_result >::type +actor::operator()(unpack_tuple const &t) const +{ + return BaseT::eval(t); +} + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/binders.hpp b/include/boost/spirit/phoenix/binders.hpp new file mode 100644 index 000000000..e6ecb735a --- /dev/null +++ b/include/boost/spirit/phoenix/binders.hpp @@ -0,0 +1,3450 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_BINDERS_HPP +#define PHOENIX_BINDERS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/functions.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// Binders +// +// There are times when it is desireable to bind a simple functor, +// function, member function or member variable for deferred +// evaluation. This can be done through the binding facilities +// provided below. There are template classes: +// +// 1) function_ptr ( function pointer binder ) +// 2) functor ( functor pointer binder ) +// 3) member_function_ptr ( member function pointer binder ) +// 4) member_var_ptr ( member variable pointer binder ) +// +// These template classes are specialized lazy function classes for +// functors, function pointers, member function pointers and member +// variable pointers, respectively. These are subclasses of the +// lazy-function class (see functions.hpp). Each of these has a +// corresponding overloaded bind(x) function. Each bind(x) function +// generates a suitable binder object. +// +// Example, given a function foo: +// +// void foo_(int n) { std::cout << n << std::endl; } +// +// Here's how the function foo is bound: +// +// bind(&foo_) +// +// This bind expression results to a lazy-function (see +// functions.hpp) that is lazily evaluated. This bind expression is +// also equivalent to: +// +// function_ptr foo = &foo_; +// +// The template parameter of the function_ptr is the return and +// argument types of actual signature of the function to be bound +// read from left to right: +// +// void foo_(int); ---> function_ptr +// +// Either bind(&foo_) and its equivalent foo can now be used in the +// same way a lazy function (see functions.hpp) is used: +// +// bind(&foo_)(arg1) +// +// or +// +// foo(arg1) +// +// The latter, of course, being much easier to understand. This is +// now a full-fledged lazy function that can finally be evaluated +// by another function call invocation. A second function call will +// invoke the actual foo function: +// +// int i = 4; +// foo(arg1)(i); +// +// will print out "4". +// +// Binding functors and member functions can be done similarly. +// Here's how to bind a functor (e.g. std::plus): +// +// bind(std::plus()) +// +// or +// +// functor > plus; +// +// Again, these are full-fledged lazy functions. In this case, +// unlike the first example, expect 2 arguments (std::plus +// needs two arguments lhs and rhs). Either or both of which can be +// lazily bound: +// +// plus(arg1, arg2) // arg1 + arg2 +// plus(100, arg1) // 100 + arg1 +// plus(100, 200) // 300 +// +// A bound member function takes in a pointer or reference to an +// object as the first argument. For instance, given: +// +// struct xyz { void foo(int) const; }; +// +// xyz's foo member function can be bound as: +// +// bind(&xyz::foo) +// +// or +// +// member_function_ptr xyz_foo = &xyz::foo; +// +// The template parameter of the member_function_ptr is the return, +// class and argument types of actual signature of the function to +// be bound read from left to right: +// +// void xyz::foo_(int); ---> member_function_ptr +// +// Take note that a member_function_ptr lazy-function expects the +// first argument to be a pointer or reference to an object. Both +// the object (reference or pointer) and the arguments can be +// lazily bound. Examples: +// +// xyz obj; +// xyz_foo(arg1, arg2) // arg1.foo(arg2) +// xyz_foo(obj, arg1) // obj.foo(arg1) +// xyz_foo(obj, 100) // obj.foo(100) +// +// Be reminded that var(obj) must be used to call non-const member +// functions. For example, if xyz was declared as: +// +// struct xyz { void foo(int); }; +// +// the pointer or reference to the object must also be non-const. +// Lazily bound arguments are stored as const value by default (see +// variable class in primitives.hpp). +// +// xyz_foo(var(obj), 100) // obj.foo(100) +// +// Finally, member variables can be bound much like member +// functions. For instance, given: +// +// struct xyz { int v; }; +// +// xyz::v can be bound as: +// +// bind(&xyz::v) +// or +// +// member_var_ptr xyz_v = &xyz::v; +// +// The template parameter of the member_var_ptr is the type of the +// variable followed by the class: +// +// int xyz::v; ---> member_var_ptr +// +// Just like the member_function_ptr, member_var_ptr also expects +// the first argument to be a pointer or reference to an object. +// Both the object (reference or pointer) and the arguments can be +// lazily bound. Examples: +// +// xyz obj; +// xyz_v(arg1) // arg1.v +// xyz_v(obj) // obj.v +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// Functor binder +// +/////////////////////////////////////////////////////////////////////////////// +template +struct functor_action : public FuncT { + +#if !defined(__BORLANDC__) && (!defined(__MWERKS__) || (__MWERKS__ > 0x3002)) + + template < + typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + > + struct result { typedef typename FuncT::result_type type; }; +#endif + + functor_action(FuncT fptr_ = FuncT()) + : FuncT(fptr_) {} +}; + +#if defined(__BORLANDC__) || (defined(__MWERKS__) && (__MWERKS__ <= 0x3002)) + +/////////////////////////////////////////////////////////////////////////////// +// +// The following specializations are needed because Borland and CodeWarrior +// does not accept default template arguments in nested template classes in +// classes (i.e functor_action::result) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite0_result, TupleT> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite1_result, TupleT, A> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite2_result, TupleT, A, B> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite3_result, TupleT, A, B, C> { + + typedef typename FuncT::result_type type; +}; + +#if PHOENIX_LIMIT > 3 +////////////////////////////////// +template +struct composite4_result, TupleT, + A, B, C, D> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite5_result, TupleT, + A, B, C, D, E> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite6_result, TupleT, + A, B, C, D, E, F> { + + typedef typename FuncT::result_type type; +}; + +#if PHOENIX_LIMIT > 6 +////////////////////////////////// +template +struct composite7_result, TupleT, + A, B, C, D, E, F, G> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite8_result, TupleT, + A, B, C, D, E, F, G, H> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite9_result, TupleT, + A, B, C, D, E, F, G, H, I> { + + typedef typename FuncT::result_type type; +}; + +#if PHOENIX_LIMIT > 9 +////////////////////////////////// +template +struct composite10_result, TupleT, + A, B, C, D, E, F, G, H, I, J> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite11_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite12_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L> { + + typedef typename FuncT::result_type type; +}; + +#if PHOENIX_LIMIT > 12 +////////////////////////////////// +template +struct composite13_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L, M> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite14_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L, M, N> { + + typedef typename FuncT::result_type type; +}; + +////////////////////////////////// +template +struct composite15_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> { + + typedef typename FuncT::result_type type; +}; + +#endif +#endif +#endif +#endif +#endif + +////////////////////////////////// +template +struct functor : public function > { + + functor(FuncT func) + : function >(functor_action(func)) {}; +}; + +////////////////////////////////// +template +inline functor +bind(FuncT func) +{ + return functor(func); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member variable pointer binder +// +/////////////////////////////////////////////////////////////////////////////// +namespace impl { + + ////////////////////////////////// + template + struct as_ptr { + + typedef T* pointer_type; + + static T* get(T& ref) + { return &ref; } + }; + + ////////////////////////////////// + template + struct as_ptr { + + typedef T* pointer_type; + + static T* get(T* ptr) + { return ptr; } + }; +} + +////////////////////////////////// +template +struct member_var_ptr_action_result { + + typedef typename ActionT::template result::type type; +}; + +////////////////////////////////// +template +struct member_var_ptr_action { + + typedef member_var_ptr_action self_t; + + template + struct result { + + typedef char is_const[boost::is_const::value ? 1 : 2]; + typedef typename impl::if_t::type type; + }; + + typedef T ClassT::*mem_var_ptr_t; + + member_var_ptr_action(mem_var_ptr_t ptr_) + : ptr(ptr_) {} + + template + typename member_var_ptr_action_result::type + operator()(CT& obj) const + { return impl::as_ptr::get(obj)->*ptr; } + + mem_var_ptr_t ptr; +}; + +////////////////////////////////// +template +struct member_var_ptr +: public function > { + + member_var_ptr(T ClassT::*mp) + : function > + (member_var_ptr_action(mp)) {} +}; + +////////////////////////////////// +template +inline member_var_ptr +bind(T ClassT::*mp) +{ + return member_var_ptr(mp); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (main class) +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename RT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + + , typename NU = nil_t // Not used +> +struct function_ptr_action; + +////////////////////////////////// +template < + typename RT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif +> +struct function_ptr +: public function 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > > { + + typedef function_ptr_action 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > action_t; + + template + function_ptr(FPT fp) + : function(action_t(fp)) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 0 arg) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(); + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()() const + { return fptr(); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)()) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 1 arg) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A); + + template + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()(A a) const + { return fptr(a); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 2 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B); + + template + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()(A a, B b) const + { return fptr(a, b); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 3 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C); + + template + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()(A a, B b, C c) const + { return fptr(a, b, c); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C)) +{ + return function_ptr(fptr); +} + +#if PHOENIX_LIMIT > 3 +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 4 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D); + + template + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()(A a, B b, C c, D d) const + { return fptr(a, b, c, d); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 5 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e + ) const + { return fptr(a, b, c, d, e); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 6 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f + ) const + { return fptr(a, b, c, d, e, f); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F)) +{ + return function_ptr(fptr); +} + +#if PHOENIX_LIMIT > 6 +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 7 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g + ) const + { return fptr(a, b, c, d, e, f, g); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 8 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h + ) const + { return fptr(a, b, c, d, e, f, g, h); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 9 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i + ) const + { return fptr(a, b, c, d, e, f, g, h, i); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I)) +{ + return function_ptr(fptr); +} + +#if PHOENIX_LIMIT > 9 +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 10 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I, J); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_, typename J_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i, J j + ) const + { return fptr(a, b, c, d, e, f, g, h, i, j); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I, J)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 11 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_, typename J_, + typename K_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i, J j, + K k + ) const + { return fptr(a, b, c, d, e, f, g, h, i, j, k); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I, J, K)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 12 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_, typename J_, + typename K_, typename L_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i, J j, + K k, L l + ) const + { return fptr(a, b, c, d, e, f, g, h, i, j, k, l); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I, J, K, L)) +{ + return function_ptr(fptr); +} + +#if PHOENIX_LIMIT > 12 +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 13 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_, typename J_, + typename K_, typename L_, typename M_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i, J j, + K k, L l, M m + ) const + { return fptr(a, b, c, d, e, f, g, h, i, j, k, l, m); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 14 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M, N); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_, typename J_, + typename K_, typename L_, typename M_, typename N_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i, J j, + K k, L l, M m, N n + ) const + { return fptr(a, b, c, d, e, f, g, h, i, j, k, l, m, n); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N)) +{ + return function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Function pointer binder (specialization for 15 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function_ptr_action { + + typedef RT result_type; + typedef RT(*func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); + + template < + typename A_, typename B_, typename C_, typename D_, typename E_, + typename F_, typename G_, typename H_, typename I_, typename J_, + typename K_, typename L_, typename M_, typename N_, typename O_ + > + struct result { typedef result_type type; }; + + function_ptr_action(func_ptr_t fptr_) + : fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, + F f, G g, H h, I i, J j, + K k, L l, M m, N n, O o + ) const + { return fptr(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); } + + func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline function_ptr +bind(RT(*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)) +{ + return function_ptr(fptr); +} + +#endif +#endif +#endif +#endif +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (main class) +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename RT, + typename ClassT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + + , typename NU = nil_t // Not used +> +struct member_function_ptr_action; + +////////////////////////////////// +template < + typename RT, + typename ClassT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif +> +struct member_function_ptr +: public function 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > > { + + typedef member_function_ptr_action 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > action_t; + + template + member_function_ptr(FPT fp) + : function(action_t(fp)) {} +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 0 arg) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj) const + { return (impl::as_ptr::get(obj)->*fptr)(); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)()) +{ + return member_function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 1 arg) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, A a) const + { return (impl::as_ptr::get(obj)->*fptr)(a); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A)) +{ + return member_function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 2 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, A a, B b) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B)) +{ + return member_function_ptr(fptr); +} + +#if PHOENIX_LIMIT > 3 +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 3 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, A a, B b, C c) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C)) +{ + return member_function_ptr(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 4 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d + ) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c, d); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 5 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e + ) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c, d, e); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E>(fptr); +} + +#if PHOENIX_LIMIT > 6 +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 6 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f + ) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c, d, e, f); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 7 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g + ) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c, d, e, f, g); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 8 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h + ) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c, d, e, f, g, h); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H>(fptr); +} + +#if PHOENIX_LIMIT > 9 +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 9 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i + ) const + { return (impl::as_ptr::get(obj)->*fptr)(a, b, c, d, e, f, g, h, i); } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 10 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j + ) const + { + return (impl::as_ptr::get(obj)->*fptr) + (a, b, c, d, e, f, g, h, i, j); + } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I, J>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 11 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k + ) const + { + return (impl::as_ptr::get(obj)->*fptr) + (a, b, c, d, e, f, g, h, i, j, k); + } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K>(fptr); +} + +#if PHOENIX_LIMIT > 12 +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 12 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l + ) const + { + return (impl::as_ptr::get(obj)->*fptr) + (a, b, c, d, e, f, g, h, i, j, k, l); + } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 13 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m + ) const + { + return (impl::as_ptr::get(obj)->*fptr) + (a, b, c, d, e, f, g, h, i, j, k, l, m); + } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M>(fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 14 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M, N); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n + ) const + { + return (impl::as_ptr::get(obj)->*fptr) + (a, b, c, d, e, f, g, h, i, j, k, l, m, n); + } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M, N>(fptr); +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Member function pointer binder (specialization for 15 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct member_function_ptr_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); + + template + struct result { typedef result_type type; }; + + member_function_ptr_action(mem_func_ptr_t fptr_) + : fptr(fptr_) {} + + template + result_type operator()(CT& obj, + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o + ) const + { + return (impl::as_ptr::get(obj)->*fptr) + (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); + } + + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline member_function_ptr +bind(RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)) +{ + return member_function_ptr< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(fptr); +} + +#endif +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (main class) +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename RT, + typename ClassT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + + , typename NU = nil_t // Not used +> +struct bound_member_action; + +////////////////////////////////// +template < + typename RT, + typename ClassT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif +> +struct bound_member +: public function 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > > { + + typedef bound_member_action 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > action_t; + + template + bound_member(CT & c, FPT fp) + : function(action_t(c,fp)) {} + +#if ! defined(__BORLANDC__) + template + bound_member(CT * c, FPT fp) + : function(action_t(c,fp)) {} +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 0 arg) +// +/////////////////////////////////////////////////////////////////////////////// + +template +struct bound_member_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(); + + template + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()() const + { return (obj->*fptr)(); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// + +template +inline bound_member +bind(ClassT & obj, RT(ClassT::*fptr)()) +{ + return bound_member(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj, RT(ClassT::*fptr)()) +{ + return bound_member(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 1 arg) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A); + + template + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()(A a) const + { return (obj->*fptr)(a); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj, RT(ClassT::*fptr)(A)) +{ + return bound_member(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj, RT(ClassT::*fptr)(A)) +{ + return bound_member(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 2 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B); + + template + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()(A a, B b) const + { return (obj->*fptr)(a, b); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B)) +{ + return bound_member(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B)) +{ + return bound_member(obj,fptr); +} + +#if PHOENIX_LIMIT > 3 +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 3 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C); + + template + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()(A a, B b, C c) const + { return (obj->*fptr)(a, b, c); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C)) +{ + return bound_member(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C)) +{ + return bound_member(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 4 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D); + + template + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()(A a, B b, C c, D d) const + { return (obj->*fptr)(a, b, c, d); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D)) +{ + return bound_member< + RT, ClassT, A, B, C, D>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D)) +{ + return bound_member< + RT, ClassT, A, B, C, D>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 5 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E); + + template + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e + ) const + { return (obj->*fptr)(a, b, c, d, e); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E>(obj,fptr); +} + +#if PHOENIX_LIMIT > 6 +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 6 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f + ) const + { return (obj->*fptr)(a, b, c, d, e, f); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 7 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g + ) const + { return (obj->*fptr)(a, b, c, d, e, f, g); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 8 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h + ) const + { return (obj->*fptr)(a, b, c, d, e, f, g, h); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H>(obj,fptr); +} + +#if PHOENIX_LIMIT > 9 +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 9 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i + ) const + { return (obj->*fptr)(a, b, c, d, e, f, g, h, i); } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 10 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_, + typename J_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j + ) const + { + return (obj->*fptr)(a, b, c, d, e, f, g, h, i, j); + } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 11 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_, + typename J_, typename K_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k + ) const + { + return (obj->*fptr)(a, b, c, d, e, f, g, h, i, j, k); + } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K>(obj,fptr); +} + +#if PHOENIX_LIMIT > 12 +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 12 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_, + typename J_, typename K_, typename L_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l + ) const + { + return (obj->*fptr)(a, b, c, d, e, f, g, h, i, j, k, l); + } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 13 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_, + typename J_, typename K_, typename L_, typename M_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m + ) const + { + return (obj->*fptr)(a, b, c, d, e, f, g, h, i, j, k, l, m); + } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 14 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M, N); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_, + typename J_, typename K_, typename L_, typename M_, typename N_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n + ) const + { + return (obj->*fptr)(a, b, c, d, e, f, g, h, i, j, k, l, m, n); + } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M, N>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M, N>(obj,fptr); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Bound member function binder (specialization for 15 args) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct bound_member_action { + + typedef RT result_type; + typedef RT(ClassT::*mem_func_ptr_t)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); + + template < + typename A_, typename B_, typename C_, typename D_, + typename E_, typename F_, typename G_, typename H_, typename I_, + typename J_, typename K_, typename L_, typename M_, typename N_, + typename O_ + > + struct result { typedef result_type type; }; + + template + bound_member_action(CT & obj_, mem_func_ptr_t fptr_) + : obj(impl::as_ptr::get(obj_)), fptr(fptr_) {} + + result_type operator()( + A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o + ) const + { + return (obj->*fptr)(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); + } + + typename impl::as_ptr::pointer_type obj; + mem_func_ptr_t fptr; +}; + +////////////////////////////////// +template +inline bound_member +bind(ClassT & obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(obj,fptr); +} + +template +inline bound_member +bind(ClassT * obj,RT(ClassT::*fptr)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)) +{ + return bound_member< + RT, ClassT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(obj,fptr); +} + +#endif +#endif +#endif +#endif + +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/casts.hpp b/include/boost/spirit/phoenix/casts.hpp new file mode 100644 index 000000000..ccc9aa5d2 --- /dev/null +++ b/include/boost/spirit/phoenix/casts.hpp @@ -0,0 +1,1292 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ + +#ifndef PHOENIX_CASTS_HPP +#define PHOENIX_CASTS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/actor.hpp" +#include "boost/spirit/phoenix/composite.hpp" +#include "boost/static_assert.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// Phoenix predefined maximum construct_ limit. This limit defines the maximum +// number of parameters supported for calles to the set of construct_ template +// functions (lazy object construction, see below). This number defaults to 3. +// The actual maximum is rounded up in multiples of 3. Thus, if this value +// is 4, the actual limit is 6. The ultimate maximum limit in this +// implementation is 15. +// PHOENIX_CONSTRUCT_LIMIT should NOT be greater than PHOENIX_LIMIT! + +#if !defined(PHOENIX_CONSTRUCT_LIMIT) +#define PHOENIX_CONSTRUCT_LIMIT PHOENIX_LIMIT +#endif + +// ensure PHOENIX_CONSTRUCT_LIMIT <= PHOENIX_LIMIT +BOOST_STATIC_ASSERT(PHOENIX_CONSTRUCT_LIMIT <= PHOENIX_LIMIT); + +// ensure PHOENIX_CONSTRUCT_LIMIT <= 15 +BOOST_STATIC_ASSERT(PHOENIX_CONSTRUCT_LIMIT <= 15); + +/////////////////////////////////////////////////////////////////////////////// +// +// Lazy C++ casts +// +// The set of lazy C++ cast template classes and functions provide a way +// of lazily casting certain type to another during parsing. +// The lazy C++ templates are (syntactically) used very much like +// the well known C++ casts: +// +// A *a = static_cast_(...actor returning a convertible type...); +// +// where the given parameter should be an actor, which eval() function +// returns a convertible type. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct static_cast_l { + + template + struct result { typedef T type; }; + + static_cast_l(A const& a_) + : a(a_) {} + + template + T + eval(TupleT const& args) const + { + return static_cast(a.eval(args)); + } + + A a; +}; + +////////////////////////////////// +template +inline actor > +static_cast_(actor const& a) +{ + typedef static_cast_l cast_t; + return actor(cast_t(a)); +} + +////////////////////////////////// +template +struct dynamic_cast_l { + + template + struct result { typedef T type; }; + + dynamic_cast_l(A const& a_) + : a(a_) {} + + template + T + eval(TupleT const& args) const + { + return dynamic_cast(a.eval(args)); + } + + A a; +}; + +////////////////////////////////// +template +inline actor > +dynamic_cast_(actor const& a) +{ + typedef dynamic_cast_l cast_t; + return actor(cast_t(a)); +} + +////////////////////////////////// +template +struct reinterpret_cast_l { + + template + struct result { typedef T type; }; + + reinterpret_cast_l(A const& a_) + : a(a_) {} + + template + T + eval(TupleT const& args) const + { + return reinterpret_cast(a.eval(args)); + } + + A a; +}; + +////////////////////////////////// +template +inline actor > +reinterpret_cast_(actor const& a) +{ + typedef reinterpret_cast_l cast_t; + return actor(cast_t(a)); +} + +////////////////////////////////// +template +struct const_cast_l { + + template + struct result { typedef T type; }; + + const_cast_l(A const& a_) + : a(a_) {} + + template + T + eval(TupleT const& args) const + { + return const_cast(a.eval(args)); + } + + A a; +}; + +////////////////////////////////// +template +inline actor > +const_cast_(actor const& a) +{ + typedef const_cast_l cast_t; + return actor(cast_t(a)); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// construct_ +// +// Lazy object construction +// +// The set of construct_<> template classes and functions provide a way +// of lazily constructing certain object from a arbitrary set of +// actors during parsing. +// The construct_ templates are (syntactically) used very much like +// the well known C++ casts: +// +// A a = construct_(...arbitrary list of actors...); +// +// where the given parameters are submitted as parameters to the +// contructor of the object of type A. (This certainly implies, that +// type A has a constructor with a fitting set of parameter types +// defined.) +// +// The maximum number of needed parameters is controlled through the +// preprocessor constant PHOENIX_CONSTRUCT_LIMIT. Note though, that this +// limit should not be greater than PHOENIX_LIMIT. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct construct_l { + + template < + typename A + , typename B + , typename C + +#if PHOENIX_CONSTRUCT_LIMIT > 3 + , typename D + , typename E + , typename F + +#if PHOENIX_CONSTRUCT_LIMIT > 6 + , typename G + , typename H + , typename I + +#if PHOENIX_CONSTRUCT_LIMIT > 9 + , typename J + , typename K + , typename L + +#if PHOENIX_CONSTRUCT_LIMIT > 12 + , typename M + , typename N + , typename O +#endif +#endif +#endif +#endif + > + struct result { typedef T type; }; + + T operator()() const { + return T(); + } + + template + T operator()(A const& a) const { + return T(a); + } + + template + T operator()(A const& a, B const& b) const { + return T(a, b); + } + + template + T operator()(A const& a, B const& b, C const& c) const { + return T(a, b, c); + } + +#if PHOENIX_CONSTRUCT_LIMIT > 3 + template < + typename A, typename B, typename C, typename D + > + T operator()( + A const& a, B const& b, C const& c, D const& d) const + { + return T(a, b, c, d); + } + + template < + typename A, typename B, typename C, typename D, typename E + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e) const + { + return T(a, b, c, d, e); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f) const + { + return T(a, b, c, d, e, f); + } + +#if PHOENIX_CONSTRUCT_LIMIT > 6 + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g) const + { + return T(a, b, c, d, e, f, g); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h) const + { + return T(a, b, c, d, e, f, g, h); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i) const + { + return T(a, b, c, d, e, f, g, h, i); + } + +#if PHOENIX_CONSTRUCT_LIMIT > 9 + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j) const + { + return T(a, b, c, d, e, f, g, h, i, j); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k) const + { + return T(a, b, c, d, e, f, g, h, i, j, k); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l) const + { + return T(a, b, c, d, e, f, g, h, i, j, k, l); + } + +#if PHOENIX_CONSTRUCT_LIMIT > 12 + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m) const + { + return T(a, b, c, d, e, f, g, h, i, j, k, l, m); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n) const + { + return T(a, b, c, d, e, f, g, h, i, j, k, l, m, n); + } + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n, O const& o) const + { + return T(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); + } + +#endif +#endif +#endif +#endif +}; + + +template +struct construct_1 { + + template < + typename A + > + struct result { typedef T type; }; + + template + T operator()(A const& a) const { + return T(a); + } + +}; + +template +struct construct_2 { + + template < + typename A + , typename B + > + struct result { typedef T type; }; + + template + T operator()(A const& a, B const& b) const { + return T(a, b); + } + +}; + +template +struct construct_3 { + + template < + typename A + , typename B + , typename C + > + struct result { typedef T type; }; + + template + T operator()(A const& a, B const& b, C const& c) const { + return T(a, b, c); + } +}; + +#if PHOENIX_CONSTRUCT_LIMIT > 3 +template +struct construct_4 { + + template < + typename A + , typename B + , typename C + , typename D + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D + > + T operator()( + A const& a, B const& b, C const& c, D const& d) const + { + return T(a, b, c, d); + } +}; + + +template +struct construct_5 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + > + struct result { typedef T type; }; + + template < + typename A, typename B, typename C, typename D, typename E + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e) const + { + return T(a, b, c, d, e); + } +}; + + +template +struct construct_6 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + > + struct result { typedef T type; }; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f) const + { + return T(a, b, c, d, e, f); + } +}; +#endif + + +#if PHOENIX_CONSTRUCT_LIMIT > 6 +template +struct construct_7 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + > + struct result { typedef T type; }; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g) const + { + return T(a, b, c, d, e, f, g); + } +}; + +template +struct construct_8 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + > + struct result { typedef T type; }; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h) const + { + return T(a, b, c, d, e, f, g, h); + } +}; + +template +struct construct_9 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + > + struct result { typedef T type; }; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i) const + { + return T(a, b, c, d, e, f, g, h, i); + } +}; +#endif + + +#if PHOENIX_CONSTRUCT_LIMIT > 9 +template +struct construct_10 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + , typename J + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j) const + { + return T(a, b, c, d, e, f, g, h, i, j); + } +}; + +template +struct construct_11 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + , typename J + , typename K + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k) const + { + return T(a, b, c, d, e, f, g, h, i, j, k); + } + +}; + +template +struct construct_12 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + , typename J + , typename K + , typename L + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l) const + { + return T(a, b, c, d, f, e, g, h, i, j, k, l); + } +}; +#endif + +#if PHOENIX_CONSTRUCT_LIMIT > 12 +template +struct construct_13 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + , typename J + , typename K + , typename L + , typename M + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m) const + { + return T(a, b, c, d, e, f, g, h, i, j, k, l, m); + } +}; + +template +struct construct_14 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + , typename J + , typename K + , typename L + , typename M + , typename N + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n) const + { + return T(a, b, c, d, e, f, g, h, i, j, k, l, m, n); + } + +}; + +template +struct construct_15 { + + template < + typename A + , typename B + , typename C + , typename D + , typename E + , typename F + , typename G + , typename H + , typename I + , typename J + , typename K + , typename L + , typename M + , typename N + , typename O + > + struct result { typedef T type; }; + + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O + > + T operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n, O const& o) const + { + return T(a, b, c, d, f, e, g, h, i, j, k, l, m, n, o); + } + +}; +#endif + + +#if defined(__BORLANDC__) || (defined(__MWERKS__) && (__MWERKS__ <= 0x3002)) + +/////////////////////////////////////////////////////////////////////////////// +// +// The following specializations are needed because Borland and CodeWarrior +// does not accept default template arguments in nested template classes in +// classes (i.e construct_l::result) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite0_result, TupleT> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite1_result, TupleT, A> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite2_result, TupleT, A, B> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite3_result, TupleT, A, B, C> { + + typedef T type; +}; + +#if PHOENIX_LIMIT > 3 +////////////////////////////////// +template +struct composite4_result, TupleT, + A, B, C, D> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite5_result, TupleT, + A, B, C, D, E> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite6_result, TupleT, + A, B, C, D, E, F> { + + typedef T type; +}; + +#if PHOENIX_LIMIT > 6 +////////////////////////////////// +template +struct composite7_result, TupleT, + A, B, C, D, E, F, G> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite8_result, TupleT, + A, B, C, D, E, F, G, H> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite9_result, TupleT, + A, B, C, D, E, F, G, H, I> { + + typedef T type; +}; + +#if PHOENIX_LIMIT > 9 +////////////////////////////////// +template +struct composite10_result, TupleT, + A, B, C, D, E, F, G, H, I, J> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite11_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite12_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L> { + + typedef T type; +}; + +#if PHOENIX_LIMIT > 12 +////////////////////////////////// +template +struct composite13_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L, M> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite14_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L, M, N> { + + typedef T type; +}; + +////////////////////////////////// +template +struct composite15_result, TupleT, + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> { + + typedef T type; +}; + +#endif +#endif +#endif +#endif +#endif + +////////////////////////////////// +template +inline typename impl::make_composite >::type +construct_() +{ + typedef impl::make_composite > make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_l())); +} + +////////////////////////////////// +template +inline typename impl::make_composite, A>::type +construct_(A const& a) +{ + typedef impl::make_composite, A> make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_1(), a)); +} + +////////////////////////////////// +template +inline typename impl::make_composite, A, B>::type +construct_(A const& a, B const& b) +{ + typedef impl::make_composite, A, B> make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_2(), a, b)); +} + +////////////////////////////////// +template +inline typename impl::make_composite, A, B, C>::type +construct_(A const& a, B const& b, C const& c) +{ + typedef impl::make_composite, A, B, C> make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_3(), a, b, c)); +} + +#if PHOENIX_CONSTRUCT_LIMIT > 3 +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D +> +inline typename impl::make_composite, A, B, C, D>::type +construct_( + A const& a, B const& b, C const& c, D const& d) +{ + typedef + impl::make_composite, A, B, C, D> + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_4(), a, b, c, d)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E +> +inline typename impl::make_composite, A, B, C, D, E>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e) +{ + typedef + impl::make_composite, A, B, C, D, E> + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_5(), a, b, c, d, e)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F +> +inline typename impl::make_composite, A, B, C, D, E, F>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f) +{ + typedef + impl::make_composite, A, B, C, D, E, F> + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type(construct_6(), a, b, c, d, e, f)); +} + +#if PHOENIX_CONSTRUCT_LIMIT > 6 +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G +> +inline typename impl::make_composite, A, B, C, D, E, F, G>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g) +{ + typedef + impl::make_composite, A, B, C, D, E, F, G> + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_7(), a, b, c, d, e, f, g)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H +> +inline typename impl::make_composite, A, B, C, D, E, F, G, H>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h) +{ + typedef + impl::make_composite, A, B, C, D, E, F, G, H> + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_8(), a, b, c, d, e, f, g, h)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I +> +inline typename impl::make_composite, A, B, C, D, E, F, G, H, I>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i) +{ + typedef + impl::make_composite, A, B, C, D, E, F, G, H, I> + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_9(), a, b, c, d, e, f, g, h, i)); +} + +#if PHOENIX_CONSTRUCT_LIMIT > 9 +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J +> +inline typename impl::make_composite< + construct_10, A, B, C, D, E, F, G, H, I, J>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j) +{ + typedef + impl::make_composite< + construct_10, A, B, C, D, E, F, G, H, I, J + > + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_10(), a, b, c, d, e, f, g, h, i, j)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, typename K +> +inline typename impl::make_composite< + construct_11, A, B, C, D, E, F, G, H, I, J, K>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k) +{ + typedef + impl::make_composite< + construct_11, A, B, C, D, E, F, G, H, I, J, K + > + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_11(), a, b, c, d, e, f, g, h, i, j, k)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, typename K, + typename L +> +inline typename impl::make_composite< + construct_12, A, B, C, D, E, F, G, H, I, J, K, L>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l) +{ + typedef + impl::make_composite< + construct_12, A, B, C, D, E, F, G, H, I, J, K, L + > + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_12(), a, b, c, d, e, f, g, h, i, j, k, l)); +} + +#if PHOENIX_CONSTRUCT_LIMIT > 12 +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, typename K, + typename L, typename M +> +inline typename impl::make_composite< + construct_13, A, B, C, D, E, F, G, H, I, J, K, L, M>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m) +{ + typedef + impl::make_composite< + construct_13, A, B, C, D, E, F, G, H, I, J, K, L, M + > + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_13(), a, b, c, d, e, f, g, h, i, j, k, l, m)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, typename K, + typename L, typename M, typename N +> +inline typename impl::make_composite< + construct_14, A, B, C, D, E, F, G, H, I, J, K, L, M>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n) +{ + typedef + impl::make_composite< + construct_14, A, B, C, D, E, F, G, H, I, J, K, L, M, N + > + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_14(), a, b, c, d, e, f, g, h, i, j, k, l, m, n)); +} + +////////////////////////////////// +template < + typename T, typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, typename K, + typename L, typename M, typename N, typename O +> +inline typename impl::make_composite< + construct_15, A, B, C, D, E, F, G, H, I, J, K, L, M, O>::type +construct_( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n, O const& o) +{ + typedef + impl::make_composite< + construct_15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O + > + make_composite_t; + + return make_composite_t::type( + make_composite_t::composite_type( + construct_15(), a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)); +} + +#endif +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#endif // PHOENIX_CASTS_HPP diff --git a/include/boost/spirit/phoenix/closures.hpp b/include/boost/spirit/phoenix/closures.hpp new file mode 100644 index 000000000..42221c6fa --- /dev/null +++ b/include/boost/spirit/phoenix/closures.hpp @@ -0,0 +1,359 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + MT code Copyright (c) 2002 Martin Wille + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_CLOSURES_HPP +#define PHOENIX_CLOSURES_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "actor.hpp" +#include + +#ifdef PHOENIX_THREADSAFE +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// Adaptable closures +// +// The framework will not be complete without some form of closures +// support. Closures encapsulate a stack frame where local +// variables are created upon entering a function and destructed +// upon exiting. Closures provide an environment for local +// variables to reside. Closures can hold heterogeneous types. +// +// Phoenix closures are true hardware stack based closures. At the +// very least, closures enable true reentrancy in lambda functions. +// A closure provides access to a function stack frame where local +// variables reside. Modeled after Pascal nested stack frames, +// closures can be nested just like nested functions where code in +// inner closures may access local variables from in-scope outer +// closures (accessing inner scopes from outer scopes is an error +// and will cause a run-time assertion failure). +// +// There are three (3) interacting classes: +// +// 1) closure: +// +// At the point of declaration, a closure does not yet create a +// stack frame nor instantiate any variables. A closure declaration +// declares the types and names[note] of the local variables. The +// closure class is meant to be subclassed. It is the +// responsibility of a closure subclass to supply the names for +// each of the local variable in the closure. Example: +// +// struct my_closure : closure { +// +// member1 num; // names the 1st (int) local variable +// member2 message; // names the 2nd (string) local variable +// member3 real; // names the 3rd (double) local variable +// }; +// +// my_closure clos; +// +// Now that we have a closure 'clos', its local variables can be +// accessed lazily using the dot notation. Each qualified local +// variable can be used just like any primitive actor (see +// primitives.hpp). Examples: +// +// clos.num = 30 +// clos.message = arg1 +// clos.real = clos.num * 1e6 +// +// The examples above are lazily evaluated. As usual, these +// expressions return composite actors that will be evaluated +// through a second function call invocation (see operators.hpp). +// Each of the members (clos.xxx) is an actor. As such, applying +// the operator() will reveal its identity: +// +// clos.num() // will return the current value of clos.num +// +// *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB) +// introduced and initilally implemented the closure member names +// that uses the dot notation. +// +// 2) closure_member +// +// The named local variables of closure 'clos' above are actually +// closure members. The closure_member class is an actor and +// conforms to its conceptual interface. member1..memberN are +// predefined typedefs that correspond to each of the listed types +// in the closure template parameters. +// +// 3) closure_frame +// +// When a closure member is finally evaluated, it should refer to +// an actual instance of the variable in the hardware stack. +// Without doing so, the process is not complete and the evaluated +// member will result to an assertion failure. Remember that the +// closure is just a declaration. The local variables that a +// closure refers to must still be instantiated. +// +// The closure_frame class does the actual instantiation of the +// local variables and links these variables with the closure and +// all its members. There can be multiple instances of +// closure_frames typically situated in the stack inside a +// function. Each closure_frame instance initiates a stack frame +// with a new set of closure local variables. Example: +// +// void foo() +// { +// closure_frame frame(clos); +// /* do something */ +// } +// +// where 'clos' is an instance of our closure 'my_closure' above. +// Take note that the usage above precludes locally declared +// classes. If my_closure is a locally declared type, we can still +// use its self_type as a paramater to closure_frame: +// +// closure_frame frame(clos); +// +// Upon instantiation, the closure_frame links the local variables +// to the closure. The previous link to another closure_frame +// instance created before is saved. Upon destruction, the +// closure_frame unlinks itself from the closure and relinks the +// preceding closure_frame prior to this instance. +// +// The local variables in the closure 'clos' above is default +// constructed in the stack inside function 'foo'. Once 'foo' is +// exited, all of these local variables are destructed. In some +// cases, default construction is not desirable and we need to +// initialize the local closure variables with some values. This +// can be done by passing in the initializers in a compatible +// tuple. A compatible tuple is one with the same number of +// elements as the destination and where each element from the +// destination can be constructed from each corresponding element +// in the source. Example: +// +// tuple init(123, "Hello", 1000); +// closure_frame frame(clos, init); +// +// Here now, our closure_frame's variables are initialized with +// int: 123, char const*: "Hello" and int: 1000. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// closure_frame class +// +/////////////////////////////////////////////////////////////////////////////// +template +class closure_frame : public ClosureT::tuple_t { + +public: + + closure_frame(ClosureT const& clos) + : ClosureT::tuple_t(), save(clos.frame), frame(clos.frame) + { clos.frame = this; } + + template + closure_frame(ClosureT const& clos, TupleT const& init) + : ClosureT::tuple_t(init), save(clos.frame), frame(clos.frame) + { clos.frame = this; } + + ~closure_frame() + { frame = save; } + +private: + + closure_frame(closure_frame const&); // no copy + closure_frame& operator=(closure_frame const&); // no assign + + closure_frame* save; + closure_frame*& frame; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// closure_member class +// +/////////////////////////////////////////////////////////////////////////////// +template +class closure_member { + +public: + + typedef typename ClosureT::tuple_t tuple_t; + + closure_member() + : frame(ClosureT::closure_frame_ref()) {} + + template + struct result { + + typedef typename tuple_element< + N, typename ClosureT::tuple_t + >::rtype type; + }; + + template + typename tuple_element::rtype + eval(TupleT const& /*args*/) const + { + using namespace std; + assert(frame != 0); + return (*frame)[tuple_index()]; + } + +private: + + typename ClosureT::closure_frame_t*& frame; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// closure class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename T0 = nil_t + , typename T1 = nil_t + , typename T2 = nil_t + +#if PHOENIX_LIMIT > 3 + , typename T3 = nil_t + , typename T4 = nil_t + , typename T5 = nil_t + +#if PHOENIX_LIMIT > 6 + , typename T6 = nil_t + , typename T7 = nil_t + , typename T8 = nil_t + +#if PHOENIX_LIMIT > 9 + , typename T9 = nil_t + , typename T10 = nil_t + , typename T11 = nil_t + +#if PHOENIX_LIMIT > 12 + , typename T12 = nil_t + , typename T13 = nil_t + , typename T14 = nil_t + +#endif +#endif +#endif +#endif +> +class closure { + +public: + + typedef tuple< + T0, T1, T2 +#if PHOENIX_LIMIT > 3 + , T3, T4, T5 +#if PHOENIX_LIMIT > 6 + , T6, T7, T8 +#if PHOENIX_LIMIT > 9 + , T9, T10, T11 +#if PHOENIX_LIMIT > 12 + , T12, T13, T14 +#endif +#endif +#endif +#endif + > tuple_t; + + typedef closure< + T0, T1, T2 +#if PHOENIX_LIMIT > 3 + , T3, T4, T5 +#if PHOENIX_LIMIT > 6 + , T6, T7, T8 +#if PHOENIX_LIMIT > 9 + , T9, T10, T11 +#if PHOENIX_LIMIT > 12 + , T12, T13, T14 +#endif +#endif +#endif +#endif + > self_t; + + typedef closure_frame closure_frame_t; + + closure() + : frame(0) { closure_frame_ref(&frame); } + closure_frame_t& context() { assert(frame!=0); return frame; } + closure_frame_t const& context() const { assert(frame!=0); return frame; } + + typedef actor > member1; + typedef actor > member2; + typedef actor > member3; + +#if PHOENIX_LIMIT > 3 + typedef actor > member4; + typedef actor > member5; + typedef actor > member6; + +#if PHOENIX_LIMIT > 6 + typedef actor > member7; + typedef actor > member8; + typedef actor > member9; + +#if PHOENIX_LIMIT > 9 + typedef actor > member10; + typedef actor > member11; + typedef actor > member12; + +#if PHOENIX_LIMIT > 12 + typedef actor > member13; + typedef actor > member14; + typedef actor > member15; + +#endif +#endif +#endif +#endif + +#if !defined(__MWERKS__) || (__MWERKS__ > 0x3002) +private: +#endif + + closure(closure const&); // no copy + closure& operator=(closure const&); // no assign + +#if !defined(__MWERKS__) || (__MWERKS__ > 0x3002) + template + friend class closure_member; + + template + friend class closure_frame; +#endif + + static closure_frame_t*& + closure_frame_ref(closure_frame_t** frame_ = 0) + { +#ifdef PHOENIX_THREADSAFE + static boost::thread_specific_ptr tsp_frame; + if (!tsp_frame.get()) + tsp_frame.reset(new closure_frame_t **(0)); + closure_frame_t **& frame = *tsp_frame; +#else + static closure_frame_t** frame = 0; +#endif + if (frame_ != 0) + frame = frame_; + return *frame; + } + + mutable closure_frame_t* frame; +}; + +} + // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/composite.hpp b/include/boost/spirit/phoenix/composite.hpp new file mode 100644 index 000000000..0f0c8df10 --- /dev/null +++ b/include/boost/spirit/phoenix/composite.hpp @@ -0,0 +1,1415 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_COMPOSITE_HPP +#define PHOENIX_COMPOSITE_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/actor.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// composite class +// +// A composite is an actor base class composed of zero or more +// actors (see actor.hpp) and an operation. A composite is itself +// an actor superclass and conforms to its conceptual interface. +// Its eval member function un-funnels the tupled actual arguments +// from the tuple by invoking each of the actors' eval member +// function. The results of each are then passed on as arguments to +// the operation. Specializations are provided to handle different +// numbers of actors. +// +// Schematically: +// +// actor0.eval(tupled_args) --> arg0 --> | +// actor1.eval(tupled_args) --> arg1 --> | +// actor2.eval(tupled_args) --> arg3 --> | --> operation(arg0...argN) +// ... | +// actorN.eval(tupled_args) --> argN --> | +// +// The operation can be any suitable functor that can accept the +// arguments passed in by the composite. The operation is expected +// to have a member operator() that carries out the actual +// operation. There should be a one to one correspondence between +// actors of the composite and the arguments of the operation's +// member operator(). +// +// The operation is also expected to have a nested template class +// result. The nested template class result should have a +// typedef 'type' that reflects the return type of its member +// operator(). This is essentially a type computer that answers the +// metaprogramming question "Given arguments of type T0...TN, what +// will be its operator()'s return type?". +// +// There is a special case for operations that accept no arguments. +// Such nullary operations are only required to define a typedef +// result_type that reflects the return type of its operator(). +// +// Here's an example of a simple operation that squares a number: +// +// struct square { +// +// template +// struct result { typedef ArgT type; }; +// +// template +// ArgT operator()(ArgT n) const { return n * n; } +// }; +// +// As can be seen, operations can be polymorphic. Its arguments and +// return type are not fixed to a particular type. The example +// above for example, can handle any ArgT type as long as it has a +// multiplication operator. +// +// Composites are not created directly. Instead, there are meta- +// programs provided that indirectly create composites. See +// operators.hpp, binders.hpp and functions.hpp for examples. +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename OperationT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + + , typename NU = nil_t // Not used +> +struct composite; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <0 actor> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite0_result { + + typedef typename OperationT::result_type type; +}; + +////////////////////////////////// +template +struct composite 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite0_result< + OperationT, TupleT + >::type type; + }; + + composite(OperationT const& op_) + : op(op_) {} + + template + typename OperationT::result_type + eval(TupleT const& /*args*/) const + { + return op(); + } + + mutable OperationT op; // operation +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <1 actor> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite1_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite1_result< + OperationT, TupleT, A + >::type type; + }; + + composite(OperationT const& op_, + A const& a_) + : op(op_), a(a_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + return op(ra); + } + + mutable OperationT op; // operation + A a; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <2 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite2_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite2_result< + OperationT, TupleT, A, B + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_) + : op(op_), a(a_), b(b_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + return op(ra, rb); + } + + mutable OperationT op; // operation + A a; B b; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <3 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite3_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite3_result< + OperationT, TupleT, A, B, C + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_) + : op(op_), a(a_), b(b_), c(c_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + return op(ra, rb, rc); + } + + mutable OperationT op; // operation + A a; B b; C c; // actors +}; + +#if PHOENIX_LIMIT > 3 +/////////////////////////////////////////////////////////////////////////////// +// +// composite <4 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite4_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite4_result< + OperationT, TupleT, A, B, C, D + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_) + : op(op_), a(a_), b(b_), c(c_), d(d_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + return op(ra, rb, rc, rd); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <5 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite5_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite5_result< + OperationT, TupleT, A, B, C, D, E + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + return op(ra, rb, rc, rd, re); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <6 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite6_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite6_result< + OperationT, TupleT, A, B, C, D, E, F + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + return op(ra, rb, rc, rd, re, rf); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; // actors +}; + +#if PHOENIX_LIMIT > 6 +/////////////////////////////////////////////////////////////////////////////// +// +// composite <7 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite7_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite7_result< + OperationT, TupleT, A, B, C, D, E, F, G + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + return op(ra, rb, rc, rd, re, rf, rg); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <8 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite8_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite8_result< + OperationT, TupleT, A, B, C, D, E, F, G, H + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <9 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite9_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite9_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; // actors +}; + +#if PHOENIX_LIMIT > 9 +/////////////////////////////////////////////////////////////////////////////// +// +// composite <10 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite10_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite10_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I, J + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_, J const& j_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + typename actor_result::type rj = j.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri, rj); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <11 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite11_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite11_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I, J, K + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_, J const& j_, + K const& k_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + typename actor_result::type rj = j.eval(args); + typename actor_result::type rk = k.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; + K k;// actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <12 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite12_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> { + + typedef composite self_t; + + template + struct result { + + typedef typename composite12_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I, J, K, L + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_, J const& j_, + K const& k_, L const& l_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + typename actor_result::type rj = j.eval(args); + typename actor_result::type rk = k.eval(args); + typename actor_result::type rl = l.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; + K k; L l;// actors +}; + +#if PHOENIX_LIMIT > 12 +/////////////////////////////////////////////////////////////////////////////// +// +// composite <13 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite13_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite { + + typedef composite self_t; + + template + struct result { + + typedef typename composite13_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I, J, K, L, M + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_, J const& j_, + K const& k_, L const& l_, M const& m_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_), m(m_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + typename actor_result::type rj = j.eval(args); + typename actor_result::type rk = k.eval(args); + typename actor_result::type rl = l.eval(args); + typename actor_result::type rm = m.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; + K k; L l; M m; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <14 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite14_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite { + + typedef composite self_t; + + template + struct result { + + typedef typename composite14_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I, J, K, L, M, N + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_, J const& j_, + K const& k_, L const& l_, M const& m_, N const& n_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_), m(m_), n(n_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + typename actor_result::type rj = j.eval(args); + typename actor_result::type rk = k.eval(args); + typename actor_result::type rl = l.eval(args); + typename actor_result::type rm = m.eval(args); + typename actor_result::type rn = n.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; + K k; L l; M m; N n; // actors +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// composite <15 actors> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct composite15_result { + + typedef typename OperationT::template result< + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type, + typename actor_result::plain_type + >::type type; +}; + +////////////////////////////////// +template +struct composite { + + typedef composite self_t; + + template + struct result { + + typedef typename composite15_result< + OperationT, TupleT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O + >::type type; + }; + + composite(OperationT const& op_, + A const& a_, B const& b_, C const& c_, D const& d_, E const& e_, + F const& f_, G const& g_, H const& h_, I const& i_, J const& j_, + K const& k_, L const& l_, M const& m_, N const& n_, O const& o_) + : op(op_), a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_), m(m_), n(n_), o(o_) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + typename actor_result::type ra = a.eval(args); + typename actor_result::type rb = b.eval(args); + typename actor_result::type rc = c.eval(args); + typename actor_result::type rd = d.eval(args); + typename actor_result::type re = e.eval(args); + typename actor_result::type rf = f.eval(args); + typename actor_result::type rg = g.eval(args); + typename actor_result::type rh = h.eval(args); + typename actor_result::type ri = i.eval(args); + typename actor_result::type rj = j.eval(args); + typename actor_result::type rk = k.eval(args); + typename actor_result::type rl = l.eval(args); + typename actor_result::type rm = m.eval(args); + typename actor_result::type rn = n.eval(args); + typename actor_result::type ro = o.eval(args); + return op(ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl, rm, rn, ro); + } + + mutable OperationT op; // operation + A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; + K k; L l; M m; N n; O o; // actors +}; + +#endif +#endif +#endif +#endif + +namespace impl { + + /////////////////////////////////////////////////////////////////////////// + // + // make_composite is basically a type computer that answers the + // question "Given types T0..TN, what composite type should I + // create and if I were to generate an actual + // composite, what type should I return?" + // + /////////////////////////////////////////////////////////////////////////// + template < + typename OperationT + , typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + > + struct make_composite { + + typedef composite::type + , typename as_actor::type + , typename as_actor::type + +#if PHOENIX_LIMIT > 3 + , typename as_actor::type + , typename as_actor::type + , typename as_actor::type + +#if PHOENIX_LIMIT > 6 + , typename as_actor::type + , typename as_actor::type + , typename as_actor::type + +#if PHOENIX_LIMIT > 9 + , typename as_actor::type + , typename as_actor::type + , typename as_actor::type + +#if PHOENIX_LIMIT > 12 + , typename as_actor::type + , typename as_actor::type + , typename as_actor::type + +#endif +#endif +#endif +#endif + > composite_type; + + typedef actor type; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // make_unary, make_binary, make_binary1, make_binary2 and + // make_binary3 utilities are provided here for easy creation of + // unary and binary composites. + // + /////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////// input is an actor + template + struct make_unary { + + typedef typename make_composite + >::type type; + + static type + construct(actor const& _0) + { + return impl::make_composite + >::composite_type + (OperationT(), _0); + } + }; + + ////////////////////////////////// LHS is an actor, RHS is unknown + template + struct make_binary1 { + + typedef typename make_composite + , B>::type type; + + static type + construct(actor const& _0, B const& _1) + { + return impl::make_composite + , B>::composite_type + (OperationT(), _0, as_actor::convert(_1)); + } + }; + + ////////////////////////////////// LHS is unknown, RHS is an actor + template + struct make_binary2 { + + typedef typename make_composite + >::type type; + + static type + construct(A const& _0, actor const& _1) + { + return impl::make_composite + >::composite_type + (OperationT(), as_actor::convert(_0), _1); + } + }; + + ////////////////////////////////// Both LHS and RHS are actors + template + struct make_binary3 { + + typedef typename make_composite + , actor >::type type; + + static type + construct(actor const& _0, actor const& _1) + { + return impl::make_composite + , actor >::composite_type + (OperationT(), _0, _1); + } + }; +} + +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/functions.hpp b/include/boost/spirit/phoenix/functions.hpp new file mode 100644 index 000000000..d45a3eb6c --- /dev/null +++ b/include/boost/spirit/phoenix/functions.hpp @@ -0,0 +1,743 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_FUNCTIONS_HPP +#define PHOENIX_FUNCTIONS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/actor.hpp" +#include "boost/spirit/phoenix/composite.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// function class +// +// Lazy functions +// +// This class provides a mechanism for lazily evaluating functions. +// Syntactically, a lazy function looks like an ordinary C/C++ +// function. The function call looks the same. However, unlike +// ordinary functions, the actual function execution is deferred. +// (see actor.hpp, primitives.hpp and composite.hpp for an +// overview). For example here are sample factorial function calls: +// +// factorial(4) +// factorial(arg1) +// factorial(arg1 * 6) +// +// These functions are automatically lazily bound unlike ordinary +// function pointers or functor objects that need to be explicitly +// bound through the bind function (see binders.hpp). +// +// A lazy function works in conjunction with a user defined functor +// (as usual with a member operator()). Only special forms of +// functor objects are allowed. This is required to enable true +// polymorphism (STL style monomorphic functors and function +// pointers can still be used through the bind facility in +// binders.hpp). +// +// This special functor is expected to have a nested template class +// result (where N is the number of arguments of its +// member operator()). The nested template class result should have +// a typedef 'type' that reflects the return type of its member +// operator(). This is essentially a type computer that answers the +// metaprogramming question "Given arguments of type A...TN, what +// will be the operator()'s return type?". +// +// There is a special case for functors that accept no arguments. +// Such nullary functors are only required to define a typedef +// result_type that reflects the return type of its operator(). +// +// Here's an example of a simple functor that computes the +// factorial of a number: +// +// struct factorial_impl { +// +// template +// struct result { typedef Arg type; }; +// +// template +// Arg operator()(Arg n) const +// { return (n <= 0) ? 1 : n * this->operator()(n-1); } +// }; +// +// As can be seen, the functor can be polymorphic. Its arguments +// and return type are not fixed to a particular type. The example +// above for example, can handle any type as long as it can carry +// out the required operations (i.e. <=, * and -). +// +// We can now declare and instantiate a lazy 'factorial' function: +// +// function factorial; +// +// Invoking a lazy function 'factorial' does not immediately +// execute the functor factorial_impl. Instead, a composite (see +// composite.hpp) object is created and returned to the caller. +// Example: +// +// factorial(arg1) +// +// does nothing more than return a composite. A second function +// call will invoke the actual factorial function. Example: +// +// int i = 4; +// cout << factorial(arg1)(i); +// +// will print out "24". +// +// Take note that in certain cases (e.g. for functors with state), +// an instance may be passed on to the constructor. Example: +// +// function factorial(ftor); +// +// where ftor is an instance of factorial_impl (this is not +// necessary in this case since factorial is a simple stateless +// functor). Take care though when using functors with state +// because the functors are taken in by value. It is best to keep +// the data manipulated by a functor outside the functor itself and +// keep a reference to this data inside the functor. Also, it is +// best to keep functors as small as possible. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct function { + + function() : op() {} + function(OperationT const& op_) : op(op_) {} + + actor > + operator()() const; + + template + typename impl::make_composite::type + operator()(A const& a) const; + + template + typename impl::make_composite::type + operator()(A const& a, B const& b) const; + + template + typename impl::make_composite::type + operator()(A const& a, B const& b, C const& c) const; + +#if PHOENIX_LIMIT > 3 + + template + typename impl::make_composite::type + operator()(A const& a, B const& b, C const& c, D const& d) const; + + template + typename impl::make_composite< + OperationT, A, B, C, D, E + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f + ) const; + +#if PHOENIX_LIMIT > 6 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i + ) const; + +#if PHOENIX_LIMIT > 9 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l + ) const; + +#if PHOENIX_LIMIT > 12 + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n + ) const; + + template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O + > + typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O + >::type + operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n, O const& o + ) const; + +#endif +#endif +#endif +#endif + + OperationT op; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// function class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline actor > +function::operator()() const +{ + return actor >(op); +} + +////////////////////////////////// +template +template +inline typename impl::make_composite::type +function::operator()(A const& a) const +{ + return impl::make_composite::composite_type + ( + op, + as_actor::convert(a) + ); +} + +////////////////////////////////// +template +template +inline typename impl::make_composite::type +function::operator()(A const& a, B const& b) const +{ + return impl::make_composite::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b) + ); +} + +////////////////////////////////// +template +template +inline typename impl::make_composite::type +function::operator()(A const& a, B const& b, C const& c) const +{ + return impl::make_composite::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c) + ); +} + +#if PHOENIX_LIMIT > 3 +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D +> +inline typename impl::make_composite< + OperationT, A, B, C, D +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d +) const +{ + return impl::make_composite< + OperationT, A, B, C, D + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f) + ); +} + +#if PHOENIX_LIMIT > 6 + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i) + ); +} + +#if PHOENIX_LIMIT > 9 + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i), + as_actor::convert(j) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i), + as_actor::convert(j), + as_actor::convert(k) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i), + as_actor::convert(j), + as_actor::convert(k), + as_actor::convert(l) + ); +} + +#if PHOENIX_LIMIT > 12 + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i), + as_actor::convert(j), + as_actor::convert(k), + as_actor::convert(l), + as_actor::convert(m) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i), + as_actor::convert(j), + as_actor::convert(k), + as_actor::convert(l), + as_actor::convert(m), + as_actor::convert(n) + ); +} + +////////////////////////////////// +template +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O +> +inline typename impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O +>::type +function::operator()( + A const& a, B const& b, C const& c, D const& d, E const& e, + F const& f, G const& g, H const& h, I const& i, J const& j, + K const& k, L const& l, M const& m, N const& n, O const& o +) const +{ + return impl::make_composite< + OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O + >::composite_type + ( + op, + as_actor::convert(a), + as_actor::convert(b), + as_actor::convert(c), + as_actor::convert(d), + as_actor::convert(e), + as_actor::convert(f), + as_actor::convert(g), + as_actor::convert(h), + as_actor::convert(i), + as_actor::convert(j), + as_actor::convert(k), + as_actor::convert(l), + as_actor::convert(m), + as_actor::convert(n), + as_actor::convert(o) + ); +} + +#endif +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/operators.hpp b/include/boost/spirit/phoenix/operators.hpp new file mode 100644 index 000000000..73909ea5a --- /dev/null +++ b/include/boost/spirit/phoenix/operators.hpp @@ -0,0 +1,2215 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_OPERATORS_HPP +#define PHOENIX_OPERATORS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#if !defined(BOOST_NO_CWCTYPE) + #include +#endif + +#ifdef __BORLANDC__ +#define CREF const& +#else +#define CREF +#endif + +#include "boost/spirit/phoenix/actor.hpp" +#include "boost/spirit/phoenix/composite.hpp" +#include "boost/config.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// Operators +// +// Lazy operators +// +// This class provides a mechanism for lazily evaluating operators. +// Syntactically, a lazy operator looks like an ordinary C/C++ +// infix, prefix or postfix operator. The operator application +// looks the same. However, unlike ordinary operators, the actual +// operator execution is deferred. (see actor.hpp, primitives.hpp +// and composite.hpp for an overview). Samples: +// +// arg1 + arg2 +// 1 + arg1 * arg2 +// 1 / -arg1 +// arg1 < 150 +// +// T1 set of classes implement all the C++ free operators. Like +// lazy functions (see functions.hpp), lazy operators are not +// immediately executed when invoked. Instead, a composite (see +// composite.hpp) object is created and returned to the caller. +// Example: +// +// (arg1 + arg2) * arg3 +// +// does nothing more than return a composite. T1 second function +// call will evaluate the actual operators. Example: +// +// int i = 4, j = 5, k = 6; +// cout << ((arg1 + arg2) * arg3)(i, j, k); +// +// will print out "54". +// +// Arbitrarily complex expressions can be lazily evaluated +// following three simple rules: +// +// 1) Lazy evaluated binary operators apply when at least one +// of the operands is an actor object (see actor.hpp and +// primitives.hpp). Consequently, if an operand is not an actor +// object, it is implicitly converted to an object of type +// actor > (where T is the original type of the +// operand). +// +// 2) Lazy evaluated unary operators apply only to operands +// which are actor objects. +// +// 3) The result of a lazy operator is a composite actor object +// that can in turn apply to rule 1. +// +// Example: +// +// arg1 + 3 +// +// is a lazy expression involving the operator+. Following rule 1, +// lazy evaluation is triggered since arg1 is an instance of an +// actor > class (see primitives.hpp). The right +// operand <3> is implicitly converted to an actor >. +// The result of this binary + expression is a composite object, +// following rule 3. +// +// Take note that although at least one of the operands must be a +// valid actor class in order for lazy evaluation to take effect, +// if this is not the case and we still want to lazily evaluate an +// expression, we can use var(x), val(x) or cref(x) to transform +// the operand into a valid action object (see primitives.hpp). +// Example: +// +// val(1) << 3; +// +// Supported operators: +// +// Unary operators: +// +// prefix: ~, !, -, +, ++, --, & (reference), * (dereference) +// postfix: ++, -- +// +// Binary operators: +// +// =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= +// +, -, *, /, %, &, |, ^, <<, >> +// ==, !=, <, >, <=, >= +// &&, || +// +// Each operator has a special tag type associated with it. For +// example the binary + operator has a plus_op tag type associated +// with it. This is used to specialize either the unary_operator or +// binary_operator template classes (see unary_operator and +// binary_operator below). Specializations of these unary_operator +// and binary_operator are the actual workhorses that implement the +// operations. The behavior of each lazy operator depends on these +// unary_operator and binary_operator specializations. 'preset' +// specializations conform to the canonical operator rules modeled +// by the behavior of integers and pointers: +// +// Prefix -, + and ~ accept constant arguments and return an +// object by value. +// +// The ! accept constant arguments and returns a boolean +// result. +// +// The & (address-of), * (dereference) both return a reference +// to an object. +// +// Prefix ++ returns a reference to its mutable argument after +// it is incremented. +// +// Postfix ++ returns the mutable argument by value before it +// is incremented. +// +// The += and its family accept mutable right hand side (rhs) +// operand and return a reference to the rhs operand. +// +// Infix + and its family accept constant arguments and return +// an object by value. +// +// The == and its family accept constant arguments and return a +// boolean result. +// +// Operators && and || accept constant arguments and return a +// boolean result and are short circuit evaluated as expected. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// Operator tags +// +// Each C++ operator has a corresponding tag type. This is +// used as a means for specializing the unary_operator and +// binary_operator (see below). The tag also serves as the +// lazy operator type compatible as a composite operation +// see (composite.hpp). +// +/////////////////////////////////////////////////////////////////////////////// + +// Unary operator tags + +struct negative_op; struct positive_op; +struct logical_not_op; struct invert_op; +struct reference_op; struct dereference_op; +struct pre_incr_op; struct pre_decr_op; +struct post_incr_op; struct post_decr_op; + +// Binary operator tags + +struct assign_op; struct index_op; +struct plus_assign_op; struct minus_assign_op; +struct times_assign_op; struct divide_assign_op; struct mod_assign_op; +struct and_assign_op; struct or_assign_op; struct xor_assign_op; +struct shift_l_assign_op; struct shift_r_assign_op; + +struct plus_op; struct minus_op; +struct times_op; struct divide_op; struct mod_op; +struct and_op; struct or_op; struct xor_op; +struct shift_l_op; struct shift_r_op; + +struct eq_op; struct not_eq_op; +struct lt_op; struct lt_eq_op; +struct gt_op; struct gt_eq_op; +struct logical_and_op; struct logical_or_op; + +/////////////////////////////////////////////////////////////////////////////// +// +// unary_operator +// +// The unary_operator class implements most of the C++ unary +// operators. Each specialization is basically a simple static eval +// function plus a result_type typedef that determines the return +// type of the eval function. +// +// TagT is one of the unary operator tags above and T is the data +// type (argument) involved in the operation. +// +// Only the behavior of C/C++ built-in types are taken into account +// in the specializations provided below. For user-defined types, +// these specializations may still be used provided that the +// operator overloads of such types adhere to the standard behavior +// of built-in types. +// +// T1 separate special_ops.hpp file implements more stl savvy +// specializations. Other more specialized unary_operator +// implementations may be defined by the client for specific +// unary operator tags/data types. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct unary_operator; + +////////////////////////////////// +template +struct unary_operator { + + typedef T const result_type; + static result_type eval(T const& v) + { return -v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T const result_type; + static result_type eval(T const& v) + { return +v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef bool result_type; + static result_type eval(T const& v) + { return !v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T const result_type; + static result_type eval(T const& v) + { return ~v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T* result_type; + static result_type eval(T& v) + { return &v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T& result_type; + static result_type eval(T* v) + { return *v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T& result_type; + static result_type eval(T* const v) + { return *v; } +}; + +////////////////////////////////// +template <> +struct unary_operator { + + // G++ eager template instantiation + // somehow requires this. + typedef nil_t result_type; +}; + +////////////////////////////////// +#ifndef __BORLANDC__ +template <> +struct unary_operator { + + // G++ eager template instantiation + // somehow requires this. + typedef nil_t result_type; +}; +#endif + +////////////////////////////////// +template +struct unary_operator { + + typedef T& result_type; + static result_type eval(T& v) + { return ++v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T& result_type; + static result_type eval(T& v) + { return --v; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T const result_type; + static result_type eval(T& v) + { T t(v); ++v; return t; } +}; + +////////////////////////////////// +template +struct unary_operator { + + typedef T const result_type; + static result_type eval(T& v) + { T t(v); --v; return t; } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// rank +// +// rank class has a static int constant 'value' that defines the +// absolute rank of a type. rank is used to choose the result +// type of binary operators such as +. The type with the higher +// rank wins and is used as the operator's return type. T1 generic +// user defined type has a very high rank and always wins when +// compared against a user defined type. If this is not desireable, +// one can write a rank specialization for the type. +// +// Take note that ranks 0..9999 are reserved for the framework. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct rank { static int const value = INT_MAX; }; + +template <> struct rank { static int const value = 0; }; +template <> struct rank { static int const value = 10; }; + +template <> struct rank { static int const value = 20; }; +template <> struct rank { static int const value = 20; }; +template <> struct rank { static int const value = 30; }; +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +template <> struct rank { static int const value = 40; }; +#endif // !defined(BOOST_NO_INTRINSIC_WCHAR_T) + +template <> struct rank { static int const value = 50; }; +template <> struct rank { static int const value = 60; }; + +template <> struct rank { static int const value = 70; }; +template <> struct rank { static int const value = 80; }; + +template <> struct rank { static int const value = 90; }; +template <> struct rank { static int const value = 100; }; + +#ifdef BOOST_HAS_LONG_LONG +template <> struct rank { static int const value = 110; }; +template <> struct rank { static int const value = 120; }; +#endif + +template <> struct rank { static int const value = 130; }; +template <> struct rank { static int const value = 140; }; +template <> struct rank { static int const value = 150; }; + +template struct rank +{ static int const value = 160; }; + +template struct rank +{ static int const value = 160; }; + +template struct rank +{ static int const value = 160; }; + +/////////////////////////////////////////////////////////////////////////////// +// +// higher_rank +// +// Chooses the type (T0 or T1) with the higher rank. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct higher_rank { + + enum { + + rank1 = rank::value, + rank2 = rank::value, + +#if defined __BORLANDC__ && __BORLANDC__ >= 0x561 + siz = (rank::value < rank::value) ? 1 : 2 +#else + siz = (rank1 < rank2) ? 1 : 2 +#endif + }; + + typedef char compare_rank[siz]; + typedef typename impl::if_t::type type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// binary_operator +// +// The binary_operator class implements most of the C++ binary +// operators. Each specialization is basically a simple static eval +// function plus a result_type typedef that determines the return +// type of the eval function. +// +// TagT is one of the binary operator tags above T0 and T1 are the +// (arguments') data types involved in the operation. +// +// Only the behavior of C/C++ built-in types are taken into account +// in the specializations provided below. For user-defined types, +// these specializations may still be used provided that the +// operator overloads of such types adhere to the standard behavior +// of built-in types. +// +// T1 separate special_ops.hpp file implements more stl savvy +// specializations. Other more specialized unary_operator +// implementations may be defined by the client for specific +// unary operator tags/data types. +// +// All binary_operator except the logical_and_op and logical_or_op +// have an eval static function that carries out the actual operation. +// The logical_and_op and logical_or_op d are special because these +// two operators are short-circuit evaluated. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct binary_operator; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs = rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + // G++ eager template instantiation + // somehow requires this. + typedef nil_t result_type; +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0* ptr, T1 const& index) + { return ptr[index]; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0* const ptr, T1 const& index) + { return ptr[index]; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0* ptr, T1 const& index) + { return ptr[index]; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs += rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs -= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs *= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs /= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs %= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs &= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs |= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs ^= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs <<= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0& result_type; + static result_type eval(T0& lhs, T1 const& rhs) + { return lhs >>= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs + rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs - rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs * rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs / rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs % rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs & rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs | rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef typename higher_rank::type const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs ^ rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0 const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs << rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef T0 const result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs >> rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs == rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs != rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs < rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs <= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs > rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + static result_type eval(T0 const& lhs, T1 const& rhs) + { return lhs >= rhs; } +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + // no eval function, see comment above. +}; + +////////////////////////////////// +template +struct binary_operator { + + typedef bool result_type; + // no eval function, see comment above. +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// negative lazy operator (prefix -) +// +/////////////////////////////////////////////////////////////////////////////// +struct negative_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator-(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// positive lazy operator (prefix +) +// +/////////////////////////////////////////////////////////////////////////////// +struct positive_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator+(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// logical not lazy operator (prefix !) +// +/////////////////////////////////////////////////////////////////////////////// +struct logical_not_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator!(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// invert lazy operator (prefix ~) +// +/////////////////////////////////////////////////////////////////////////////// +struct invert_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator~(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// reference lazy operator (prefix &) +// +/////////////////////////////////////////////////////////////////////////////// +struct reference_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator&(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// dereference lazy operator (prefix *) +// +/////////////////////////////////////////////////////////////////////////////// +struct dereference_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator*(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// pre increment lazy operator (prefix ++) +// +/////////////////////////////////////////////////////////////////////////////// +struct pre_incr_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator++(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// pre decrement lazy operator (prefix --) +// +/////////////////////////////////////////////////////////////////////////////// +struct pre_decr_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator--(actor const& _0) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// post increment lazy operator (postfix ++) +// +/////////////////////////////////////////////////////////////////////////////// +struct post_incr_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator++(actor const& _0, int) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// post decrement lazy operator (postfix --) +// +/////////////////////////////////////////////////////////////////////////////// +struct post_decr_op { + + template + struct result { + + typedef typename unary_operator::result_type type; + }; + + template + typename unary_operator::result_type + operator()(T0& _0) const + { return unary_operator::eval(_0); } +}; + +////////////////////////////////// +template +inline typename impl::make_unary::type +operator--(actor const& _0, int) +{ + return impl::make_unary::construct(_0); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// assignment lazy operator (infix =) +// The acual lazy operator is a member of the actor class. +// +/////////////////////////////////////////////////////////////////////////////// +struct assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +template +inline typename impl::make_binary1::type +actor::operator=(B const& _1) const +{ + return impl::make_binary1::construct(*this, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// index lazy operator (array index []) +// The acual lazy operator is a member of the actor class. +// +/////////////////////////////////////////////////////////////////////////////// +struct index_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +template +inline typename impl::make_binary1::type +actor::operator[](B const& _1) const +{ + return impl::make_binary1::construct(*this, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// plus assign lazy operator (infix +=) +// +/////////////////////////////////////////////////////////////////////////////// +struct plus_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator+=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// minus assign lazy operator (infix -=) +// +/////////////////////////////////////////////////////////////////////////////// +struct minus_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator-=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// times assign lazy operator (infix *=) +// +/////////////////////////////////////////////////////////////////////////////// +struct times_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator*=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// divide assign lazy operator (infix /=) +// +/////////////////////////////////////////////////////////////////////////////// +struct divide_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator/=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// mod assign lazy operator (infix %=) +// +/////////////////////////////////////////////////////////////////////////////// +struct mod_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator%=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// and assign lazy operator (infix &=) +// +/////////////////////////////////////////////////////////////////////////////// +struct and_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator&=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// or assign lazy operator (infix |=) +// +/////////////////////////////////////////////////////////////////////////////// +struct or_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator|=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// xor assign lazy operator (infix ^=) +// +/////////////////////////////////////////////////////////////////////////////// +struct xor_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator^=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// shift left assign lazy operator (infix <<=) +// +/////////////////////////////////////////////////////////////////////////////// +struct shift_l_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator<<=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// shift right assign lazy operator (infix >>=) +// +/////////////////////////////////////////////////////////////////////////////// +struct shift_r_assign_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator>>=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// plus lazy operator (infix +) +// +/////////////////////////////////////////////////////////////////////////////// +struct plus_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator+(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator+(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator+(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// minus lazy operator (infix -) +// +/////////////////////////////////////////////////////////////////////////////// +struct minus_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator-(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator-(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator-(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// times lazy operator (infix *) +// +/////////////////////////////////////////////////////////////////////////////// +struct times_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator*(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator*(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator*(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// divide lazy operator (infix /) +// +/////////////////////////////////////////////////////////////////////////////// +struct divide_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator/(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator/(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator/(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// mod lazy operator (infix %) +// +/////////////////////////////////////////////////////////////////////////////// +struct mod_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator%(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator%(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator%(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// and lazy operator (infix &) +// +/////////////////////////////////////////////////////////////////////////////// +struct and_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator&(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator&(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator&(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// or lazy operator (infix |) +// +/////////////////////////////////////////////////////////////////////////////// +struct or_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator|(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator|(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator|(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// xor lazy operator (infix ^) +// +/////////////////////////////////////////////////////////////////////////////// +struct xor_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator^(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator^(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator^(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// shift left lazy operator (infix <<) +// +/////////////////////////////////////////////////////////////////////////////// +struct shift_l_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator<<(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator<<(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator<<(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// shift right lazy operator (infix >>) +// +/////////////////////////////////////////////////////////////////////////////// +struct shift_r_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator>>(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator>>(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator>>(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// equal lazy operator (infix ==) +// +/////////////////////////////////////////////////////////////////////////////// +struct eq_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator==(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator==(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator==(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// not equal lazy operator (infix !=) +// +/////////////////////////////////////////////////////////////////////////////// +struct not_eq_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator!=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator!=(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator!=(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// less than lazy operator (infix <) +// +/////////////////////////////////////////////////////////////////////////////// +struct lt_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator<(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator<(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator<(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// less than equal lazy operator (infix <=) +// +/////////////////////////////////////////////////////////////////////////////// +struct lt_eq_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator<=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator<=(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator<=(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// greater than lazy operator (infix >) +// +/////////////////////////////////////////////////////////////////////////////// +struct gt_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator>(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator>(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator>(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// greater than equal lazy operator (infix >=) +// +/////////////////////////////////////////////////////////////////////////////// +struct gt_eq_op { + + template + struct result { + + typedef typename binary_operator + ::result_type type; + }; + + template + typename binary_operator::result_type + operator()(T0& _0, T1& _1) const + { return binary_operator::eval(_0, _1); } +}; + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator>=(actor const& _0, T1 CREF _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary2::type +operator>=(T0 CREF _0, actor const& _1) +{ + return impl::make_binary2::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary3::type +operator>=(actor const& _0, actor const& _1) +{ + return impl::make_binary3::construct(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// logical and lazy operator (infix &&) +// +// The logical_and_composite class and its corresponding generators are +// provided to allow short-circuit evaluation of the operator's +// operands. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct logical_and_composite { + + typedef logical_and_composite self_t; + + template + struct result { + + typedef typename binary_operator::plain_type, + typename actor_result::plain_type + >::result_type type; + }; + + logical_and_composite(A0 const& _0, A1 const& _1) + : a0(_0), a1(_1) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + return a0.eval(args) && a1.eval(args); + } + + A0 a0; A1 a1; // actors +}; + +#if !(defined(__ICL) && __ICL <= 500) +////////////////////////////////// +template +inline actor, typename as_actor::type> > +operator&&(actor const& _0, T1 CREF _1) +{ + return logical_and_composite + , typename as_actor::type> + (_0, as_actor::convert(_1)); +} + +////////////////////////////////// +template +inline actor::type, actor > > +operator&&(T0 CREF _0, actor const& _1) +{ + return logical_and_composite + ::type, actor > + (as_actor::convert(_0), _1); +} + +////////////////////////////////// +template +inline actor, actor > > +operator&&(actor const& _0, actor const& _1) +{ + return logical_and_composite + , actor > + (_0, _1); +} +#else +////////////////////////////////// +template +inline actor::type, typename as_actor::type> > +operator&&(T0 CREF _0, T1 CREF _1) +{ + return logical_and_composite + ::type, typename as_actor::type> + (as_actor::convert(_0), as_actor::convert(_1)); +} +#endif // !(__ICL && __ICL <= 500) + +/////////////////////////////////////////////////////////////////////////////// +// +// logical or lazy operator (infix ||) +// +// The logical_or_composite class and its corresponding generators are +// provided to allow short-circuit evaluation of the operator's +// operands. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct logical_or_composite { + + typedef logical_or_composite self_t; + + template + struct result { + + typedef typename binary_operator::plain_type, + typename actor_result::plain_type + >::result_type type; + }; + + logical_or_composite(A0 const& _0, A1 const& _1) + : a0(_0), a1(_1) {} + + template + typename actor_result::type + eval(TupleT const& args) const + { + return a0.eval(args) || a1.eval(args); + } + + A0 a0; A1 a1; // actors +}; + +////////////////////////////////// +template +inline actor, typename as_actor::type> > +operator||(actor const& _0, T1 CREF _1) +{ + return logical_or_composite + , typename as_actor::type> + (_0, as_actor::convert(_1)); +} + +////////////////////////////////// +template +inline actor::type, actor > > +operator||(T0 CREF _0, actor const& _1) +{ + return logical_or_composite + ::type, actor > + (as_actor::convert(_0), _1); +} + +////////////////////////////////// +template +inline actor, actor > > +operator||(actor const& _0, actor const& _1) +{ + return logical_or_composite + , actor > + (_0, _1); +} + +} // namespace phoenix + +#undef CREF +#endif diff --git a/include/boost/spirit/phoenix/primitives.hpp b/include/boost/spirit/phoenix/primitives.hpp new file mode 100644 index 000000000..e2a9c86a4 --- /dev/null +++ b/include/boost/spirit/phoenix/primitives.hpp @@ -0,0 +1,249 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_PRIMITIVES_HPP +#define PHOENIX_PRIMITIVES_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/actor.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// argument class +// +// Lazy arguments +// +// An actor base class that extracts and returns the Nth argument +// from the argument list passed in the 'args' tuple in the eval +// member function (see actor.hpp). There are some predefined +// argument constants that can be used as actors (arg1..argN). +// +// The argument actor is a place-holder for the actual arguments +// passed by the client. For example, wherever arg1 is seen placed +// in a lazy function (see functions.hpp) or lazy operator (see +// operators.hpp), this will be replaced by the actual first +// argument in the actual function evaluation. Argument actors are +// essentially lazy arguments. A lazy argument is a full actor in +// its own right and can be evaluated through the actor's operator(). +// +// Example: +// +// char c = 'A'; +// int i = 123; +// const char* s = "Hello World"; +// +// cout << arg1(c) << ' '; +// cout << arg1(i, s) << ' '; +// cout << arg2(i, s) << ' '; +// +// will print out "A 123 Hello World" +// +/////////////////////////////////////////////////////////////////////////////// +template +struct argument { + + template + struct result { typedef typename tuple_element::type type; }; + + template + typename tuple_element::type + eval(TupleT const& args) const + { + return args[tuple_index()]; + } +}; + +////////////////////////////////// +actor > const arg1 = argument<0>(); +actor > const arg2 = argument<1>(); +actor > const arg3 = argument<2>(); + +#if PHOENIX_LIMIT > 3 +actor > const arg4 = argument<3>(); +actor > const arg5 = argument<4>(); +actor > const arg6 = argument<5>(); + +#if PHOENIX_LIMIT > 6 +actor > const arg7 = argument<6>(); +actor > const arg8 = argument<7>(); +actor > const arg9 = argument<8>(); + +#if PHOENIX_LIMIT > 9 +actor > const arg10 = argument<9>(); +actor > const arg11 = argument<10>(); +actor > const arg12 = argument<11>(); + +#if PHOENIX_LIMIT > 12 +actor > const arg13 = argument<12>(); +actor > const arg14 = argument<13>(); +actor > const arg15 = argument<14>(); + +#endif +#endif +#endif +#endif +/////////////////////////////////////////////////////////////////////////////// +// +// value class +// +// Lazy values +// +// A bound actual parameter is kept in a value class for deferred +// access later when needed. A value object is immutable. Value +// objects are typically created through the val(x) free function +// which returns a value with T deduced from the type of x. x is +// held in the value object by value. +// +// Lazy values are actors. As such, lazy values can be evaluated +// through the actor's operator(). Such invocation gives the value's +// identity. Example: +// +// cout << val(3)() << val("Hello World")(); +// +// prints out "3 Hello World" +// +/////////////////////////////////////////////////////////////////////////////// +template +struct value { + + typedef typename boost::remove_reference::type plain_t; + + template + struct result { typedef plain_t const type; }; + + value(plain_t val_) + : val(val_) {} + + template + plain_t const + eval(TupleT const& /*args*/) const + { + return val; + } + + plain_t val; +}; + +////////////////////////////////// +template +inline actor > const +val(T v) +{ + return value(v); +} + +////////////////////////////////// +template +void +val(actor const& v); // This is undefined and not allowed. + +/////////////////////////////////////////////////////////////////////////// +// +// Arbitrary types T are typically converted to a actor > +// (see as_actor in actor.hpp). A specialization is also provided +// for arrays. T[N] arrays are converted to actor >. +// +/////////////////////////////////////////////////////////////////////////// +template +struct as_actor { + + typedef actor > type; + static type convert(T const& x) + { return value(x); } +}; + +////////////////////////////////// +template +struct as_actor { + + typedef actor > type; + static type convert(T const x[N]) + { return value(x); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// variable class +// +// Lazy variables +// +// A bound actual parameter may also be held by non-const reference +// in a variable class for deferred access later when needed. A +// variable object is mutable, i.e. its referenced variable can be +// modified. Variable objects are typically created through the +// var(x) free function which returns a variable with T deduced +// from the type of x. x is held in the value object by +// reference. +// +// Lazy variables are actors. As such, lazy variables can be +// evaluated through the actor's operator(). Such invocation gives +// the variables's identity. Example: +// +// int i = 3; +// char const* s = "Hello World"; +// cout << var(i)() << var(s)(); +// +// prints out "3 Hello World" +// +// Another free function const_(x) may also be used. const_(x) creates +// a variable object using a constant reference. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct variable { + + template + struct result { typedef T& type; }; + + variable(T& var_) + : var(var_) {} + + template + T& + eval(TupleT const& /*args*/) const + { + return var; + } + + T& var; +}; + +////////////////////////////////// +template +inline actor > const +var(T& v) +{ + return variable(v); +} + +////////////////////////////////// +template +inline actor > const +const_(T const& v) +{ + return variable(v); +} + +////////////////////////////////// +template +void +var(actor const& v); // This is undefined and not allowed. + +////////////////////////////////// +template +void +const_(actor const& v); // This is undefined and not allowed. + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/special_ops.hpp b/include/boost/spirit/phoenix/special_ops.hpp new file mode 100644 index 000000000..a617fac1c --- /dev/null +++ b/include/boost/spirit/phoenix/special_ops.hpp @@ -0,0 +1,343 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_SPECIAL_OPS_HPP +#define PHOENIX_SPECIAL_OPS_HPP + +#include "boost/config.hpp" +#ifdef BOOST_NO_STRINGSTREAM +#include +#define PHOENIX_SSTREAM strstream +#else +#include +#define PHOENIX_SSTREAM stringstream +#endif + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/operators.hpp" +#include + +/////////////////////////////////////////////////////////////////////////////// +#if defined(_STLPORT_VERSION) && defined(__STL_USE_OWN_NAMESPACE) +#define PHOENIX_STD _STLP_STD +#define PHOENIX_NO_STD_NAMESPACE +#else +#define PHOENIX_STD std +#endif + +/////////////////////////////////////////////////////////////////////////////// +//#if !defined(PHOENIX_NO_STD_NAMESPACE) +namespace PHOENIX_STD +{ +//#endif + + template class complex; + +//#if !defined(PHOENIX_NO_STD_NAMESPACE) +} +//#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// The following specializations take into account the C++ standard +// library components. There are a couple of issues that has to be +// dealt with to enable lazy operator overloads for the standard +// library classes. +// +// *iostream (e.g. cout, cin, strstream/ stringstream) uses non- +// canonical shift operator overloads where the lhs is taken in +// by reference. +// +// *I/O manipulators overloads for the RHS of the << and >> +// operators. +// +// *STL iterators can be objects that conform to pointer semantics. +// Some operators need to be specialized for these. +// +// *std::complex is given a rank (see rank class in operators.hpp) +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// specialization for rank +// +/////////////////////////////////////////////////////////////////////////////// +template struct rank > +{ static int const value = 170 + rank::value; }; + +/////////////////////////////////////////////////////////////////////////////// +// +// specializations for std::istream +// +/////////////////////////////////////////////////////////////////////////////// +#if defined(__GNUC__) && (__GNUC__ < 3) + #if defined(_STLPORT_VERSION) + #define PHOENIX_ISTREAM _IO_istream_withassign + #else + #define PHOENIX_ISTREAM PHOENIX_STD::_IO_istream_withassign + #endif +#else + #if (defined(__ICL) && defined(_STLPORT_VERSION)) + #define PHOENIX_ISTREAM istream_withassign + #else + #define PHOENIX_ISTREAM PHOENIX_STD::istream + #endif +#endif + +////////////////////////////////// +#if defined(__GNUC__) && (__GNUC__ < 3) \ + || (defined(__ICL) && defined(_STLPORT_VERSION)) +template +struct binary_operator +{ + typedef PHOENIX_STD::istream& result_type; + static result_type eval(PHOENIX_STD::istream& out, T1& rhs) + { return out >> rhs; } +}; +#endif + +////////////////////////////////// +template +struct binary_operator +{ + typedef PHOENIX_STD::istream& result_type; + static result_type eval(PHOENIX_STD::istream& out, T1& rhs) + { return out >> rhs; } +}; + +////////////////////////////////// +template +inline typename impl::make_binary3 + , BaseT>::type +operator>>(PHOENIX_ISTREAM& _0, actor const& _1) +{ + return impl::make_binary3 + , BaseT> + ::construct(var(_0), _1); +} + +#undef PHOENIX_ISTREAM +/////////////////////////////////////////////////////////////////////////////// +// +// specializations for std::ostream +// +/////////////////////////////////////////////////////////////////////////////// +#if defined(__GNUC__) && (__GNUC__ < 3) + #if defined(_STLPORT_VERSION) + #define PHOENIX_OSTREAM _IO_ostream_withassign + #else + #define PHOENIX_OSTREAM PHOENIX_STD::_IO_ostream_withassign + #endif +#else + #if (defined(__ICL) && defined(_STLPORT_VERSION)) + #define PHOENIX_OSTREAM ostream_withassign + #else + #define PHOENIX_OSTREAM PHOENIX_STD::ostream + #endif +#endif + +////////////////////////////////// +#if defined(__GNUC__) && (__GNUC__ < 3) \ + || (defined(__ICL) && defined(_STLPORT_VERSION)) +template +struct binary_operator +{ + typedef PHOENIX_STD::ostream& result_type; + static result_type eval(PHOENIX_STD::ostream& out, T1 const& rhs) + { return out << rhs; } +}; +#endif + +////////////////////////////////// +template +struct binary_operator +{ + typedef PHOENIX_STD::ostream& result_type; + static result_type eval(PHOENIX_STD::ostream& out, T1 const& rhs) + { return out << rhs; } +}; + +////////////////////////////////// +template +inline typename impl::make_binary3 + , BaseT>::type +operator<<(PHOENIX_OSTREAM& _0, actor const& _1) +{ + return impl::make_binary3 + , BaseT> + ::construct(var(_0), _1); +} + +#undef PHOENIX_OSTREAM + +/////////////////////////////////////////////////////////////////////////////// +// +// specializations for std::strstream / stringstream +// +/////////////////////////////////////////////////////////////////////////////// +template +struct binary_operator +{ + typedef PHOENIX_STD::istream& result_type; + static result_type eval(PHOENIX_STD::istream& out, T1& rhs) + { return out >> rhs; } +}; + +////////////////////////////////// +template +inline typename impl::make_binary3 + , BaseT>::type +operator>>(PHOENIX_STD::PHOENIX_SSTREAM& _0, actor const& _1) +{ + return impl::make_binary3 + , BaseT> + ::construct(var(_0), _1); +} + +////////////////////////////////// +template +struct binary_operator +{ + typedef PHOENIX_STD::ostream& result_type; + static result_type eval(PHOENIX_STD::ostream& out, T1 const& rhs) + { return out << rhs; } +}; + +////////////////////////////////// +template +inline typename impl::make_binary3 + , BaseT>::type +operator<<(PHOENIX_STD::PHOENIX_SSTREAM& _0, actor const& _1) +{ + return impl::make_binary3 + , BaseT> + ::construct(var(_0), _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// I/O manipulator specializations +// +/////////////////////////////////////////////////////////////////////////////// +#if (!defined(__GNUC__) || (__GNUC__ > 2)) \ + && !(defined(__ICL) && defined(_STLPORT_VERSION)) + +typedef PHOENIX_STD::ios_base& (*iomanip_t)(PHOENIX_STD::ios_base&); +typedef PHOENIX_STD::istream& (*imanip_t)(PHOENIX_STD::istream&); +typedef PHOENIX_STD::ostream& (*omanip_t)(PHOENIX_STD::ostream&); + +#if defined(__BORLANDC__) + +/////////////////////////////////////////////////////////////////////////////// +// +// Borland does not like i/o manipulators functions such as endl to +// be the rhs of a lazy << operator (Borland incorrectly reports +// ambiguity). To get around the problem, we provide function +// pointer versions of the same name with a single trailing +// underscore. +// +// You can use the same trick for other i/o manipulators. +// Alternatively, you can prefix the manipulator with a '&' +// operator. Example: +// +// cout << arg1 << &endl +// +/////////////////////////////////////////////////////////////////////////////// + +imanip_t ws_ = &PHOENIX_STD::ws; +iomanip_t dec_ = &PHOENIX_STD::dec; +iomanip_t hex_ = &PHOENIX_STD::hex; +iomanip_t oct_ = &PHOENIX_STD::oct; +omanip_t endl_ = &PHOENIX_STD::endl; +omanip_t ends_ = &PHOENIX_STD::ends; +omanip_t flush_ = &PHOENIX_STD::flush; + +#else // __BORLANDC__ + +/////////////////////////////////////////////////////////////////////////////// +// +// The following are overloads for I/O manipulators. +// +/////////////////////////////////////////////////////////////////////////////// +template +inline typename impl::make_binary1::type +operator>>(actor const& _0, imanip_t _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator>>(actor const& _0, iomanip_t _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator<<(actor const& _0, omanip_t _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +////////////////////////////////// +template +inline typename impl::make_binary1::type +operator<<(actor const& _0, iomanip_t _1) +{ + return impl::make_binary1::construct(_0, _1); +} + +#endif // __BORLANDC__ +#endif // !defined(__GNUC__) || (__GNUC__ > 2) + +/////////////////////////////////////////////////////////////////////////////// +// +// specializations for stl iterators and containers +// +/////////////////////////////////////////////////////////////////////////////// +template +struct unary_operator +{ + typedef typename T::reference result_type; + static result_type eval(T const& iter) + { return *iter; } +}; + +////////////////////////////////// +template +struct binary_operator +{ + typedef typename T0::reference result_type; + static result_type eval(T0& container, T1 const& index) + { return container[index]; } +}; + +////////////////////////////////// +template +struct binary_operator +{ + typedef typename T0::const_reference result_type; + static result_type eval(T0 const& container, T1 const& index) + { return container[index]; } +}; + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#undef PHOENIX_SSTREAM +#undef PHOENIX_STD +#endif diff --git a/include/boost/spirit/phoenix/statements.hpp b/include/boost/spirit/phoenix/statements.hpp new file mode 100644 index 000000000..ed304cb93 --- /dev/null +++ b/include/boost/spirit/phoenix/statements.hpp @@ -0,0 +1,445 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_STATEMENTS_HPP +#define PHOENIX_STATEMENTS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/phoenix/composite.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// sequential_composite +// +// Two or more actors separated by the comma generates a +// sequential_composite which is a composite actor. Example: +// +// actor, +// actor, +// actor +// +// The actors are evaluated sequentially. The result type of this +// is void. Note that the last actor should not have a trailing +// comma. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct sequential_composite { + + typedef sequential_composite self_t; + + template + struct result { typedef void type; }; + + sequential_composite(A0 const& _0, A1 const& _1) + : a0(_0), a1(_1) {} + + template + void + eval(TupleT const& args) const + { + a0.eval(args); + a1.eval(args); + } + + A0 a0; A1 a1; // actors +}; + +////////////////////////////////// +template +inline actor, actor > > +operator,(actor const& _0, actor const& _1) +{ + return sequential_composite, actor >(_0, _1); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// if_then_else_composite +// +// This composite has two (2) forms: +// +// if_(condition) +// [ +// statement +// ] +// +// and +// +// if_(condition) +// [ +// true_statement +// ] +// .else_ +// [ +// false_statement +// ] +// +// where condition is an actor that evaluates to bool. If condition +// is true, the true_statement (again an actor) is executed +// otherwise, the false_statement (another actor) is executed. The +// result type of this is void. Note the trailing underscore after +// if_ and the the leading dot and the trailing underscore before +// and after .else_. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct if_then_else_composite { + + typedef if_then_else_composite self_t; + + template + struct result { + + typedef void type; + }; + + if_then_else_composite( + CondT const& cond_, + ThenT const& then_, + ElseT const& else__) + : cond(cond_), then(then_), else_(else__) {} + + template + void eval(TupleT const& args) const + { + if (cond.eval(args)) + then.eval(args); + else + else_.eval(args); + } + + CondT cond; ThenT then; ElseT else_; // actors +}; + +////////////////////////////////// +template +struct else_gen { + + else_gen(CondT const& cond_, ThenT const& then_) + : cond(cond_), then(then_) {} + + template + actor::type> > + operator[](ElseT const& else_) + { + typedef if_then_else_composite::type> + result; + + return result(cond, then, as_actor::convert(else_)); + } + + CondT cond; ThenT then; +}; + +////////////////////////////////// +template +struct if_then_composite { + + typedef if_then_composite self_t; + + template + struct result { typedef void type; }; + + if_then_composite(CondT const& cond_, ThenT const& then_) + : cond(cond_), then(then_), else_(cond, then) {} + + template + void eval(TupleT const& args) const + { + if (cond.eval(args)) + then.eval(args); + } + + CondT cond; ThenT then; // actors + else_gen else_; +}; + +////////////////////////////////// +template +struct if_gen { + + if_gen(CondT const& cond_) + : cond(cond_) {} + + template + actor::type, + typename as_actor::type> > + operator[](ThenT const& then) const + { + typedef if_then_composite< + typename as_actor::type, + typename as_actor::type> + result; + + return result( + as_actor::convert(cond), + as_actor::convert(then)); + } + + CondT cond; +}; + +////////////////////////////////// +template +inline if_gen +if_(CondT const& cond) +{ + return if_gen(cond); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// while_composite +// +// This composite has the form: +// +// while_(condition) +// [ +// statement +// ] +// +// While the condition (an actor) evaluates to true, statement +// (another actor) is executed. The result type of this is void. +// Note the trailing underscore after while_. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct while_composite { + + typedef while_composite self_t; + + template + struct result { typedef void type; }; + + while_composite(CondT const& cond_, DoT const& do__) + : cond(cond_), do_(do__) {} + + template + void eval(TupleT const& args) const + { + while (cond.eval(args)) + do_.eval(args); + } + + CondT cond; + DoT do_; +}; + +////////////////////////////////// +template +struct while_gen { + + while_gen(CondT const& cond_) + : cond(cond_) {} + + template + actor::type, + typename as_actor::type> > + operator[](DoT const& do_) const + { + typedef while_composite< + typename as_actor::type, + typename as_actor::type> + result; + + return result( + as_actor::convert(cond), + as_actor::convert(do_)); + } + + CondT cond; +}; + +////////////////////////////////// +template +inline while_gen +while_(CondT const& cond) +{ + return while_gen(cond); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// do_composite +// +// This composite has the form: +// +// do_ +// [ +// statement +// ] +// .while_(condition) +// +// While the condition (an actor) evaluates to true, statement +// (another actor) is executed. The statement is executed at least +// once. The result type of this is void. Note the trailing +// underscore after do_ and the the leading dot and the trailing +// underscore before and after .while_. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct do_composite { + + typedef do_composite self_t; + + template + struct result { typedef void type; }; + + do_composite(DoT const& do__, CondT const& cond_) + : do_(do__), cond(cond_) {} + + template + void eval(TupleT const& args) const + { + do + do_.eval(args); + while (cond.eval(args)); + } + + DoT do_; + CondT cond; +}; + +//////////////////////////////////// +template +struct do_gen2 { + + do_gen2(DoT const& do__) + : do_(do__) {} + + template + actor::type, + typename as_actor::type> > + while_(CondT const& cond) const + { + typedef do_composite< + typename as_actor::type, + typename as_actor::type> + result; + + return result( + as_actor::convert(do_), + as_actor::convert(cond)); + } + + DoT do_; +}; + +//////////////////////////////////// +struct do_gen { + + template + do_gen2 + operator[](DoT const& do_) const + { + return do_gen2(do_); + } +}; + +do_gen const do_ = do_gen(); + +/////////////////////////////////////////////////////////////////////////////// +// +// for_composite +// +// This statement has the form: +// +// for_(init, condition, step) +// [ +// statement +// ] +// +// Where init, condition, step and statement are all actors. init +// is executed once before entering the for-loop. The for-loop +// exits once condition evaluates to false. At each loop iteration, +// step and statement is called. The result of this statement is +// void. Note the trailing underscore after for_. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct for_composite { + + typedef composite self_t; + + template + struct result { typedef void type; }; + + for_composite( + InitT const& init_, + CondT const& cond_, + StepT const& step_, + DoT const& do__) + : init(init_), cond(cond_), step(step_), do_(do__) {} + + template + void + eval(TupleT const& args) const + { + for (init.eval(args); cond.eval(args); step.eval(args)) + do_.eval(args); + } + + InitT init; CondT cond; StepT step; DoT do_; // actors +}; + +////////////////////////////////// +template +struct for_gen { + + for_gen( + InitT const& init_, + CondT const& cond_, + StepT const& step_) + : init(init_), cond(cond_), step(step_) {} + + template + actor::type, + typename as_actor::type, + typename as_actor::type, + typename as_actor::type> > + operator[](DoT const& do_) const + { + typedef for_composite< + typename as_actor::type, + typename as_actor::type, + typename as_actor::type, + typename as_actor::type> + result; + + return result( + as_actor::convert(init), + as_actor::convert(cond), + as_actor::convert(step), + as_actor::convert(do_)); + } + + InitT init; CondT cond; StepT step; +}; + +////////////////////////////////// +template +inline for_gen +for_(InitT const& init, CondT const& cond, StepT const& step) +{ + return for_gen(init, cond, step); +} + +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/phoenix/tuple_helpers.hpp b/include/boost/spirit/phoenix/tuple_helpers.hpp new file mode 100644 index 000000000..5546f3330 --- /dev/null +++ b/include/boost/spirit/phoenix/tuple_helpers.hpp @@ -0,0 +1,1077 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2002 Joel de Guzman + Copyright (c) 2002-2003 Hartmut Kaiser + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_TUPLEHELPERS_HPP +#define PHOENIX_TUPLEHELPERS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include +#include "boost/spirit/phoenix/tuples.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// make_tuple template class +// +// This template class is used to calculate a tuple type required to hold +// the given template parameter type +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// normal (non-tuple types are wrapped into a tuple) +template +struct make_tuple { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// nil_t is converted to an empty tuple type +template <> +struct make_tuple { + + typedef tuple<> type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// tuple types are left alone without any refactoring +template < + typename A, typename B, typename C +#if PHOENIX_LIMIT > 3 + , typename D, typename E, typename F +#if PHOENIX_LIMIT > 6 + , typename G, typename H, typename I +#if PHOENIX_LIMIT > 9 + , typename J, typename K, typename L +#if PHOENIX_LIMIT > 12 + , typename M, typename N, typename O +#endif +#endif +#endif +#endif +> +struct make_tuple 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > > { + +// the tuple parameter itself is the required tuple type + typedef tuple 3 + , D, E, F +#if PHOENIX_LIMIT > 6 + , G, H, I +#if PHOENIX_LIMIT > 9 + , J, K, L +#if PHOENIX_LIMIT > 12 + , M, N, O +#endif +#endif +#endif +#endif + > type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat_tuple type computer +// +// This class returns the type of a tuple, which is constructed by +// concatenating a tuple with a given type +// +/////////////////////////////////////////////////////////////////////////////// +template +struct concat_tuple; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <0 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template <> +struct concat_tuple, nil_t> { + + typedef tuple<> type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <1 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <2 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +#if PHOENIX_LIMIT > 3 +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <3 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <4 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <5 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +#if PHOENIX_LIMIT > 6 +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <6 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <7 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <8 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +#if PHOENIX_LIMIT > 9 +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <9 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <10 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <11 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +#if PHOENIX_LIMIT > 12 +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <12 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, typename L, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, typename L +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <13 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, typename L, + typename M, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, typename L, + typename M +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// concat tuple <14 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, typename L, + typename M, typename N, + typename AppendT +> +struct concat_tuple, AppendT> { + + typedef tuple type; +}; + +template < + typename A, typename B, typename C, typename D, typename E, typename F, + typename G, typename H, typename I, typename J, typename K, typename L, + typename M, typename N +> +struct concat_tuple, nil_t> { + + typedef tuple type; +}; + +#endif +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// concat_tuples type computer +// +// This template class returns the type of a tuple built from the +// concatenation of two given tuples. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct concat_tuple_element { + + typedef + typename concat_tuple_element< + typename concat_tuple::type, TupleT2, N+1, + typename tuple_element::type + >::type + type; +}; + +template +struct concat_tuple_element { + + typedef TupleT1 type; +}; + +template +struct concat_tuples { + + typedef + typename concat_tuple_element< + TupleT1, TupleT2, 0, + typename tuple_element<0, TupleT2>::type + >::type + type; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// convert_actors template function +// +// The convert_actors template functions constructs a new tuple object +// composed of the elements returned by the actors contained in the +// input tuple. (i.e. the given tuple type 'actor_tuple' contains a set +// of actors to evaluate and the resulting tuple contains the results of +// evaluating the actors.) +// +/////////////////////////////////////////////////////////////////////////////// +template +struct actor_result; // forward declaration + +namespace impl +{ + template + struct convert_actors_ {}; +} + +template +TupleResultT +convert_actors(ActorTupleT const& actor_tuple) +{ + BOOST_STATIC_ASSERT(ActorTupleT::length <= TupleResultT::length); + BOOST_STATIC_CONSTANT(int, length = TupleResultT::length); + return impl::convert_actors_ + ::template apply::do_(actor_tuple); +} + +namespace impl +{ + template + struct convert_actor + { + typedef typename tuple_element::type type; + + template + struct is_default_t {}; + typedef is_default_t is_default; + typedef is_default_t is_not_default; + + static type + actor_element(ActorTupleT const& actor_tuple, is_default) + { + return type(); // default construct + } + + static type + actor_element(ActorTupleT const& actor_tuple, is_not_default) + { + BOOST_STATIC_ASSERT(ActorTupleT::length <= TupleResultT::length); + return actor_tuple[tuple_index()](); // apply the actor + } + + static type + do_(ActorTupleT const& actor_tuple) + { + return actor_element( + actor_tuple, is_default_t<(N >= ActorTupleT::length)>()); + } + }; + + /////////////////////////////////////// + template <> + struct convert_actors_<1> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + + return TupleResultT( + converter0::do_(actor_tuple) + ); + } + }; + }; + + /////////////////////////////////////// + template <> + struct convert_actors_<2> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + ); + } + }; + }; + + /////////////////////////////////////// + template <> + struct convert_actors_<3> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + ); + } + }; + }; + + #if PHOENIX_LIMIT > 3 + + ///////////////////////////////////// + template <> + struct convert_actors_<4> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + ); + } + }; + }; + + ///////////////////////////////////// + template <> + struct convert_actors_<5> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + ); + } + }; + }; + + ///////////////////////////////////// + template <> + struct convert_actors_<6> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + ); + } + }; + }; + + #if PHOENIX_LIMIT > 6 + + ///////////////////////////////////// + template <> + struct convert_actors_<7> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + ); + } + }; + }; + + ///////////////////////////////////// + template <> + struct convert_actors_<8> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + ); + } + }; + }; + + ///////////////////////////////////// + template <> + struct convert_actors_<9> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + ); + } + }; + }; + + #if PHOENIX_LIMIT > 9 + + ///////////////////////////////////// + template <> + struct convert_actors_<10> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + typedef impl::convert_actor<9, TupleResultT, ActorTupleT> converter9; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + , converter9::do_(actor_tuple) + ); + } + }; + }; + + ///////////////////////////////////// + template <> + struct convert_actors_<11> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + typedef impl::convert_actor<9, TupleResultT, ActorTupleT> converter9; + typedef impl::convert_actor<10, TupleResultT, ActorTupleT> converter10; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + , converter9::do_(actor_tuple) + , converter10::do_(actor_tuple) + ); + } + }; + }; + + ///////////////////////////////////// + template <> + struct convert_actors_<12> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + typedef impl::convert_actor<9, TupleResultT, ActorTupleT> converter9; + typedef impl::convert_actor<10, TupleResultT, ActorTupleT> converter10; + typedef impl::convert_actor<11, TupleResultT, ActorTupleT> converter11; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + , converter9::do_(actor_tuple) + , converter10::do_(actor_tuple) + , converter11::do_(actor_tuple) + ); + } + }; + }; + + #if PHOENIX_LIMIT > 12 + + ///////////////////////////////////// + template <> + struct convert_actors_<13> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + typedef impl::convert_actor<9, TupleResultT, ActorTupleT> converter9; + typedef impl::convert_actor<10, TupleResultT, ActorTupleT> converter10; + typedef impl::convert_actor<11, TupleResultT, ActorTupleT> converter11; + typedef impl::convert_actor<12, TupleResultT, ActorTupleT> converter12; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + , converter9::do_(actor_tuple) + , converter10::do_(actor_tuple) + , converter11::do_(actor_tuple) + , converter12::do_(actor_tuple) + ); + } + }; + }; + + /////////////////////////////////////// + template <> + struct convert_actors_<14> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + typedef impl::convert_actor<9, TupleResultT, ActorTupleT> converter9; + typedef impl::convert_actor<10, TupleResultT, ActorTupleT> converter10; + typedef impl::convert_actor<11, TupleResultT, ActorTupleT> converter11; + typedef impl::convert_actor<12, TupleResultT, ActorTupleT> converter12; + typedef impl::convert_actor<13, TupleResultT, ActorTupleT> converter13; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + , converter9::do_(actor_tuple) + , converter10::do_(actor_tuple) + , converter11::do_(actor_tuple) + , converter12::do_(actor_tuple) + , converter13::do_(actor_tuple) + ); + } + }; + }; + + /////////////////////////////////////// + template <> + struct convert_actors_<15> + { + template + struct apply + { + static TupleResultT + do_(ActorTupleT const& actor_tuple) + { + typedef impl::convert_actor<0, TupleResultT, ActorTupleT> converter0; + typedef impl::convert_actor<1, TupleResultT, ActorTupleT> converter1; + typedef impl::convert_actor<2, TupleResultT, ActorTupleT> converter2; + typedef impl::convert_actor<3, TupleResultT, ActorTupleT> converter3; + typedef impl::convert_actor<4, TupleResultT, ActorTupleT> converter4; + typedef impl::convert_actor<5, TupleResultT, ActorTupleT> converter5; + typedef impl::convert_actor<6, TupleResultT, ActorTupleT> converter6; + typedef impl::convert_actor<7, TupleResultT, ActorTupleT> converter7; + typedef impl::convert_actor<8, TupleResultT, ActorTupleT> converter8; + typedef impl::convert_actor<9, TupleResultT, ActorTupleT> converter9; + typedef impl::convert_actor<10, TupleResultT, ActorTupleT> converter10; + typedef impl::convert_actor<11, TupleResultT, ActorTupleT> converter11; + typedef impl::convert_actor<12, TupleResultT, ActorTupleT> converter12; + typedef impl::convert_actor<13, TupleResultT, ActorTupleT> converter13; + typedef impl::convert_actor<14, TupleResultT, ActorTupleT> converter14; + + using namespace tuple_index_names; + return TupleResultT( + converter0::do_(actor_tuple) + , converter1::do_(actor_tuple) + , converter2::do_(actor_tuple) + , converter3::do_(actor_tuple) + , converter4::do_(actor_tuple) + , converter5::do_(actor_tuple) + , converter6::do_(actor_tuple) + , converter7::do_(actor_tuple) + , converter8::do_(actor_tuple) + , converter9::do_(actor_tuple) + , converter10::do_(actor_tuple) + , converter11::do_(actor_tuple) + , converter12::do_(actor_tuple) + , converter13::do_(actor_tuple) + , converter14::do_(actor_tuple) + ); + } + }; + }; + + #endif + #endif + #endif + #endif +} // namespace impl + + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#endif // PHOENIX_TUPLEHELPERS_HPP diff --git a/include/boost/spirit/phoenix/tuples.hpp b/include/boost/spirit/phoenix/tuples.hpp new file mode 100644 index 000000000..d6cbdde15 --- /dev/null +++ b/include/boost/spirit/phoenix/tuples.hpp @@ -0,0 +1,1297 @@ +/*============================================================================= + Phoenix V1.0 + Copyright (c) 2001-2002 Joel de Guzman + + Permission to copy, use, modify, sell and distribute this software + is granted provided this copyright notice appears in all copies. + This software is provided "as is" without express or implied + warranty, and with no claim as to its suitability for any purpose. +==============================================================================*/ +#ifndef PHOENIX_TUPLES_HPP +#define PHOENIX_TUPLES_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// Phoenix predefined maximum limit. This limit defines the maximum +// number of elements a tuple can hold. This number defaults to 3. The +// actual maximum is rounded up in multiples of 3. Thus, if this value +// is 4, the actual limit is 6. The ultimate maximum limit in this +// implementation is 15. +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef PHOENIX_LIMIT +#define PHOENIX_LIMIT 3 +#endif + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/static_assert.hpp" +#include "boost/call_traits.hpp" +#include "boost/type_traits.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace phoenix { + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple +// +// Tuples hold heterogeneous types up to a predefined maximum. Only +// the most basic functionality needed is provided. Unlike other +// recursive list-like tuple implementations, this tuple +// implementation uses simple structs similar to std::pair with +// specialization for 0 to N tuple elements. +// +// 1) Construction +// Here are examples on how to construct tuples: +// +// typedef tuple t1_t; +// typedef tuple t2_t; +// +// // this tuple has an int and char members +// t1_t t1(3, 'c'); +// +// // this tuple has an int, std::string and double members +// t2_t t2(3, "hello", 3.14); +// +// Tuples can also be constructed from other tuples. The +// source and destination tuples need not have exactly the +// same element types. The only requirement is that the +// source tuple have the same number of elements as the +// destination and that each element slot in the +// destination can be copy constructed from the source +// element. For example: +// +// tuple t3(t1); // OK. Compatible tuples +// tuple t4(t2); // Error! Incompatible tuples +// +// 2) Member access +// A member in a tuple can be accessed using the +// tuple's [] operator by specifying the Nth +// tuple_index. Here are some examples: +// +// tuple_index<0> ix0; // 0th index == 1st item +// tuple_index<1> ix1; // 1st index == 2nd item +// tuple_index<2> ix2; // 2nd index == 3rd item +// +// t1[ix0] = 33; // sets the int member of the tuple t1 +// t2[ix2] = 6e6; // sets the double member of the tuple t2 +// t1[ix1] = 'a'; // sets the char member of the tuple t1 +// +// There are some predefined names are provided in sub- +// namespace tuple_index_names: +// +// tuple_index<0> _1; +// tuple_index<1> _2; +// ... +// tuple_index _N; +// +// These indexes may be used by 'using' namespace +// phoenix::tuple_index_names. +// +// Access to out of bound indexes returns a nil_t value. +// +// 3) Member type inquiry +// The type of an individual member can be queried. +// Example: +// +// tuple_element<1, t2_t>::type +// +// Refers to the type of the second member (note zero based, +// thus 0 = 1st item, 1 = 2nd item) of the tuple. +// +// Aside from tuple_element::type, there are two +// more types that tuple_element provides: rtype and +// crtype. While 'type' is the plain underlying type, +// 'rtype' is the reference type, or type& and 'crtype' +// is the constant reference type or type const&. The +// latter two are provided to make it easy for the +// client in dealing with the possibility of reference +// to reference when type is already a reference, which +// is illegal in C++. +// +// Access to out of bound indexes returns a nil_t type. +// +// 4) Tuple length +// The number of elements in a tuple can be queried. +// Example: +// +// int n = t1.length; +// +// gets the number of elements in tuple t1. +// +// length is a static constant. Thus, TupleT::length +// also works. Example: +// +// int n = t1_t::length; +// +/////////////////////////////////////////////////////////////////////////////// +struct nil_t {}; +using boost::remove_reference; +using boost::call_traits; + +////////////////////////////////// +namespace impl { + + template + struct access { + + typedef const T& ctype; + typedef T& type; + }; + + template + struct access { + + typedef T& ctype; + typedef T& type; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple_element +// +// A query class that gets the Nth element inside a tuple. +// Examples: +// +// tuple_element<1, tuple >::type // plain +// tuple_element<1, tuple >::rtype // ref +// tuple_element<1, tuple >::crtype // const ref +// +// Has type char which is the 2nd type in the tuple +// (note zero based, thus 0 = 1st item, 1 = 2nd item). +// +// Given a tuple object, the static function tuple_element::get(tuple) gets the Nth element in the tuple. The +// tuple class' tuple::operator[] uses this to get its Nth +// element. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple_element +{ + typedef nil_t type; + typedef nil_t& rtype; + typedef nil_t const& crtype; + + static nil_t get(TupleT const& t) { return nil_t(); } +}; + +////////////////////////////////// +template +struct tuple_element<0, TupleT> +{ + typedef typename TupleT::a_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.a; } + static crtype get(TupleT const& t) { return t.a; } +}; + +////////////////////////////////// +template +struct tuple_element<1, TupleT> +{ + typedef typename TupleT::b_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.b; } + static crtype get(TupleT const& t) { return t.b; } +}; + +////////////////////////////////// +template +struct tuple_element<2, TupleT> +{ + typedef typename TupleT::c_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.c; } + static crtype get(TupleT const& t) { return t.c; } +}; + +#if PHOENIX_LIMIT > 3 +////////////////////////////////// +template +struct tuple_element<3, TupleT> +{ + typedef typename TupleT::d_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.d; } + static crtype get(TupleT const& t) { return t.d; } +}; + +////////////////////////////////// +template +struct tuple_element<4, TupleT> +{ + typedef typename TupleT::e_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.e; } + static crtype get(TupleT const& t) { return t.e; } +}; + +////////////////////////////////// +template +struct tuple_element<5, TupleT> +{ + typedef typename TupleT::f_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.f; } + static crtype get(TupleT const& t) { return t.f; } +}; + +#if PHOENIX_LIMIT > 6 +////////////////////////////////// +template +struct tuple_element<6, TupleT> +{ + typedef typename TupleT::g_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.g; } + static crtype get(TupleT const& t) { return t.g; } +}; + +////////////////////////////////// +template +struct tuple_element<7, TupleT> +{ + typedef typename TupleT::h_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.h; } + static crtype get(TupleT const& t) { return t.h; } +}; + +////////////////////////////////// +template +struct tuple_element<8, TupleT> +{ + typedef typename TupleT::i_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.i; } + static crtype get(TupleT const& t) { return t.i; } +}; + +#if PHOENIX_LIMIT > 9 +////////////////////////////////// +template +struct tuple_element<9, TupleT> +{ + typedef typename TupleT::j_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.j; } + static crtype get(TupleT const& t) { return t.j; } +}; + +////////////////////////////////// +template +struct tuple_element<10, TupleT> +{ + typedef typename TupleT::k_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.k; } + static crtype get(TupleT const& t) { return t.k; } +}; + +////////////////////////////////// +template +struct tuple_element<11, TupleT> +{ + typedef typename TupleT::l_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.l; } + static crtype get(TupleT const& t) { return t.l; } +}; + +#if PHOENIX_LIMIT > 12 +////////////////////////////////// +template +struct tuple_element<12, TupleT> +{ + typedef typename TupleT::m_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.m; } + static crtype get(TupleT const& t) { return t.m; } +}; + +////////////////////////////////// +template +struct tuple_element<13, TupleT> +{ + typedef typename TupleT::n_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.n; } + static crtype get(TupleT const& t) { return t.n; } +}; + +////////////////////////////////// +template +struct tuple_element<14, TupleT> +{ + typedef typename TupleT::o_type type; + typedef typename impl::access::type rtype; + typedef typename impl::access::ctype crtype; + + static rtype get(TupleT& t) { return t.o; } + static crtype get(TupleT const& t) { return t.o; } +}; + +#endif +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple forward declaration. +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A = nil_t + , typename B = nil_t + , typename C = nil_t + +#if PHOENIX_LIMIT > 3 + , typename D = nil_t + , typename E = nil_t + , typename F = nil_t + +#if PHOENIX_LIMIT > 6 + , typename G = nil_t + , typename H = nil_t + , typename I = nil_t + +#if PHOENIX_LIMIT > 9 + , typename J = nil_t + , typename K = nil_t + , typename L = nil_t + +#if PHOENIX_LIMIT > 12 + , typename M = nil_t + , typename N = nil_t + , typename O = nil_t + +#endif +#endif +#endif +#endif + + , typename NU = nil_t // Not used +> +struct tuple; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple_index +// +// This class wraps an integer in a type to be used for indexing +// the Nth element in a tuple. See tuple operator[]. Some +// predefined names are provided in sub-namespace +// tuple_index_names. +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple_index {}; + +////////////////////////////////// +namespace tuple_index_names { + + tuple_index<0> const _1 = tuple_index<0>(); + tuple_index<1> const _2 = tuple_index<1>(); + tuple_index<2> const _3 = tuple_index<2>(); + +#if PHOENIX_LIMIT > 3 + tuple_index<3> const _4 = tuple_index<3>(); + tuple_index<4> const _5 = tuple_index<4>(); + tuple_index<5> const _6 = tuple_index<5>(); + +#if PHOENIX_LIMIT > 6 + tuple_index<6> const _7 = tuple_index<6>(); + tuple_index<7> const _8 = tuple_index<7>(); + tuple_index<8> const _9 = tuple_index<8>(); + +#if PHOENIX_LIMIT > 9 + tuple_index<9> const _10 = tuple_index<9>(); + tuple_index<10> const _11 = tuple_index<10>(); + tuple_index<11> const _12 = tuple_index<11>(); + +#if PHOENIX_LIMIT > 12 + tuple_index<12> const _13 = tuple_index<12>(); + tuple_index<13> const _14 = tuple_index<13>(); + tuple_index<14> const _15 = tuple_index<14>(); + +#endif +#endif +#endif +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple_common class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple_base { + + typedef nil_t a_type; + typedef nil_t b_type; + typedef nil_t c_type; + +#if PHOENIX_LIMIT > 3 + typedef nil_t d_type; + typedef nil_t e_type; + typedef nil_t f_type; + +#if PHOENIX_LIMIT > 6 + typedef nil_t g_type; + typedef nil_t h_type; + typedef nil_t i_type; + +#if PHOENIX_LIMIT > 9 + typedef nil_t j_type; + typedef nil_t k_type; + typedef nil_t l_type; + +#if PHOENIX_LIMIT > 12 + typedef nil_t m_type; + typedef nil_t n_type; + typedef nil_t o_type; + +#endif +#endif +#endif +#endif + + template + typename tuple_element::crtype + operator[](tuple_index) const + { + return tuple_element + ::get(*static_cast(this)); + } + + template + typename tuple_element::rtype + operator[](tuple_index) + { + return tuple_element + ::get(*static_cast(this)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <0 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template <> +struct tuple<> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 0); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <1 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 1); + typedef A a_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_ + ): a(a_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <2 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 2); + typedef A a_type; typedef B b_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_ + ): a(a_), b(b_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <3 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple 3 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 3); + typedef A a_type; typedef B b_type; + typedef C c_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_ + ): a(a_), b(b_), c(c_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; +}; + +#if PHOENIX_LIMIT > 3 +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <4 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 4); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_ + ): a(a_), b(b_), c(c_), d(d_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <5 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template +struct tuple 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 5); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_ + ): a(a_), b(b_), c(c_), d(d_), e(e_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <6 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F> +struct tuple 6 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 6); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; +}; + +#if PHOENIX_LIMIT > 6 +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <7 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G> +struct tuple 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 7); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <8 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H> +struct tuple 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 8); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <9 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I> +struct tuple 9 + nil_t, nil_t, nil_t, +#if PHOENIX_LIMIT > 12 + nil_t, nil_t, nil_t, +#endif +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 9); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; +}; + +#if PHOENIX_LIMIT > 9 +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <10 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J> +struct tuple 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 10); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; typedef J j_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_, + typename call_traits::param_type j_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]), j(init[tuple_index<9>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; J j; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <11 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K> +struct tuple 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 11); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; typedef J j_type; + typedef K k_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_, + typename call_traits::param_type j_, + typename call_traits::param_type k_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]), j(init[tuple_index<9>()]), + k(init[tuple_index<10>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; J j; + K k; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <12 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L> +struct tuple 12 + nil_t, nil_t, nil_t, +#endif + nil_t // Unused +> +: public tuple_base > { + + BOOST_STATIC_CONSTANT(int, length = 12); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; typedef J j_type; + typedef K k_type; typedef L l_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_, + typename call_traits::param_type j_, + typename call_traits::param_type k_, + typename call_traits::param_type l_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]), j(init[tuple_index<9>()]), + k(init[tuple_index<10>()]), l(init[tuple_index<11>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; J j; + K k; L l; +}; + +#if PHOENIX_LIMIT > 12 +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <13 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M> +struct tuple +: public tuple_base< + tuple > { + + BOOST_STATIC_CONSTANT(int, length = 13); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; typedef J j_type; + typedef K k_type; typedef L l_type; + typedef M m_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_, + typename call_traits::param_type j_, + typename call_traits::param_type k_, + typename call_traits::param_type l_, + typename call_traits::param_type m_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_), m(m_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]), j(init[tuple_index<9>()]), + k(init[tuple_index<10>()]), l(init[tuple_index<11>()]), + m(init[tuple_index<12>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; J j; + K k; L l; M m; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <14 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N> +struct tuple +: public tuple_base< + tuple > { + + BOOST_STATIC_CONSTANT(int, length = 14); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; typedef J j_type; + typedef K k_type; typedef L l_type; + typedef M m_type; typedef N n_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_, + typename call_traits::param_type j_, + typename call_traits::param_type k_, + typename call_traits::param_type l_, + typename call_traits::param_type m_, + typename call_traits::param_type n_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_), m(m_), n(n_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]), j(init[tuple_index<9>()]), + k(init[tuple_index<10>()]), l(init[tuple_index<11>()]), + m(init[tuple_index<12>()]), n(init[tuple_index<13>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; J j; + K k; L l; M m; N n; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// tuple <15 member> class +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename A, typename B, typename C, typename D, typename E, + typename F, typename G, typename H, typename I, typename J, + typename K, typename L, typename M, typename N, typename O> +struct tuple +: public tuple_base< + tuple > { + + BOOST_STATIC_CONSTANT(int, length = 15); + typedef A a_type; typedef B b_type; + typedef C c_type; typedef D d_type; + typedef E e_type; typedef F f_type; + typedef G g_type; typedef H h_type; + typedef I i_type; typedef J j_type; + typedef K k_type; typedef L l_type; + typedef M m_type; typedef N n_type; + typedef O o_type; + + tuple() {} + + tuple( + typename call_traits::param_type a_, + typename call_traits::param_type b_, + typename call_traits::param_type c_, + typename call_traits::param_type d_, + typename call_traits::param_type e_, + typename call_traits::param_type f_, + typename call_traits::param_type g_, + typename call_traits::param_type h_, + typename call_traits::param_type i_, + typename call_traits::param_type j_, + typename call_traits::param_type k_, + typename call_traits::param_type l_, + typename call_traits::param_type m_, + typename call_traits::param_type n_, + typename call_traits::param_type o_ + ): a(a_), b(b_), c(c_), d(d_), e(e_), + f(f_), g(g_), h(h_), i(i_), j(j_), + k(k_), l(l_), m(m_), n(n_), o(o_) {} + + template + tuple(TupleT const& init) + : a(init[tuple_index<0>()]), b(init[tuple_index<1>()]), + c(init[tuple_index<2>()]), d(init[tuple_index<3>()]), + e(init[tuple_index<4>()]), f(init[tuple_index<5>()]), + g(init[tuple_index<6>()]), h(init[tuple_index<7>()]), + i(init[tuple_index<8>()]), j(init[tuple_index<9>()]), + k(init[tuple_index<10>()]), l(init[tuple_index<11>()]), + m(init[tuple_index<12>()]), n(init[tuple_index<13>()]), + o(init[tuple_index<14>()]) + { BOOST_STATIC_ASSERT(TupleT::length == length); } + + A a; B b; C c; D d; E e; + F f; G g; H h; I i; J j; + K k; L l; M m; N n; O o; +}; + +#endif +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +} // namespace phoenix + +#endif diff --git a/include/boost/spirit/symbols.hpp b/include/boost/spirit/symbols.hpp new file mode 100644 index 000000000..4b5c0660e --- /dev/null +++ b/include/boost/spirit/symbols.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#if !defined(BOOST_SPIRIT_SYMBOLS_MAIN_HPP) +#define BOOST_SPIRIT_SYMBOLS_MAIN_HPP + +/////////////////////////////////////////////////////////////////////////////// +// +// Master header for Spirit.Symbols +// +/////////////////////////////////////////////////////////////////////////////// + +#include "boost/spirit/symbols/symbols.hpp" + +#endif // !defined(BOOST_SPIRIT_SYMBOLS_MAIN_HPP) diff --git a/include/boost/spirit/symbols/Makefile.am b/include/boost/spirit/symbols/Makefile.am new file mode 100644 index 000000000..1734210f5 --- /dev/null +++ b/include/boost/spirit/symbols/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = symbols.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/symbols diff --git a/include/boost/spirit/symbols/impl/Makefile.am b/include/boost/spirit/symbols/impl/Makefile.am new file mode 100644 index 000000000..278f3b2a2 --- /dev/null +++ b/include/boost/spirit/symbols/impl/Makefile.am @@ -0,0 +1,3 @@ +#This file generated by Makefileamgen.sh +spiritinclude_HEADERS = symbols.ipp tst.ipp +spiritincludedir = $(includedir)/spirit/boost/spirit/symbols/impl diff --git a/include/boost/spirit/symbols/impl/symbols.ipp b/include/boost/spirit/symbols/impl/symbols.ipp new file mode 100644 index 000000000..a71ac362a --- /dev/null +++ b/include/boost/spirit/symbols/impl/symbols.ipp @@ -0,0 +1,98 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_SYMBOLS_IPP +#define BOOST_SPIRIT_SYMBOLS_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include "boost/spirit/symbols/impl/tst.ipp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// +// symbols class implementation +// +/////////////////////////////////////////////////////////////////////////////// +template +inline symbols::symbols() +: SetT() +, add(*this) +{ +} + +////////////////////////////////// +template +symbols::symbols(symbols const& other) +: SetT(other) +, parser >() +, add(*this) +{ +} + +////////////////////////////////// +template +inline symbols::~symbols() +{} + +////////////////////////////////// +template +inline symbols& +symbols::operator=(symbols const& other) +{ + SetT::operator=(other); + return *this; +} + +////////////////////////////////// +template +inline symbol_inserter const& +symbols::operator=(CharT const* str) +{ + return add, str; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Symbol table utilities +// +/////////////////////////////////////////////////////////////////////////////// +template +inline T* +find(symbols const& table, CharT const* sym) +{ + CharT const* last = sym; + while (*last) + last++; + scanner<> scan(sym, last); + T* result = table.find(scan); + return scan.at_end()? result: 0; +} + +////////////////////////////////// +template +inline T* +add(symbols& table, CharT const* sym, T const& data) +{ + CharT const* last = sym; + while (*last) + last++; + scanner<> scan(sym, last); + if (table.find(scan)) + return 0; // symbol already contained in symbol table + table.add(sym, last, data); + return table.find(scan); // refind the inserted symbol +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/symbols/impl/tst.ipp b/include/boost/spirit/symbols/impl/tst.ipp new file mode 100644 index 000000000..1f9f4dcfa --- /dev/null +++ b/include/boost/spirit/symbols/impl/tst.ipp @@ -0,0 +1,272 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_TST_IPP +#define BOOST_SPIRIT_TST_IPP + +/////////////////////////////////////////////////////////////////////////////// +#include // for std::auto_ptr + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + + namespace impl + { + +/////////////////////////////////////////////////////////////////////////////// +// +// tst class +// +// Ternary Search Tree implementation. The data structure is faster than +// hashing for many typical search problems especially when the search +// interface is iterator based. Searching for a string of length k in a +// ternary search tree with n strings will require at most O(log n+k) +// character comparisons. TSTs are many times faster than hash tables +// for unsuccessful searches since mismatches are discovered earlier +// after examining only a few characters. Hash tables always examine an +// entire key when searching. +// +// For details see http://www.cs.princeton.edu/~rs/strings/. +// +// *** This is a low level class and is +// not meant for public consumption *** +// +/////////////////////////////////////////////////////////////////////////////// + template + struct tst_node + { + tst_node(CharT value_) + : value(value_) + , left(0) + , right(0) + { middle.link = 0; } + + ~tst_node() + { + delete left; + delete right; + if (value) + delete middle.link; + else + delete middle.data; + } + + tst_node* + clone() const + { + std::auto_ptr copy(new tst_node(value)); + + if (left) + copy->left = left->clone(); + if (right) + copy->right = right->clone(); + + if (value && middle.link) + { + copy->middle.link = middle.link->clone(); + } + else + { + std::auto_ptr mid_data(new T(*middle.data)); + copy->middle.data = mid_data.release(); + } + + return copy.release(); + } + + union center { + + tst_node* link; + T* data; + }; + + CharT value; + tst_node* left; + center middle; + tst_node* right; + }; + + /////////////////////////////////////////////////////////////////////////// + template + class tst + { + public: + + struct search_info + { + T* data; + unsigned length; + }; + + tst() + : root(0) {} + + tst(tst const& other) + : root(other.root ? other.root->clone() : 0) {} + + ~tst() + { delete root; } + + tst& + operator=(tst const& other) + { + if (this != &other) + { + node_t* new_root = other.root ? other.root->clone() : 0; + delete root; + root = new_root; + } + return *this; + } + + template + T* add(IteratorT first, IteratorT const& last, T const& data) + { + if (first == last) + return 0; + + node_t** np = &root; + CharT ch = *first; + + for (;;) + { + if (*np == 0 || ch == 0) + { + node_t* right = 0; + if (np != 0) + right = *np; + *np = new node_t(ch); + if (right) + (**np).right = right; + } + + if (ch < (**np).value) + { + np = &(**np).left; + } + else + { + if (ch == (**np).value) + { + if (ch == 0) + { + if ((**np).middle.data == 0) + { + (**np).middle.data = new T(data); + return (**np).middle.data; + } + else + { + // re-addition is disallowed + return 0; + } + } + ++first; + ch = (first == last) ? 0 : *first; + np = &(**np).middle.link; + } + else + { + np = &(**np).right; + } + } + } + } + + template + search_info find(ScannerT const& scan) const + { + search_info result = { 0, 0 }; + if (scan.at_end()) { + return result; + } + + typedef typename ScannerT::iterator_t iterator_t; + node_t* np = root; + CharT ch = *scan; + iterator_t save = scan.first; + iterator_t latest = scan.first; + unsigned latest_len = 0; + + while (np) + { + if (ch < np->value) + { + if (np->value == 0) + { + result.data = np->middle.data; + if (result.data) + { + latest = scan.first; + latest_len = result.length; + } + } + np = np->left; + } + else + { + if (ch == np->value) + { + if (scan.at_end()) + { + result.data = np->middle.data; + if (result.data) + { + latest = scan.first; + latest_len = result.length; + } + break; + } + + ++scan; + ch = scan.at_end() ? 0 : *scan; + np = np->middle.link; + ++result.length; + } + else + { + if (np->value == 0) + { + result.data = np->middle.data; + if (result.data) + { + latest = scan.first; + latest_len = result.length; + } + } + np = np->right; + } + } + } + + if (result.data == 0) + { + scan.first = save; + } + else + { + scan.first = latest; + result.length = latest_len; + } + return result; + } + + private: + + typedef tst_node node_t; + node_t* root; + }; + +/////////////////////////////////////////////////////////////////////////////// + } // namespace impl + +}} // namespace boost::spirit + +#endif diff --git a/include/boost/spirit/symbols/symbols.hpp b/include/boost/spirit/symbols/symbols.hpp new file mode 100644 index 000000000..b70bd02b8 --- /dev/null +++ b/include/boost/spirit/symbols/symbols.hpp @@ -0,0 +1,239 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Joel de Guzman + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_SYMBOLS_HPP +#define BOOST_SPIRIT_SYMBOLS_HPP + +/////////////////////////////////////////////////////////////////////////////// +#include + +#include "boost/ref.hpp" + +#include "boost/spirit/core/parser.hpp" +#include "boost/spirit/core/composite/directives.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +// Forward Declarations + +namespace impl +{ + template + class tst; +} + +template +class symbol_inserter; + +/////////////////////////////////////////////////////////////////////////////// +// +// symbols class +// +// This class implements a symbol table. The symbol table holds a +// dictionary of symbols where each symbol is a sequence of CharTs. +// The template class can work efficiently with 8, 16 and 32 bit +// characters. Mutable data of type T is associated with each +// symbol. +// +// The class is a parser. The parse member function returns +// additional information in the symbol_match class (see below). +// The additional data is a pointer to some data associated with +// the matching symbol. +// +// The actual set implementation is supplied by the SetT template +// parameter. By default, this uses the tst class (see tst.ipp). +// +// Symbols are added into the symbol table statically using the +// construct: +// +// sym = a, b, c, d ...; +// +// where sym is a symbol table and a..d are strings. Example: +// +// sym = "pineapple", "orange", "banana", "apple"; +// +// Alternatively, symbols may be added dynamically through the +// member functor 'add' (see symbol_inserter below). The member +// functor 'add' may be attached to a parser as a semantic action +// taking in a begin/end pair: +// +// p[sym.add] +// +// where p is a parser (and sym is a symbol table). On success, +// the matching portion of the input is added to the symbol table. +// +// 'add' may also be used to directly initialize data. Examples: +// +// sym.add("hello", 1)("crazy", 2)("world", 3); +// +/////////////////////////////////////////////////////////////////////////////// +template +< + typename T = int, + typename CharT = char, + typename SetT = impl::tst +> +class symbols +: private SetT +, public parser > +{ +public: + + typedef parser > parser_base_t; + typedef symbols self_t; + typedef self_t const& embed_t; + typedef T symbol_data_t; + typedef boost::reference_wrapper symbol_ref_t; + + symbols(); + symbols(symbols const& other); + ~symbols(); + + symbols& + operator=(symbols const& other); + + symbol_inserter const& + operator=(CharT const* str); + + template + struct result + { + typedef typename match_result::type type; + }; + + template + typename parser_result::type + parse_main(ScannerT const& scan) const + { + typedef typename ScannerT::iterator_t iterator_t; + iterator_t first = scan.first; + typename SetT::search_info result = SetT::find(scan); + + if (result.data) + return scan. + create_match( + result.length, + symbol_ref_t(*result.data), + first, + scan.first); + else + return scan.no_match(); + } + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename parser_result::type result_t; + return impl::implicit_lexeme_parse + (*this, scan, scan); + } + + template < typename ScannerT > + T* find(ScannerT const& scan) const + { return SetT::find(scan).data; } + + symbol_inserter const add; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Symbol table utilities +// +// add +// +// adds a symbol 'sym' (string) to a symbol table 'table' plus an +// optional data 'data' associated with the symbol. Returns a pointer to +// the data associated with the symbol or NULL if add failed (e.g. when +// the symbol is already added before). +// +// find +// +// finds a symbol 'sym' (string) from a symbol table 'table'. Returns a +// pointer to the data associated with the symbol or NULL if not found +// +/////////////////////////////////////////////////////////////////////////////// +template +T* add(symbols& table, CharT const* sym, T const& data = T()); + +template +T* find(symbols const& table, CharT const* sym); + +/////////////////////////////////////////////////////////////////////////////// +// +// symbol_inserter class +// +// The symbols class holds an instance of this class named 'add'. +// This can be called directly just like a member function, +// passing in a first/last iterator and optional data: +// +// sym.add(first, last, data); +// +// Or, passing in a C string and optional data: +// +// sym.add(c_string, data); +// +// where sym is a symbol table. The 'data' argument is optional. +// This may also be used as a semantic action since it conforms +// to the action interface (see action.hpp): +// +// p[sym.add] +// +/////////////////////////////////////////////////////////////////////////////// +template +class symbol_inserter +{ +public: + + symbol_inserter(SetT& set_) + : set(set_) {} + + template + symbol_inserter const& + operator()(IteratorT first, IteratorT const& last, T const& data = T()) const + { + set.add(first, last, data); + return *this; + } + + template + symbol_inserter const& + operator()(CharT const* str, T const& data = T()) const + { + CharT const* last = str; + while (*last) + last++; + set.add(str, last, data); + return *this; + } + + template + symbol_inserter const& + operator,(CharT const* str) const + { + CharT const* last = str; + while (*last) + last++; + set.add(str, last, T()); + return *this; + } + +private: + + SetT& set; +}; + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#include "boost/spirit/symbols/impl/symbols.ipp" +#endif diff --git a/include/boost/spirit/tree/Makefile.am b/include/boost/spirit/tree/Makefile.am new file mode 100644 index 000000000..87ae2f55a --- /dev/null +++ b/include/boost/spirit/tree/Makefile.am @@ -0,0 +1,4 @@ +#This file generated by Makefileamgen.sh +SUBDIRS = impl +spiritinclude_HEADERS = ast.hpp common.hpp parse_tree.hpp parse_tree_xml.hpp parsetree.dtd tree_iterator.hpp tree_to_xml.hpp +spiritincludedir = $(includedir)/spirit/boost/spirit/tree diff --git a/include/boost/spirit/tree/ast.hpp b/include/boost/spirit/tree/ast.hpp new file mode 100644 index 000000000..eeeca4979 --- /dev/null +++ b/include/boost/spirit/tree/ast.hpp @@ -0,0 +1,323 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_TREE_AST_HPP +#define BOOST_SPIRIT_TREE_AST_HPP + +#include "boost/spirit/tree/common.hpp" +#include "boost/spirit/core/scanner/scanner.hpp" + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +template +struct ast_tree_policy; + +////////////////////////////////// +// ast_match_policy is simply an id so the correct specialization of +// tree_policy can be found. +template < + typename IteratorT, + typename NodeFactoryT = node_val_data_factory +> +struct ast_match_policy : + public common_tree_match_policy< + ast_match_policy, + IteratorT, + NodeFactoryT, + ast_tree_policy< + ast_match_policy, + NodeFactoryT + > + > +{ +}; + +////////////////////////////////// +template +struct ast_tree_policy : + public common_tree_tree_policy +{ + typedef + typename common_tree_tree_policy::match_t + match_t; + typedef typename MatchPolicyT::iterator_t iterator_t; + + static void concat(match_t& a, match_t const& b) + { + BOOST_SPIRIT_ASSERT(a && b); + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) + BOOST_SPIRIT_DEBUG_OUT << "concat. a = " << a << + "\n\tb = " << b << std::endl; +#endif + typedef typename tree_match::container_t + container_t; + + // test for size() is nessecary, because no_tree_gen_node leaves a.trees + // and/or b.trees empty + if (0 != b.trees.size() && b.trees.begin()->value.is_root()) + { + BOOST_SPIRIT_ASSERT(b.trees.size() == 1); + + container_t tmp; + std::swap(a.trees, tmp); // save a into tmp + std::swap(b.trees, a.trees); // make b.trees[0] be new root (a.trees[0]) + container_t* pnon_root_trees = &a.trees; + while (pnon_root_trees->size() > 0 && + pnon_root_trees->begin()->value.is_root()) + { + pnon_root_trees = & pnon_root_trees->begin()->children; + } + pnon_root_trees->insert(pnon_root_trees->begin(), + tmp.begin(), tmp.end()); + } + else if (0 != a.trees.size() && a.trees.begin()->value.is_root()) + { + BOOST_SPIRIT_ASSERT(a.trees.size() == 1); + std::copy(b.trees.begin(), + b.trees.end(), + std::back_insert_iterator( + a.trees.begin()->children)); + } + else + { + std::copy(b.trees.begin(), + b.trees.end(), + std::back_insert_iterator(a.trees)); + } + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) + BOOST_SPIRIT_DEBUG_OUT << "after concat. a = " << a << std::endl; +#endif + + return; + } + + template + static void group_match(match_t& m, parser_id const& id, + Iterator1T const& first, Iterator2T const& last) + { + if (!m) + return; + + typedef typename tree_match::container_t + container_t; + typedef typename container_t::iterator cont_iterator_t; + typedef typename NodeFactoryT::template factory factory_t; + // only one node, so don't make a new level + if (m.trees.size() == 1) + { + // set rule_id's. There may have been multiple nodes created. + // Because of root_node[] they may be left-most children of the top + // node. + container_t* punset_id = &m.trees; + while (punset_id->size() > 0 && + punset_id->begin()->value.id() == 0) + { + punset_id->begin()->value.id(id); + punset_id = &punset_id->begin()->children; + } + + m.trees.begin()->value.is_root(false); + } + else + { + match_t newmatch(m.length(), + factory_t::create_node(first, last, false)); + + std::swap(newmatch.trees.begin()->children, m.trees); + // set this node and all it's unset children's rule_id + newmatch.trees.begin()->value.id(id); + for (cont_iterator_t i = newmatch.trees.begin(); + i != newmatch.trees.end(); + ++i) + { + if (i->value.id() == 0) + i->value.id(id); + } + m = newmatch; + } + } + + template + static void apply_op_to_match(FunctorT const& op, match_t& m) + { + op(m); + } +}; + +namespace impl { + + template + struct tree_policy_selector > + { + typedef ast_tree_policy< + ast_match_policy, NodeFactoryT> type; + }; + +} // namespace impl + + +////////////////////////////////// +struct gen_ast_node_parser_gen; + +template +struct gen_ast_node_parser +: public unary > > +{ + typedef gen_ast_node_parser self_t; + typedef gen_ast_node_parser_gen parser_generator_t; + typedef unary_parser_category parser_category_t; + + gen_ast_node_parser(T const& a) + : unary > >(a) {} + + template + typename parser_result::type + parse(ScannerT const& scan) const + { + typedef typename ScannerT::iteration_policy_t iteration_policy_t; + typedef typename ScannerT::match_policy_t::iterator_t iterator_t; + typedef typename ScannerT::match_policy_t::factory_t factory_t; + typedef ast_match_policy match_policy_t; + typedef typename ScannerT::action_policy_t action_policy_t; + typedef scanner_policies< + iteration_policy_t, + match_policy_t, + action_policy_t + > policies_t; + + return this->subject().parse(scan.change_policies(policies_t())); + } +}; + +////////////////////////////////// +struct gen_ast_node_parser_gen +{ + template + struct result { + + typedef gen_ast_node_parser type; + }; + + template + static gen_ast_node_parser + generate(parser const& s) + { + return gen_ast_node_parser(s.derived()); + } + + template + gen_ast_node_parser + operator[](parser const& s) const + { + return gen_ast_node_parser(s.derived()); + } +}; + +////////////////////////////////// +const gen_ast_node_parser_gen gen_ast_node_d = gen_ast_node_parser_gen(); + + +////////////////////////////////// +struct root_node_op +{ + template + void operator()(MatchT& m) const + { + BOOST_SPIRIT_ASSERT(m.trees.size() > 0); + m.trees.begin()->value.is_root(true); + } +}; + +const node_parser_gen root_node_d = + node_parser_gen(); + +/////////////////////////////////////////////////////////////////////////////// +// +// Parse functions for ASTs +// +/////////////////////////////////////////////////////////////////////////////// +template +tree_parse_info +ast_parse( + IteratorT const& first_, + IteratorT const& last_, + parser const& parser, + SkipT const& skip_) +{ + typedef skip_parser_iteration_policy iter_policy_t; + typedef + scanner_policies > + scanner_policies_t; + typedef scanner scanner_t; + + iter_policy_t iter_policy(skip_); + scanner_policies_t policies(iter_policy); + IteratorT first = first_; + scanner_t scan(first, last_, policies); + tree_match hit = parser.derived().parse(scan); + return tree_parse_info( + first, hit, hit && (first == last_), hit.length(), hit.trees); +} + +////////////////////////////////// +template +tree_parse_info +ast_parse( + IteratorT const& first_, + IteratorT const& last, + parser const& parser) +{ + IteratorT first = first_; + scanner< + IteratorT, + scanner_policies > + > scan(first, last); + tree_match hit = parser.derived().parse(scan); + return tree_parse_info(first, hit, hit && (first == last), + hit.length(), hit.trees); +} + +////////////////////////////////// +template +tree_parse_info +ast_parse( + CharT const* str, + parser const& parser, + SkipT const& skip) +{ + CharT const* last = str; + while (*last) + last++; + return ast_parse(str, last, parser, skip); +} + +////////////////////////////////// +template +tree_parse_info +ast_parse( + CharT const* str, + parser const& parser) +{ + CharT const* last = str; + while (*last) + { + last++; + } + return ast_parse(str, last, parser); +} + +/////////////////////////////////////////////////////////////////////////////// +}} // namespace boost::spirit + +#endif + diff --git a/include/boost/spirit/tree/common.hpp b/include/boost/spirit/tree/common.hpp new file mode 100644 index 000000000..dc760d8d8 --- /dev/null +++ b/include/boost/spirit/tree/common.hpp @@ -0,0 +1,1355 @@ +/*============================================================================= + Spirit V1.5.2 + Copyright (c) 2001-2003 Daniel Nuffer + http://spirit.sourceforge.net/ + + Permission to copy, use, modify, sell and distribute this software is + granted provided this copyright notice appears in all copies. This + software is provided "as is" without express or implied warranty, and + with no claim as to its suitability for any purpose. +=============================================================================*/ +#ifndef BOOST_SPIRIT_TREE_COMMON_HPP +#define BOOST_SPIRIT_TREE_COMMON_HPP + +#include + +#include +#include + +#include "boost/spirit/core.hpp" + +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +#define BOOST_SPIRIT_MP_TYPE_COMPUTER_ARGS typename T, typename Pizza = nil_t +#else +#define BOOST_SPIRIT_MP_TYPE_COMPUTER_ARGS typename T +#endif + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) +#include +#endif + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { + +/////////////////////////////////////////////////////////////////////////////// +template +struct tree_node; + +template +struct node_iter_data; + +template +void swap(tree_node& a, tree_node& b); + +template +void swap(node_iter_data& a, node_iter_data& b); + +namespace impl { + template + inline void cp_swap(T& t1, T& t2); +} + +template +struct tree_node +{ + typedef T parse_node_t; + typedef std::vector > children_t; + typedef typename children_t::iterator tree_iterator; + typedef typename children_t::const_iterator const_tree_iterator; + + T value; + children_t children; + + tree_node() + : value() + , children() + {} + + explicit tree_node(T const& v) + : value(v) + , children() + {} + + tree_node(T const& v, children_t const& c) + : value(v) + , children(c) + {} + + void swap(tree_node& x) + { + impl::cp_swap(value, x.value); + impl::cp_swap(children, x.children); + } + +// Intel V5.0.1 has a problem without this explicit operator= + tree_node &operator= (tree_node const &rhs) + { + tree_node(rhs).swap(*this); + return *this; + } +}; + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) +template +inline std::ostream& +operator<<(std::ostream& o, tree_node const& n) +{ + static int depth = 0; + o << "\n"; + for (int i = 0; i <= depth; ++i) + { + o << "\t"; + } + o << "(depth = " << depth++ << " value = " << n.value; + int c = 0; + for (typename tree_node::children_t::const_iterator it = n.children.begin(); + it != n.children.end(); ++it) + { + o << " children[" << c++ << "] = " << *it; + } + o << ")"; + --depth; + return o; +} +#endif + +////////////////////////////////// +template +struct node_iter_data +{ + typedef IteratorT iterator_t; + typedef IteratorT /*const*/ const_iterator_t; + + node_iter_data() + : first(), last(), is_root_(false), parser_id_(), value_() + {} + + node_iter_data(IteratorT const& _first, IteratorT const& _last) + : first(_first), last(_last), is_root_(false), parser_id_(), value_() + {} + + void swap(node_iter_data& x) + { + impl::cp_swap(first, x.first); + impl::cp_swap(last, x.last); + impl::cp_swap(parser_id_, x.parser_id_); + impl::cp_swap(is_root_, x.is_root_); + impl::cp_swap(value_, x.value_); + } + + IteratorT begin() + { + return first; + } + + IteratorT const& begin() const + { + return first; + } + + IteratorT end() + { + return last; + } + + IteratorT const& end() const + { + return last; + } + + bool is_root() const + { + return is_root_; + } + + void is_root(bool b) + { + is_root_ = b; + } + + parser_id id() const + { + return parser_id_; + } + + void id(parser_id r) + { + parser_id_ = r; + } + + ValueT const& value() const + { + return value_; + } + + void value(ValueT const& v) + { + value_ = v; + } +private: + IteratorT first, last; + bool is_root_; + parser_id parser_id_; + ValueT value_; + +public: +}; + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) +// value is default nil_t, so provide an operator<< for nil_t +inline std::ostream& +operator<<(std::ostream& o, nil_t const&) +{ + return o; +} + +template +inline std::ostream& +operator<<(std::ostream& o, node_iter_data const& n) +{ + o << "(id = " << n.id() << " text = \""; + typedef typename std::iterator_traits::value_type iterator_t; + std::copy(n.begin(), n.end(), std::ostream_iterator(o)); + o << "\" is_root = " << n.is_root() + << " value = " << n.value() << ")"; + return o; +} +#endif + +////////////////////////////////// +template +struct node_val_data +{ + typedef typename std::iterator_traits::value_type value_type; + typedef std::vector container_t; + typedef typename container_t::iterator iterator_t; + typedef typename container_t::const_iterator const_iterator_t; + + node_val_data() + : text(), is_root_(false), parser_id_(), value_() + {} + + node_val_data(IteratorT const& _first, IteratorT const& _last) + : text(_first, _last), is_root_(false), parser_id_(), value_() + {} + + // This constructor is for building text out of vector iterators + template + node_val_data(IteratorT2 const& _first, IteratorT2 const& _last) + : text(_first, _last), is_root_(false), parser_id_(), value_() + {} + + void swap(node_val_data& x) + { + impl::cp_swap(text, x.text); + impl::cp_swap(is_root_, x.is_root_); + impl::cp_swap(parser_id_, x.parser_id_); + impl::cp_swap(value_, x.value_); + } + + typename container_t::iterator begin() + { + return text.begin(); + } + + typename container_t::const_iterator begin() const + { + return text.begin(); + } + + typename container_t::iterator end() + { + return text.end(); + } + + typename container_t::const_iterator end() const + { + return text.end(); + } + + bool is_root() const + { + return is_root_; + } + + void is_root(bool b) + { + is_root_ = b; + } + + parser_id id() const + { + return parser_id_; + } + + void id(parser_id r) + { + parser_id_ = r; + } + + ValueT const& value() const + { + return value_; + } + + void value(ValueT const& v) + { + value_ = v; + } + +private: + container_t text; + bool is_root_; + parser_id parser_id_; + ValueT value_; +}; + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) +template +inline std::ostream& +operator<<(std::ostream& o, node_val_data const& n) +{ + o << "(id = " << n.id() << " text = \""; + typedef typename std::iterator_traits::value_type iterator_t; + std::copy(n.begin(), n.end(), std::ostream_iterator(o)); + o << "\" is_root = " << n.is_root() + << " value = " << n.value() << ")"; + return o; +} +#endif + +template +void swap(tree_node& a, tree_node& b) +{ + a.swap(b); +} + +template +void swap(node_iter_data& a, node_iter_data& b) +{ + a.swap(b); +} + + +////////////////////////////////// +template +class node_iter_data_factory; + +////////////////////////////////// +template +class node_iter_data_factory +{ +public: + // This inner class is so that node_iter_data_factory can simluate + // a template template parameter + template + class factory + { + public: + typedef IteratorT iterator_t; + typedef node_iter_data node_t; + + static node_t create_node(iterator_t const& first, iterator_t const& last, + bool /*is_leaf_node*/) + { + return node_t(first, last); + } + + static node_t empty_node() + { + return node_t(); + } + + // precondition: ContainerT contains a tree_node. And all + // iterators in the container point to the same sequence. + template + static node_t group_nodes(ContainerT const& nodes) + { + return node_t(nodes.begin()->value.begin(), + nodes.back().value.end()); + } + }; +}; + + +////////////////////////////////// +template +class node_val_data_factory +{ +public: + // This inner class is so that node_val_data_factory can simluate + // a template template parameter + template + class factory + { + public: + typedef IteratorT iterator_t; + typedef node_val_data node_t; + + static node_t create_node(iterator_t const& first, iterator_t const& last, + bool is_leaf_node) + { + if (is_leaf_node) + return node_t(first, last); + else + return node_t(); + } + + static node_t empty_node() + { + return node_t(); + } + + template + static node_t group_nodes(ContainerT const& nodes) + { + typename node_t::container_t c; + // copy all the nodes text into a new one + for (typename ContainerT::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + // See docs: token_node_d or leaf_node_d cannot be used with a + // rule inside the []. + assert(i->children.size() == 0); + c.insert(c.end(), i->value.begin(), i->value.end()); + } + return node_t(c.begin(), c.end()); + } + }; +}; + + +////////////////////////////////// +template +class node_all_val_data_factory; + +////////////////////////////////// +template +class node_all_val_data_factory +{ +public: + // This inner class is so that node_all_val_data_factory can simluate + // a template template parameter + template + class factory + { + public: + typedef IteratorT iterator_t; + typedef node_val_data node_t; + + static node_t create_node(iterator_t const& first, iterator_t const& last, + bool /*is_leaf_node*/) + { + return node_t(first, last); + } + + static node_t empty_node() + { + return node_t(); + } + + template + static node_t group_nodes(ContainerT const& nodes) + { + typename node_t::container_t c; + // copy all the nodes text into a new one + for (typename ContainerT::const_iterator i = nodes.begin(); + i != nodes.end(); ++i) + { + // See docs: token_node_d or leaf_node_d cannot be used with a + // rule inside the []. + assert(i->children.size() == 0); + c.insert(c.end(), i->value.begin(), i->value.end()); + } + return node_t(c.begin(), c.end()); + } + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// forward declaration +template < + typename IteratorT, + typename NodeFactoryT = node_val_data_factory, + typename T = nil_t +> +class tree_match; + +namespace impl { + template + struct tree_match_attr + { + template + static T get(MatchT const& m) + { return T(m.value()); } + + template + static T get(tree_match const& /*m*/) + { return T(); } + + static T get_default() + { return T(); } + }; + + ////////////////////////////////// + template + struct tree_match_attr > + { + template + static boost::reference_wrapper + get(MatchT const& m) + { return boost::reference_wrapper(m.value()); } + + template + static boost::reference_wrapper + get(tree_match const& /*m*/) + { + static T v; + return boost::reference_wrapper(v); + } + + static boost::reference_wrapper + get_default() + { + static T v; + return boost::reference_wrapper(v); + } + }; + + ////////////////////////////////// + template <> + struct tree_match_attr + { + template + static nil_t get(MatchT const& /*m*/) + { return nil_t(); } + static nil_t get_default() + { return nil_t(); } + }; + + // can't call unqualified swap from within classname::swap + // as Koenig lookup rules will find only the classname::swap + // member function not the global declaration, so use cp_swap + // as a forwarding function (JM): +#if __GNUC__ == 2 + using ::std::swap; +#endif + template + inline void cp_swap(T& t1, T& t2) + { + using std::swap; + using boost::spirit::swap; + using boost::swap; + swap(t1, t2); + } +} + +////////////////////////////////// +template +class tree_match +{ +public: + typedef typename NodeFactoryT::template factory node_factory_t; + typedef typename node_factory_t::node_t parse_node_t; + typedef tree_node node_t; + typedef typename node_t::children_t container_t; + typedef typename container_t::iterator tree_iterator; + typedef typename container_t::const_iterator const_tree_iterator; + + typedef T attr_t; + typedef typename boost::call_traits::param_type param_type; + typedef typename boost::call_traits::reference reference; + typedef typename boost::call_traits::const_reference const_reference; + + tree_match() + : len(-1), trees(), val(impl::tree_match_attr::get_default()) + {} + + explicit + tree_match(unsigned length) + : len(length), trees(), val(impl::tree_match_attr::get_default()) + {} + + tree_match(unsigned length, parse_node_t const& n) + : len(length), trees(), val(impl::tree_match_attr::get_default()) + { + trees.push_back(node_t(n)); + } + + tree_match(unsigned length, param_type val_, parse_node_t const& n) + : len(length), trees(), val(val_) + { + trees.push_back(node_t(n)); + } + + template + tree_match(match const& other) + : len(other.length()), trees(), val(impl::tree_match_attr::get(other)) + {} + + template + tree_match(tree_match const& other) + : len(other.length()), trees(), val(impl::tree_match_attr::get(other)) + { + impl::cp_swap(trees, other.trees); + } + + template + tree_match& + operator=(match const& other) + { + len = other.length(); + val = impl::tree_match_attr::get(other); + return *this; + } + + template + tree_match& + operator=(tree_match const& other) + { + len = other.length(); + val = impl::tree_match_attr::get(other); + impl::cp_swap(trees, other.trees); + return *this; + } + + tree_match(tree_match const& x) + : len(x.len), trees() + { + // use auto_ptr like ownership for the trees data member + impl::cp_swap(trees, x.trees); + } + + tree_match& operator=(tree_match const& x) + { + tree_match tmp(x); + this->swap(tmp); + return *this; + } + + void swap(tree_match& x) + { + impl::cp_swap(len, x.len); + impl::cp_swap(trees, x.trees); + } + + operator impl::safe_bool() const + { return BOOST_SPIRIT_SAFE_BOOL(len >= 0); } + + bool operator!() const + { return len < 0; } + + int length() const { return len; } + const_reference value() const { return val; } + reference value() { return val; } + + template + void + concat(MatchT const& other) + { + BOOST_SPIRIT_ASSERT(*this && other); + len += other.length(); + } + + int len; + mutable container_t trees; + T val; +}; + +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) +template +inline std::ostream& +operator<<(std::ostream& o, tree_match const& m) +{ + typedef + typename tree_match::container_t::iterator + iterator; + + o << "(length = " << m.length(); + int c = 0; + for (iterator i = m.trees.begin(); i != m.trees.end(); ++i) + { + o << " trees[" << c++ << "] = " << *i; + } + o << ")"; + return o; +} +#endif + +////////////////////////////////// +struct tree_policy +{ + template + static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/) + {} + + template + static void group_match(MatchT& /*m*/, parser_id const& /*id*/, + Iterator1T const& /*first*/, Iterator2T const& /*last*/) + {} + + template + static void concat(MatchT& /*a*/, MatchT const& /*b*/) + {} +}; + +////////////////////////////////// +template < + typename MatchPolicyT, + typename IteratorT, + typename NodeFactoryT, + typename TreePolicyT +> +struct common_tree_match_policy +{ + template + struct result { typedef tree_match type; }; + + typedef tree_match match_t; + typedef IteratorT iterator_t; + typedef TreePolicyT tree_policy_t; + typedef NodeFactoryT factory_t; + + static const match_t no_match() { return match_t(); } + static const match_t empty_match() + { return match_t(0, tree_policy_t::empty_node()); } + + template + static match_t create_match( + unsigned length, + AttrT const& /*val*/, + Iterator1T const& first, + Iterator2T const& last) + { +#if defined(BOOST_SPIRIT_DEBUG) && (BOOST_SPIRIT_DEBUG_FLAGS_NODES & BOOST_SPIRIT_DEBUG_FLAGS_TREES) + BOOST_SPIRIT_DEBUG_OUT << "create_node. creating node" + " text: \""; + for (Iterator1T it = first; it != last; ++it) + BOOST_SPIRIT_DEBUG_OUT << *it; + BOOST_SPIRIT_DEBUG_OUT << "\"" << std::endl; +#endif + return match_t(length, /*val,*/ + tree_policy_t::create_node(length, first, last, true)); + } + + template + static void concat_match(Match1T& a, Match2T const& b) + { + BOOST_SPIRIT_ASSERT(a && b); + if (a.length() == 0) + { + a = b; + return; + } + else if (b.length() == 0) + { + return; + } + a.concat(b); + tree_policy_t::concat(a, b); + } + + template + void + group_match( + MatchT& m, + parser_id const& id, + IteratorT2 const& first, + IteratorT2 const& last) const + { + tree_policy_t::group_match(m, id, first, last); + } +}; + +////////////////////////////////// +template +struct common_tree_tree_policy +{ + typedef typename MatchPolicyT::iterator_t iterator_t; + typedef typename MatchPolicyT::match_t match_t; + typedef typename NodeFactoryT::template factory factory_t; + typedef typename factory_t::node_t node_t; + + template + static node_t + create_node(int /*length*/, Iterator1T const& first, Iterator2T const& last, bool leaf_node) + { + return factory_t::create_node(first, last, leaf_node); + } + + static node_t + empty_node() + { + return factory_t::empty_node(); + } + + template + static void apply_op_to_match(FunctorT const& op, match_t& m) + { + op(m); + } +}; + +////////////////////////////////// +// directives to modify how the parse tree is generated + +struct no_tree_gen_node_parser_gen; + +template +struct no_tree_gen_node_parser +: public unary > > +{ + typedef no_tree_gen_node_parser self_t; + typedef no_tree_gen_node_parser_gen parser_generator_t; + typedef unary_parser_category parser_category_t; + + no_tree_gen_node_parser(T const& a) + : unary > >(a) {} + + template + typename parser_result::type + parse(ScannerT const& scanner) const + { + typedef typename ScannerT::iteration_policy_t iteration_policy_t; + typedef match_policy match_policy_t; + typedef typename ScannerT::action_policy_t action_policy_t; + typedef scanner_policies< + iteration_policy_t, + match_policy_t, + action_policy_t + > policies_t; + + return this->subject().parse(scanner.change_policies(policies_t())); + } +}; + +////////////////////////////////// +struct no_tree_gen_node_parser_gen +{ + template + struct result { + + typedef no_tree_gen_node_parser type; + }; + + template + static no_tree_gen_node_parser + generate(parser const& s) + { + return no_tree_gen_node_parser(s.derived()); + } + + template + no_tree_gen_node_parser + operator[](parser const& s) const + { + return no_tree_gen_node_parser(s.derived()); + } +}; + +////////////////////////////////// +const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen(); + + +////////////////////////////////// +namespace impl { + +template +struct tree_policy_selector +{ + typedef tree_policy type; +}; + +} // namespace impl +////////////////////////////////// +template +struct node_parser_gen; + +template +struct node_parser +: public unary > > +{ + typedef node_parser self_t; + typedef node_parser_gen parser_generator_t; + typedef unary_parser_category parser_category_t; + + node_parser(T const& a) + : unary > >(a) {} + + template + typename parser_result::type + parse(ScannerT const& scanner) const + { + typename parser_result::type hit = this->subject().parse(scanner); + if (hit) + { + impl::tree_policy_selector::type::apply_op_to_match(NodeParserT(), hit); + } + return hit; + } +}; + +////////////////////////////////// +template +struct node_parser_gen +{ + template + struct result { + + typedef node_parser type; + }; + + template + static node_parser + generate(parser const& s) + { + return node_parser(s.derived()); + } + + template + node_parser + operator[](parser const& s) const + { + return node_parser(s.derived()); + } +}; + +struct discard_node_op +{ + template + void operator()(MatchT& m) const + { + m.trees.clear(); + } +}; + +const node_parser_gen discard_node_d = + node_parser_gen(); + +struct leaf_node_op +{ + template + void operator()(MatchT& m) const + { + if (m.trees.size() == 1) + { + m.trees.begin()->children.clear(); + } + else if (m.trees.size() > 1) + { + typedef typename MatchT::node_factory_t node_factory_t; + m = MatchT(m.length(), node_factory_t::group_nodes(m.trees)); + } + } +}; + +const node_parser_gen leaf_node_d = node_parser_gen(); +const node_parser_gen token_node_d = + node_parser_gen(); + +struct infix_node_op +{ + template + void operator()(MatchT& m) const + { + typedef typename MatchT::container_t container_t; + typedef typename MatchT::container_t::iterator iter_t; + typedef typename MatchT::container_t::value_type value_t; + + using std::swap; + using boost::swap; + using boost::spirit::swap; + + // copying the tree nodes is expensive, since it may copy a whole + // tree. swapping them is cheap, so swap the nodes we want into + // a new container of children. + bool keep = true; + container_t new_children; + for (iter_t i = m.trees.begin(); i != m.trees.end(); ++i) + { + if (keep) + { + // move the child node + new_children.push_back(value_t()); + swap(new_children.back(), *i); + keep = false; + } + else + { + // ignore this child node + keep = true; + } + } + swap(m.trees, new_children); + } +}; + +const node_parser_gen infix_node_d = + node_parser_gen(); + +struct discard_first_node_op +{ + template + void operator()(MatchT& m) const + { + typedef typename MatchT::container_t container_t; + typedef typename MatchT::container_t::iterator iter_t; + typedef typename MatchT::container_t::value_type value_t; + + using std::swap; + using boost::swap; + using boost::spirit::swap; + + // copying the tree nodes is expensive, since it may copy a whole + // tree. swapping them is cheap, so swap the nodes we want into + // a new container of children, instead of saying + // m.trees.erase(m.trees.begin()) because, on a vector that will cause + // all the nodes afterwards to be copied into the previous position. + container_t new_children; + iter_t i = m.trees.begin(); + for (++i; i != m.trees.end(); ++i) + { + // move the child node + new_children.push_back(value_t()); + swap(new_children.back(), *i); + } + swap(m.trees, new_children); + } +}; + +const node_parser_gen discard_first_node_d = + node_parser_gen(); + +struct discard_last_node_op +{ + template + void operator()(MatchT& m) const + { + m.trees.pop_back(); + } +}; + +const node_parser_gen discard_last_node_d = + node_parser_gen(); + +struct inner_node_op +{ + template + void operator()(MatchT& m) const + { + typedef typename MatchT::container_t container_t; + typedef typename MatchT::container_t::iterator iter_t; + typedef typename MatchT::container_t::value_type value_t; + + using std::swap; + using boost::swap; + using boost::spirit::swap; + + // copying the tree nodes is expensive, since it may copy a whole + // tree. swapping them is cheap, so swap the nodes we want into + // a new container of children, instead of saying + // m.trees.erase(m.trees.begin()) because, on a vector that will cause + // all the nodes afterwards to be copied into the previous position. + container_t new_children; + m.trees.pop_back(); // erase the last element + iter_t i = m.trees.begin(); // skip over the first element + for (++i; i != m.trees.end(); ++i) + { + // move the child node + new_children.push_back(value_t()); + swap(new_children.back(), *i); + } + swap(m.trees, new_children); + } +}; + +const node_parser_gen inner_node_d = + node_parser_gen(); + + +////////////////////////////////// +// action_directive_parser and action_directive_parser_gen +// are meant to be used as a template to create directives that +// generate action classes. For example access_match and +// access_node. The ActionParserT template parameter must be +// a class that has an innter class called action that is templated +// on the parser type and the action type. +template +struct action_directive_parser_gen; + +template +struct action_directive_parser +: public unary > > +{ + typedef action_directive_parser self_t; + typedef action_directive_parser_gen parser_generator_t; + typedef unary_parser_category parser_category_t; + + action_directive_parser(T const& a) + : unary > >(a) {} + + template + typename parser_result::type + parse(ScannerT const& scanner) const + { + return this->subject().parse(scanner); + } + + template + typename ActionParserT::template action, ActionT> + operator[](ActionT const& actor) const + { + typedef typename + ActionParserT::template action + action_t; + return action_t(*this, actor); + } +}; + +////////////////////////////////// +template +struct action_directive_parser_gen +{ + template + struct result { + + typedef action_directive_parser type; + }; + + template + static action_directive_parser + generate(parser const& s) + { + return action_directive_parser(s.derived()); + } + + template + action_directive_parser + operator[](parser const& s) const + { + return action_directive_parser(s.derived()); + } +}; + +////////////////////////////////// +// Calls the attached action passing it the match from the parser +// and the first and last iterators +struct access_match_action +{ + // inner template class to simulate template-template parameters + template + struct action + : public unary > > + { + typedef action_parser_category parser_category; + typedef action self_t; + + action( ParserT const& subject, + ActionT const& actor_); + + template + typename parser_result::type + parse(ScannerT const& scanner) const; + + ActionT const &predicate() const; + + private: + ActionT actor; + }; +}; + +////////////////////////////////// +template +access_match_action::action::action( + ParserT const& subject, + ActionT const& actor_) +: unary > >(subject) +, actor(actor_) +{} + +////////////////////////////////// +template +template +typename parser_result, ScannerT>::type +access_match_action::action:: +parse(ScannerT const& scan) const +{ + typedef typename parser_result::type result_t; + if (!scan.at_end()) + { + result_t hit = this->subject().parse(scan); + actor(hit, scan.first, scan.last); + return hit; + } + return scan.no_match(); +} + +////////////////////////////////// +template +ActionT const &access_match_action::action::predicate() const +{ + return actor; +} + +////////////////////////////////// +const action_directive_parser_gen access_match_d + = action_directive_parser_gen(); + + + +////////////////////////////////// +// Calls the attached action passing it the node from the parser +// and the first and last iterators +struct access_node_action +{ + // inner template class to simulate template-template parameters + template + struct action + : public unary > > + { + typedef action_parser_category parser_category; + typedef action self_t; + + action( ParserT const& subject, + ActionT const& actor_); + + template + typename parser_result::type + parse(ScannerT const& scanner) const; + + ActionT const &predicate() const; + + private: + ActionT actor; + }; +}; + +////////////////////////////////// +template +access_node_action::action::action( + ParserT const& subject, + ActionT const& actor_) +: unary > >(subject) +, actor(actor_) +{} + +////////////////////////////////// +template +template +typename parser_result, ScannerT>::type +access_node_action::action:: +parse(ScannerT const& scan) const +{ + typedef typename parser_result::type result_t; + if (!scan.at_end()) + { + result_t hit = this->subject().parse(scan); + if (hit && hit.trees.size() > 0) + actor(*hit.trees.begin(), scan.first, scan.last); + return hit; + } + return scan.no_match(); +} + +////////////////////////////////// +template +ActionT const &access_node_action::action::predicate() const +{ + return actor; +} + +////////////////////////////////// +const action_directive_parser_gen access_node_d + = action_directive_parser_gen(); + + + +////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// +// tree_parse_info +// +// Results returned by the tree parse functions: +// +// stop: points to the final parse position (i.e parsing +// processed the input up to this point). +// +// match: true if parsing is successful. This may be full: +// the parser consumed all the input, or partial: +// the parser consumed only a portion of the input. +// +// full: true when we have a full match (i.e the parser +// consumed all the input. +// +// length: The number of characters consumed by the parser. +// This is valid only if we have a successful match +// (either partial or full). A negative value means +// that the match is unsucessful. +// +// trees: Contains the root node(s) of the tree. +// +/////////////////////////////////////////////////////////////////////////////// +template < + typename IteratorT = char const *, + typename NodeFactoryT = node_val_data_factory, + typename T = nil_t +> +struct tree_parse_info { + + IteratorT stop; + bool match; + bool full; + unsigned length; + typename tree_match::container_t trees; + + tree_parse_info() + : stop() + , match(false) + , full(false) + , length(0) + , trees() + {} + + template + tree_parse_info(tree_parse_info const& pi) + : stop(pi.stop) + , match(pi.match) + , full(pi.full) + , length(pi.length) + , trees() + { + using std::swap; + using boost::swap; + using boost::spirit::swap; + + // use auto_ptr like ownership for the trees data member + swap(trees, pi.trees); + } + + tree_parse_info( + IteratorT stop_, + bool match_, + bool full_, + unsigned length_, + typename tree_match::container_t trees_) + : stop(stop_) + , match(match_) + , full(full_) + , length(length_) + , trees() + { + using std::swap; + using boost::swap; + using boost::spirit::swap; + + // use auto_ptr like ownership for the trees data member + swap(trees, trees_); + } +}; + +}} // namespace boost::spirit + +#endif + +#undef BOOST_SPIRIT_MP_TYPE_COMPUTER_ARGS