Boost logo

Boost Users :

From: ope (ope-devel_at_[hidden])
Date: 2008-02-19 13:44:41


Hi,

my first parser and problems :-) Well, obviously I didn't understood the
translation of BNF in spirit (probably BNF also); attached the code.

The result is:

$ g++ spirit.cpp -o spirit && ./spirit
[Date] =
"[Data Ver] 3.4 "
^-- error ("D")
[Data Ver] = 0
"[File Name] foo.csv"
^-- error ("F")
[File Name] =
[Notes] = y

Can anybody help? Further more I need to replace the comment symbol rule
dynamically ("[Comment Char]") for the data self (not displayed here).

Thanks,
Olaf

---8<---
#include <boost/spirit/core.hpp>
#include <boost/spirit/symbols/symbols.hpp>
#include <boost/spirit/utility/chset.hpp>
#include <boost/spirit/utility/escape_char.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <boost/spirit/actor.hpp>

#include <iostream>
#include <iomanip>

namespace sp = ::boost::spirit;

struct data {
     std::pair<int, int> data_ver; // major,minor
     std::string comment_char;
     std::string file_name;
     std::string file_rev;
     std::string date;
     std::string notes;
};

struct grammar
     : public sp::grammar<grammar>
{
     explicit grammar( data& data )
         : m_data( data )
     { }

     template <typename ScannerT>
     struct definition
     {
         definition( const grammar& self )
         {
             typedef sp::chset<char> chset_t;

             using sp::comment_p;
             using sp::int_p;
             using sp::anychar_p;
             using sp::blank_p;

             using sp::lexeme_d;
             using sp::as_lower_d;

             using sp::assign_a;

             using sp::strlit;

             data& data = self.m_data;

             chset_t COMMENT_SYMBOL_CHSET( "!\"#$%&'()*,:;<>?@\\^`{|}~" );
             chset_t FILE_NAME_CHSET(
"abcdefghijklmnopqrstuvwxyz0123456789_^$~!#%&-{})(@'`" );

             std::pair<int, int> v( 0, 0 );

             document
                 = comment
                 | data_ver
                 | comment_char
                 | file_name
                 | file_rev
                 | date
                 | notes
                 ;

             comment
                 = comment_p('|')
                 ;

             data_ver
                 =
                 ( lexeme_d[strlit<>("[Data Ver]")]
>> int_p[assign_a(v.first)]
>> '.'
>> int_p[assign_a(v.second)]
                     )[assign_a( data.data_ver, v )]
                 ;

             comment_char
                 = lexeme_d[strlit<>("[Comment Char]")]
                 // FixMe: dynamic rule for comment !!!
>> COMMENT_SYMBOL_CHSET[assign_a( data.comment_char )]
>> "_char"
                 ;

             file_name
                 =
                 ( lexeme_d[strlit<>("[File Name]")]
>> ( +FILE_NAME_CHSET
>> "."
>> (
                              as_lower_d[".csv"]
                            | as_lower_d[".txt"]
                           )
                      )
                 )[assign_a( data.file_name )]
                 ;

             file_rev
                 = lexeme_d[strlit<>("[File Rev]")]
>> (
                     // treated as string
                     +anychar_p
                     )[assign_a( data.file_rev )]
                 ;

             date
                 = "[Date]"
>> (
                     // treated as string
                     +anychar_p[assign_a( data.date )]
                     )
                 ;

             notes
                 = "[Notes]"
>> (
                     // treated as string
                     +anychar_p[assign_a( data.notes )]
                     )
                 ;
         }

         sp::rule<ScannerT> const& start() const { return document; }

         sp::rule<ScannerT> document, comment,
             data_ver,
             comment_char,
             file_name,
             file_rev,
             date,
             notes
             ;
     };

private:
     data& m_data;
};

template <typename GrammarT>
static void
parse(GrammarT const& grammar, std::string expr)
{
     std::string::iterator first = expr.begin();

     sp::parse_info<std::string::iterator> result
         = sp::parse(first, expr.end(), grammar);

     if ( !result.hit ) {
         std::cerr << "\"" << expr << "\""
                   << std::endl;
         std::cerr << std::setw(result.stop - expr.begin() + 1)
                   << "^-- error ("
                   << "\"" << *result.stop << "\")"
                   << std::endl;
     }
     else if ( !result.full ) {
         first = result.stop;
     }
}

int main()
{
     data d;
     grammar g( d );

     parse( g, "[Date] 19.03.2008 | yeah " );
     std::cout << "[Date] = " << d.date << std::endl;

     parse( g, "[Data Ver] 3.4 " );
     std::cout << "[Data Ver] = " << d.data_ver.first << std::endl;

     parse( g, "[File Name] foo.csv" );
     std::cout << "[File Name] = " << d.file_name << std::endl;

     parse( g, "[Notes] Use this section for any special notes
related to the file."
               " This information is for modeling
purposes only, and is not"
               " guaranteed. | May
vary");
     std::cout << "[Notes] = " << d.notes << std::endl;
}

--->8---


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net