From 933c4ffab7def1eeb6b5c02c6678d62675c8d0c0 Mon Sep 17 00:00:00 2001 From: Michael Andres Date: Mon, 2 Jan 2006 00:24:38 +0000 Subject: [PATCH] tagfile parser --- configure.ac | 1 + devel/devel.ma/Main.cc | 85 ++++++-------- devel/devel.ma/Makefile.am | 7 +- devel/devel.ma/Parse.cc | 148 ++++++++++++++++++++++++ devel/devel.ma/ma_test | 2 +- zypp/parser/Makefile.am | 16 ++- zypp/parser/Spirit.cc | 61 ++++++++++ zypp/parser/Spirit.h | 210 +++++++++++++++++++++++++++++++++ zypp/parser/tagfile/.cvsignore | 8 ++ zypp/parser/tagfile/Makefile.am | 22 ++++ zypp/parser/tagfile/Tags.cc | 59 ++++++++++ zypp/parser/tagfile/Tags.h | 249 ++++++++++++++++++++++++++++++++++++++++ 12 files changed, 812 insertions(+), 56 deletions(-) create mode 100644 devel/devel.ma/Parse.cc create mode 100644 zypp/parser/Spirit.cc create mode 100644 zypp/parser/Spirit.h create mode 100644 zypp/parser/tagfile/.cvsignore create mode 100644 zypp/parser/tagfile/Makefile.am create mode 100644 zypp/parser/tagfile/Tags.cc create mode 100644 zypp/parser/tagfile/Tags.h diff --git a/configure.ac b/configure.ac index 67f2b49..add3eae 100644 --- a/configure.ac +++ b/configure.ac @@ -165,6 +165,7 @@ AC_OUTPUT( \ zypp/parser/Makefile \ zypp/parser/yum/Makefile \ zypp/parser/yum/schema/Makefile \ + zypp/parser/tagfile/Makefile \ zypp/solver/Makefile \ zypp/solver/testsuite/Makefile \ zypp/solver/testsuite/lib/Makefile \ diff --git a/devel/devel.ma/Main.cc b/devel/devel.ma/Main.cc index 7001e3b..e80e1d1 100644 --- a/devel/devel.ma/Main.cc +++ b/devel/devel.ma/Main.cc @@ -1,46 +1,43 @@ #include #include -#include -#include -#include #include -#include -#include -#include - -#include -#include -#include +#include using namespace std; using namespace zypp; +// work around flaw in y2logview +template + void printOnHack( const _Tp & obj ) + { + MIL << obj << endl; + }; -void test( long long v ) -{ - ByteCount b( v ); - unsigned fw = 7; - unsigned sw = 1; - unsigned p = 2; - MIL << "'" << b << "'\t" - << "'" << b.asString( ByteCount::B, fw, sw, p ) << "'\t" - << "'" << b.asString( ByteCount::K, fw, sw, p ) << "'\t" - << "'" << b.asString( ByteCount::M, fw, sw, p ) << "'\t" - << "'" << b.asString( ByteCount::G, fw, sw, p ) << "'\t" - << "'" << b.asString( ByteCount::T, fw, sw, p ) << "'" << endl; -} -void test2( long long v ) +/////////////////////////////////////////////////////////////////// +// Just for the stats +struct Measure { - ByteCount b( v ); - unsigned fw = 7; - unsigned sw = 1; - unsigned p = 2; - MIL << b.asString( ByteCount::B ) << "-----------------" << endl; - MIL << "'" << b.fullBlocks( ByteCount::B ) << "'\t" - << "'" << b.blocks( ByteCount::B ) << endl; - MIL << "'" << b.fullBlocks( ByteCount::K ) << "'\t" - << "'" << b.blocks( ByteCount::K ) << endl; + time_t _begin; + Measure() + : _begin( time(NULL) ) + { + USR << "START MEASURE..." << endl; + } + ~Measure() + { + USR << "DURATION: " << (time(NULL)-_begin) << " sec." << endl; + } +}; + +/////////////////////////////////////////////////////////////////// +// Print stream status +ostream & operator<<( ostream & str, const istream & obj ) { + return str + << (obj.good() ? 'g' : '_') + << (obj.eof() ? 'e' : '_') + << (obj.fail() ? 'F' : '_') + << (obj.bad() ? 'B' : '_'); } /****************************************************************** @@ -50,24 +47,18 @@ void test2( long long v ) */ int main( int argc, char * argv[] ) { - INT << "===[START]==========================================" << endl; - - for ( long long i = 1; i < 10000000000000LL; i*=2 ) + --argc; + ++argv; + if ( ! argc ) { - test( i ); + cerr << "Usage: prognme " << endl; + return 1; } + string file( argv[0] ); + + INT << "===[START]==========================================" << endl; - test2( -1025 ); - test2( -1024 ); - test2( -2 ); - test2( -1 ); - test2( 0 ); - test2( 1 ); - test2( 2 ); - test2( 1024 ); - test2( 1025 ); INT << "===[END]============================================" << endl; return 0; } - diff --git a/devel/devel.ma/Makefile.am b/devel/devel.ma/Makefile.am index 47552f8..b6cd68f 100644 --- a/devel/devel.ma/Makefile.am +++ b/devel/devel.ma/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in ## ################################################## -noinst_PROGRAMS = Main Main.debug PtrTest +noinst_PROGRAMS = Main Main.debug Parse ## ################################################## @@ -12,7 +12,7 @@ AM_LDFLAGS = AM_CXXFLAGS = # gperf: -pg -LDADD = $(top_srcdir)/zypp/lib@PACKAGE@.la -lboost_regex +LDADD = $(top_srcdir)/zypp/lib@PACKAGE@.la -lboost_regex ## ################################################## @@ -23,7 +23,8 @@ Main_debug_LDFLAGS = -static ## ################################################## -PtrTest_SOURCES = PtrTest.cc +Parse_SOURCES = Parse.cc +Parse_LDFLAGS = -static ## ################################################## diff --git a/devel/devel.ma/Parse.cc b/devel/devel.ma/Parse.cc new file mode 100644 index 0000000..56e373c --- /dev/null +++ b/devel/devel.ma/Parse.cc @@ -0,0 +1,148 @@ +//http://www.boost.org/libs/libraries.htm +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace tagfile + { ///////////////////////////////////////////////////////////////// + + void echoOn( std::ostream & str, + iterator_t first, const iterator_t last, + const char* s = "" ) + { + //return; + str << first.get_position() << last.get_position(); + str << s << ">>"; + while ( first != last ) + str << *first++; + str << "<< " << std::endl; + } + + void echo( iterator_t first, const iterator_t last, const char* s = "" ) + { + echoOn( DBG, first, last, s ); + } + void mecho( iterator_t first, const iterator_t last, const char* s = "" ) + { + echoOn( MIL, first, last, s ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace tagfile + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// +// Types +// +//////////////////////////////////////////////////////////////////////////// +using std::endl; +using std::list; +using std::string; +using namespace zypp; +using namespace zypp::parser::tagfile; +typedef scanner scanner_t; +typedef rule rule_t; +//////////////////////////////////////////////////////////////////////////// +// +// Just for the stats +// +//////////////////////////////////////////////////////////////////////////// +struct Measure +{ + time_t _begin; + Measure() + : _begin( time(NULL) ) + { + USR << "START MEASURE..." << endl; + } + ~Measure() + { + USR << "DURATION: " << (time(NULL)-_begin) << " sec." << endl; + } +}; +//////////////////////////////////////////////////////////////////////////// +// +// Main +// +//////////////////////////////////////////////////////////////////////////// +int main( int argc, char* argv[] ) +{ + INT << "===[START]==========================================" << endl; + string infile( "p" ); + if (argc >= 2 ) + infile = argv[1]; + + // Create a file iterator for this file + fiterator_t first(infile); + if (!first) + { + ERR << "Unable to open file!\n"; + return -1; + } + // Create an EOF iterator + fiterator_t last = first.make_end(); + + // Create position iterators + iterator_t begin( first, last, infile ); + iterator_t end; + + // Result var + SingleTag stag; + MultiTag mtag; + STag stagData; + MTag mtagData; + + rule_t file = end_p + | ( stag + | mtag + | ( *blank_p + >> !( ch_p('#') + >> *(anychar_p - eol_p) + ) + >> (eol_p|end_p) + | error_report_p( "neither empty nor comment" ) + ) + ) + >> file; + + // Parse + shared_ptr duration( new Measure ); + parse_info info + = parse( begin, end, file ); + duration.reset(); + + // Check for fail... + if ( info.full ) + USR << "Parse succeeded!\n"; + else if ( info.hit ) + { + ERR << "Parse partial!\n"; + ERR << " at pos " << info.length << endl; + } + else + { + ERR << "Parse failed!\n"; + ERR << " at pos " << info.length << endl; + } + + INT << "===[END]============================================" << endl; + return 0; +} diff --git a/devel/devel.ma/ma_test b/devel/devel.ma/ma_test index fc44c2f..016be37 100755 --- a/devel/devel.ma/ma_test +++ b/devel/devel.ma/ma_test @@ -29,7 +29,7 @@ else MAKE=make fi -$MAKE -C ../../zypp || exit 1 +#$MAKE -C ../../zypp || exit 1 $MAKE $PRG || exit 1 ./$PRG "$@" 2> $LPIPE diff --git a/zypp/parser/Makefile.am b/zypp/parser/Makefile.am index 4a29ecf..be1872d 100644 --- a/zypp/parser/Makefile.am +++ b/zypp/parser/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in ## ################################################## -SUBDIRS = yum +SUBDIRS = yum tagfile INCLUDES = -I$(oldincludedir)/libxml2 @@ -9,19 +9,25 @@ INCLUDES = -I$(oldincludedir)/libxml2 include_HEADERS = \ XMLNodeIterator.h \ - LibXMLHelper.h + LibXMLHelper.h \ + \ + Spirit.h noinst_LTLIBRARIES = lib@PACKAGE@_parser.la + ## ################################################## lib@PACKAGE@_parser_la_SOURCES = \ XMLNodeIterator.cc \ - LibXMLHelper.cc + LibXMLHelper.cc \ + \ + Spirit.cc lib@PACKAGE@_parser_la_LIBADD = yum/lib@PACKAGE@_parser_yum.la \ - -lxml2 \ - -lz + -lxml2 \ + -lz \ + tagfile/lib@PACKAGE@_parser_tagfile.la ## ################################################## diff --git a/zypp/parser/Spirit.cc b/zypp/parser/Spirit.cc new file mode 100644 index 0000000..675a8ec --- /dev/null +++ b/zypp/parser/Spirit.cc @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/Spirit.cc + * +*/ +#include + +#include "zypp/base/Logger.h" +#include "zypp/parser/Spirit.h" + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace boost +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace spirit + { ///////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const file_position_and_offset & obj ) + { + return str << obj.file + << '[' << obj.offset << "](" + << obj.line << ':' << obj.column << ')'; + } + + ///////////////////////////////////////////////////////////////// + } // namespace spirit + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace boost +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace spirit + { ///////////////////////////////////////////////////////////////// + + std::ostream & error_report_parser::errstream() + { return ERR; } + + ///////////////////////////////////////////////////////////////// + } // namespace spirit + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/Spirit.h b/zypp/parser/Spirit.h new file mode 100644 index 0000000..8099d8b --- /dev/null +++ b/zypp/parser/Spirit.h @@ -0,0 +1,210 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/Spirit.h + * +*/ +#ifndef ZYPP_PARSER_SPIRIT_H +#define ZYPP_PARSER_SPIRIT_H + +#include +#include +#include +#include +#include +#include +#include + +#include +/////////////////////////////////////////////////////////////////// +namespace boost +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace spirit + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : file_position_and_offset + // + /** A structure to hold positional information. + * This includes file name and offset, line and column. + * Suitable to customize position_iterator. + */ + struct file_position_and_offset + { + std::string file; + std::streamoff offset; + unsigned line; + unsigned column; + + file_position_and_offset( const std::string & file_r = std::string(), + std::streamoff offset_r = 0, + unsigned line_r = 1, + unsigned column_r = 1 ) + : file ( file_r ) + , offset( offset_r ) + , line ( line_r ) + , column( column_r ) + {} + + bool operator==( const file_position_and_offset & rhs ) const + { + return( offset == rhs.offset + && line == rhs.line + && column == rhs.column + && file == rhs.file ); + } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates file_position_and_offset Stream output. */ + std::ostream & operator<<( std::ostream & str, const file_position_and_offset & obj ); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : position_policy + // + /** Specialization to handle file_position_and_offset. + * Track offset, line and column (tab character is not expanded). + */ + template <> + class position_policy + { + public: + void next_line( file_position_and_offset & pos ) + { + ++pos.offset; + ++pos.line; + pos.column = 1; + } + + //void set_tab_chars( unsigned /*chars*/ ) {} + + void next_char( file_position_and_offset & pos ) + { + ++pos.offset; + ++pos.column; + } + + void tabulation( file_position_and_offset & pos ) + { next_char( pos ); } + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace spirit + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace boost +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace spirit + { ///////////////////////////////////////////////////////////////// + + using namespace boost::spirit; + + //////////////////////////////////////////////////////////////////////////// + // + // Parsers + // + //////////////////////////////////////////////////////////////////////////// + + struct error_report_parser + { + error_report_parser( const char * msg_r ) + : msg( msg_r ) + {} + + typedef nil_t result_t; + + static std::ostream & errstream(); + + template + int operator()( const ScannerT & scan, result_t & /*result*/ ) const + { + errstream() << scan.first.get_position() << ' ' << msg << std::endl; + return -1; // Fail. + } + + const char * msg; + }; + + typedef functor_parser error_report_p; + + //////////////////////////////////////////////////////////////////////////// + // + // Phoenix actors + // + //////////////////////////////////////////////////////////////////////////// + + struct push_back_impl + { + template + struct result + { + typedef void type; + }; + + template + void operator()( Container & container, const Item & item ) const + { + container.push_back( item ); + } + }; + const phoenix::function push_back = push_back_impl(); + + struct ddump_impl + { + template + struct result + { + typedef void type; + }; + + template + void operator()( const C & item ) const + { + DBG << item << endl; + } + }; + const phoenix::function ddump = ddump_impl(); + + struct mdump_impl + { + template + struct result + { + typedef void type; + }; + + template + void operator()( const C & item ) const + { + MIL << item << endl; + } + }; + const phoenix::function mdump = mdump_impl(); + + ///////////////////////////////////////////////////////////////// + } // namespace spirit + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_SPIRIT_H diff --git a/zypp/parser/tagfile/.cvsignore b/zypp/parser/tagfile/.cvsignore new file mode 100644 index 0000000..5c94a2f --- /dev/null +++ b/zypp/parser/tagfile/.cvsignore @@ -0,0 +1,8 @@ +Makefile.in +Makefile +.deps +.libs +*.o +*.lo +*.a +*.la diff --git a/zypp/parser/tagfile/Makefile.am b/zypp/parser/tagfile/Makefile.am new file mode 100644 index 0000000..ba07894 --- /dev/null +++ b/zypp/parser/tagfile/Makefile.am @@ -0,0 +1,22 @@ +## Process this file with automake to produce Makefile.in +## ################################################## + +SUBDIRS = + +INCLUDES = + +## ################################################## + +include_HEADERS = \ + Tags.h + +noinst_LTLIBRARIES = lib@PACKAGE@_parser_tagfile.la + +## ################################################## + +lib@PACKAGE@_parser_tagfile_la_SOURCES = \ + Tags.cc + +lib@PACKAGE@_parser_tagfile_la_LIBADD = + +## ################################################## diff --git a/zypp/parser/tagfile/Tags.cc b/zypp/parser/tagfile/Tags.cc new file mode 100644 index 0000000..d700763 --- /dev/null +++ b/zypp/parser/tagfile/Tags.cc @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/tagfile/Tags.cc + * +*/ +#include +//#include "zypp/base/Logger.h" + +#include "zypp/parser/tagfile/Tags.h" + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace tagfile + { ///////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const Range & obj ) + { + return str << '[' << obj.start << ':' << obj.length << ']'; + } + + std::ostream & operator<<( std::ostream & str, const Tag & obj ) + { + return str << obj.range << '(' << obj.ident << '.' << obj.ext << ')'; + } + + std::ostream & operator<<( std::ostream & str, const STag & obj ) + { + return str << obj.stag << std::endl + << obj.data << '(' << obj.value << ')'; + } + + std::ostream & operator<<( std::ostream & str, const MTag & obj ) + { + return str << obj.stag << '-' << obj.etag << std::endl + << obj.data << '(' << obj.value.size() << ')'; + } + + ///////////////////////////////////////////////////////////////// + } // namespace tagfile + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/tagfile/Tags.h b/zypp/parser/tagfile/Tags.h new file mode 100644 index 0000000..ca6cb34 --- /dev/null +++ b/zypp/parser/tagfile/Tags.h @@ -0,0 +1,249 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/tagfile/Tags.h + * +*/ +#ifndef ZYPP_PARSER_TAGFILE_TAGS_H +#define ZYPP_PARSER_TAGFILE_TAGS_H + +#include +#include +#include + +#include "zypp/parser/Spirit.h" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace tagfile + { ///////////////////////////////////////////////////////////////// + + using namespace spirit; + using namespace phoenix; + + typedef char char_t; + typedef file_iterator fiterator_t; + typedef position_iterator iterator_t; + + //////////////////////////////////////////////////////////////////////////// + // + // Data types + // + //////////////////////////////////////////////////////////////////////////// + + struct Range + { + std::streamoff start; + unsigned length; + + Range() + : start( 0 ), length( 0 ) + {} + + Range( const iterator_t & first, const iterator_t & last ) + : start( first.get_position().offset ), length( last.get_position().offset - start ) + {} + }; + + /** \relates Range Stream output.*/ + std::ostream & operator<<( std::ostream & str, const Range & obj ); + + struct Tag + { + Range range; + std::string ident; + std::string ext; + }; + + /** \relates Tag Stream output.*/ + std::ostream & operator<<( std::ostream & str, const Tag & obj ); + + struct STag + { + Tag stag; + Range data; + std::string value; + }; + + /** \relates STag Stream output.*/ + std::ostream & operator<<( std::ostream & str, const STag & obj ); + + struct MTag + { + Tag stag; + Tag etag; + Range data; + std::list value; + }; + + /** \relates MTag Stream output.*/ + std::ostream & operator<<( std::ostream & str, const MTag & obj ); + + //////////////////////////////////////////////////////////////////////////// + // + // Closures + // + //////////////////////////////////////////////////////////////////////////// + + struct TagClosure : public spirit::closure + { + member1 val; + }; + typedef TagClosure::context_t TagVal; + + struct STagClosure : public spirit::closure + { + member1 val; + }; + typedef STagClosure::context_t STagVal; + + struct MTagClosure : public spirit::closure + { + member1 val; + member2 expect; + }; + typedef MTagClosure::context_t MTagVal; + + //////////////////////////////////////////////////////////////////////////// + // + // SingleTag Grammar + // + //////////////////////////////////////////////////////////////////////////// + + struct SingleTag : public grammar + { + template + struct definition + { + definition( const SingleTag & self ) + { + first = + ( + line + = stag [bind(&STag::stag)(self.val)=arg1] + >> *blank_p + >> (!data) [bind(&STag::data)(self.val)=construct_(arg1,arg2)] + [bind(&STag::value)(self.val)=construct_(arg1,arg2)] + >> *blank_p + >> (eol_p|end_p) + , + stag + = ( ch_p('=') + >> (+alpha_p) [bind(&Tag::ident)(stag.val)=construct_(arg1,arg2)] + >> !( '.' + >> (+alpha_p) [bind(&Tag::ext)(stag.val)=construct_(arg1,arg2)] + ) + >> ':' + ) [bind(&Tag::range)(stag.val)=construct_(arg1,arg2)] + , + data + = +~space_p + >> *( +blank_p + >> +~space_p + ) + ); + } + + subrule<0> line; + subrule<1,TagVal> stag; + subrule<2> data; + + rule first; + const rule & start() const + { return first; } + }; + }; + + //////////////////////////////////////////////////////////////////////////// + // + // MultiTag Grammar + // + //////////////////////////////////////////////////////////////////////////// + + struct MultiTag : public grammar + { + template + struct definition + { + definition( const MultiTag & self ) + { + first = + ( + line + = stag [bind(&MTag::stag)(self.val)=arg1] + >> *(anychar_p - eol_p) + >> eol_p + >> data [bind(&MTag::data)(self.val)=construct_(arg1,arg2)] + >> ( etag [bind(&MTag::etag)(self.val)=arg1] + | error_report_p( "Missing end tag" ) + ) + >> *(anychar_p - eol_p) + >> (eol_p|end_p) + , + stag + = ( ch_p('+') + >> ( (+alpha_p) [bind(&Tag::ident)(stag.val)=construct_(arg1,arg2)] + >> !( '.' + >> (+alpha_p) [bind(&Tag::ext)(stag.val)=construct_(arg1,arg2)] + ) + ) [self.expect=construct_(arg1,arg2)] + >> ':' + ) [bind(&Tag::range)(stag.val)=construct_(arg1,arg2)] + , + data + = while_p( ~eps_p(dataend) ) + [ + ( !( *blank_p >> +~space_p + >> *( +blank_p >> +~space_p ) + ) + ) [push_back(bind(&MTag::value)(self.val),construct_(arg1,arg2))] + >> *blank_p + >> eol_p + ] + , + dataend + = ( ch_p('-') | ch_p('+') ) + >> f_str_p(self.expect) + >> ':' + , + etag + = ( ch_p('-') + >> f_str_p(self.expect) + >> ':' + ) [bind(&Tag::range)(etag.val)=construct_(arg1,arg2)] + + ); + } + + subrule<0> line; + subrule<1,TagVal> stag; + subrule<2> data; + subrule<3> dataend; + subrule<4,TagVal> etag; + + rule first; + const rule & start() const + { return first; } + }; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace tagfile + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_TAGFILE_TAGS_H -- 2.7.4