2

qi::as_string[]どういうわけか、私はと仕事をすることができませんrepeat()[]

解析std::string str = { "{ +100S+++ ;\n }" };すると、次の出力が得られます

PLUS OR MINUS+
THREE PLUS OR MINUS
PARSED FINE
-------------------------
Parsing succeeded
-------------------------

これは、解析+がうまくいったことを示しています+++

three_plus_or_minus: 1 ~ 3 個のプラスまたはマイナスを連続して文字列としてキャプチャしようとしています。使用しない代替ソリューションas_string[]も高く評価されます。

リストが長くなって申し訳ありませんが、実際のコードではレクサーとパーサーの両方を使用する必要があります。

コード

// --------------  Third Party  --------------
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

// --------------  C++ stdlib   --------------
#include <iostream>
#include <fstream>
#include <string>

using namespace boost::spirit;
using boost::phoenix::val;

enum token_ids
{
    ID_CONSTANT = 1000,
        ID_INTEGER,
        ID_TAG,
    ID_IDENTIFIER
};

template <typename Lexer>
struct example6_tokens : lex::lexer<Lexer>
{
    example6_tokens()
    {
        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
        constant   = "[0-9]+";

        tag           = "sl|s|l|tl|SL|S|L|TSL|"    
                                    "z|r|i|Z|R|I|"              
                                    "<>|><|<<>>|>><<|><><|<><>";

        this->self = lex::token_def<>('(') | ')' | '{' | '}' 
            | '=' | ';' | ':' | '+' | '-';

        this->self.add
        (constant,        ID_CONSTANT       )
        (tag,             ID_TAG            )
        (identifier,      ID_IDENTIFIER     )
        ;

        this->self("WS")
            =   lex::token_def<>("[ \\t\\n]+")
                |   "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
                |   "\\/\\/[^\n]*"
                ;
    }
    lex::token_def<std::string>   identifier, tag;
    lex::token_def<unsigned int>  constant;
};

// ----------------------------------------------------------------------------
template <typename Iterator, typename Lexer>
struct example6_grammar
        : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
{
    template <typename TokenDef>
    example6_grammar(TokenDef const& tok)
        : example6_grammar::base_type(program)
    {
        using boost::spirit::_val;

        program
            =  +block
               ;

        block
            =   '{' >> *slsltl_stmt >> '}'
                ;

        plus_or_minus
                %=   ( qi::as_string[ qi::lit( '+' ) ] | qi::as_string[ '-' ])
                    [
                 std::cout << val("PLUS OR MINUS") << val( _1 ) << "\n"
                    ]
                        ;

        three_plus_or_minus
                %=   ( qi::as_string[ repeat(1,3)['+'] ] | qi::as_string[ repeat(1,3)['-'] ] )
                    [
                 std::cout << val("THREE PLUS OR MINUS") << val( _1 ) << "\n"
                    ]
                        ;

        slsltl_stmt
        =  (  - plus_or_minus
                    >> token(ID_CONSTANT) 
                    >> token(ID_TAG)
                    >> three_plus_or_minus
                    >> ';'
                )
                        [
                    std::cout << val("PARSED FINE") << "\n"
                        ]
                ;

        expression
            =   tok.identifier [ _val = _1 ]
                |   tok.constant   [ _val = _1 ]
                ;
    }

    typedef boost::variant<unsigned int, std::string> expression_type;

    qi::rule<Iterator, qi::in_state_skipper<Lexer> > program, block;
    qi::rule<Iterator, std::string(), qi::in_state_skipper<Lexer> > 
        plus_or_minus, three_plus_or_minus;
    qi::rule<Iterator, std::string(), qi::in_state_skipper<Lexer> > slsltl_stmt;
    qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> >  expression;
};

int
main( int argv, char* argc[] )
{
    typedef std::string::iterator base_iterator_type;
    typedef lex::lexertl::token<
    base_iterator_type, boost::mpl::vector<unsigned int, std::string>
    > token_type;

    typedef lex::lexertl::lexer<token_type> lexer_type;
    typedef example6_tokens<lexer_type> example6_tokens;
    typedef example6_tokens::iterator_type iterator_type;
    typedef example6_grammar<iterator_type, example6_tokens::lexer_def> example6_grammar;

    example6_tokens tokens;                         // Our lexer
    example6_grammar calc(tokens);                  // Our parser
    std::string str = { "{ +100S+++ ;\n }" };

    std::string::iterator it = str.begin();
    iterator_type iter = tokens.begin(it, str.end());
    iterator_type end = tokens.end();

    std::string ws("WS");
    bool r = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self]);
    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }
}
4

1 に答える 1

2

試す

    slsltl_stmt %=  /*....*/;

の代わりにslsltl_stmt =。セマンティック アクションを使用すると、属性の自動伝播が無効になります。

(私はあなたのコードの残りの部分をまだ見ていません。これ/他のものを適応させる必要がある場所がもっとあるかもしれません)


編集

私はさらにいくつかのテストを行いましたが、これはあなたが期待したとおりになると思います:

three_plus_or_minus
        =   (qi::as_string[ repeat(1,3)[qi::char_('+')] | repeat(1,3)[qi::char_('-')] ])
            [ std::cout << val("THREE PLUS OR MINUS") << _1 << "\n" ]
                ;

すぐに使える質問ですが、なぜレクサーを使用しているのですか? のトークンを持つことは理にかなっている+++でしょうか?

于 2012-12-29T19:06:50.527 に答える