0

How I can check in next code that value of last tok.identifier is '='-character?

parameter = (
                    tok.identifier
                    >> ((lit(":")
                    >> tok.identifier) |
                    (tok.identifier >> statement))
                    );

EDIT. I declare identifier lex::token_def<std::string> identifier;

Viola
  • 23
  • 7
  • in what universe does `identifier` match `=`?. Also, include the token definitions (in your SSCCE) if you want help. Are you using an `actor_lexer`? Are you using `token_def`? Are you adding the `T`s to the `mpl::vector` in the lexer declaration? – sehe Mar 12 '16 at 20:32
  • I use `token_def` and, I use lexer with parser `lex::tokenize_and_parse`. That code in ask is from parser/grammar. – Viola Mar 13 '16 at 07:27
  • 1
    I know it's from the rule definition. But you don't show any of the relevant types. Sorry, but that means we can't help (except making up the whole code ourselves, and (a) I have better things to do with my time (b) that would just risk answering with irrelevant code) – sehe Mar 13 '16 at 11:56

1 Answers1

0

The correspondent concept in boost::spirit::qi is described by qi::lit. You have to create a qi::lit for your tokens. Here is an example:

template <typename TokenAttr>
struct LiteralToken : qi::primitive_parser<LiteralToken<TokenAttr>>
{
    LiteralToken(const lex::token_def<TokenAttr> &tok, const TokenAttr &value)
      : id(tok.id())
      , value(value)
    {}

    template <typename Context, typename Iterator>
    struct attribute
    {
        typedef unused_type type;
    };

    template <typename Iterator, typename Context, typename Skipper, typename Attribute>
    bool parse(Iterator& first, Iterator const& last, Context& context, Skipper const& skipper, Attribute& attr_) const
    {
        typedef typename Iterator::token_type::token_value_type token_value_type;
        typedef typename Iterator::base_iterator_type base_iterator_type;

        base_iterator_type it;

        qi::skip_over(first, last, skipper);
        if (first != last && id == first->id())
        {
            auto v = boost::get<boost::iterator_range<base_iterator_type>>(first->value());
            if (v == value)
            {
                traits::assign_to(*first, attr_);
                ++first;
                return true;
            }
        }
        return false;
    }

    typename lex::token_def<TokenAttr>::id_type id;
    TokenAttr                                   value;
};

namespace boost
{
    namespace spirit
    {
        template <typename A0, typename A1>
        struct use_terminal<
            qi::domain
          , terminal_ex<tag::lit, fusion::vector2<A0, A1>>
          , typename enable_if<boost::is_same<A0, lex::token_def<std::string>>>::type
          > : mpl::true_
        {};

        namespace qi
        {
            template <typename Modifiers, typename A0, typename A1>
            struct make_primitive<
                terminal_ex<tag::lit, fusion::vector2<A0, A1> >
              , Modifiers
              , typename enable_if<boost::is_same<A0, lex::token_def<std::string>>>::type
              >
            {
                typedef LiteralToken<std::string> result_type;

                template <typename Terminal>
                result_type operator()(Terminal const& term, unused_type) const
                {
                    return result_type(fusion::at_c<0>(term.args), fusion::at_c<1>(term.args));
                }
            };
        }
    }
}

Then you can write

parameter = (
                    lit(tok.identifier, "=")
                    >> ((lit(":")
                    >> tok.identifier) |
                    (tok.identifier >> statement))
                    );
facetus
  • 1,091
  • 6
  • 20
  • I just checked boost 1.65.1. qi::lit is defined for char, string, bool, integers and real numbers. It is not defined for lex::token_def. – facetus Sep 21 '17 at 22:36
  • I never said it's called `lit`. It's not. I think it was `id_token(id)` or `token_id(id)` or something (maybe even `any_token(id)` or just `qi::token(id)`). I'll look for it later – sehe Sep 21 '17 at 22:37
  • Ok. I checked all terminals defined in the lexer. I found these: in_state, plain_raw_token, plain_token, plain_token_range, plain_tokenid, plain_tokenid_range, plain_tokenid_mask, state_switcher, and state_switcher_context. None of them checks the literal value of a token. – facetus Sep 21 '17 at 23:08
  • Do you happen to have a self-contained sample using your code? I will try to look at this tomorrow. – sehe Sep 21 '17 at 23:10
  • I don't. I have it in my project and it is working. I cannot share the project. Just copy&paste what I posted and try to use a rule that looks like `r = qi::lit(tok.identifier, ''match-this-literally")`. In my case it was useful in parsing dot language (http://www.graphviz.org/content/dot-language). Check compass_pt rule. It has these n, ne, e, se..., which are not keywords. It was easier not to define dedicated entities in the lexer for them. – facetus Sep 21 '17 at 23:21
  • I'm not really in the mood to invent a lexer for the purpose. I'm not a fan of spirit::lex. I might find one of my own answers with a sample though :) – sehe Sep 21 '17 at 23:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155088/discussion-between-sehe-and-noxmetus). – sehe Sep 22 '17 at 13:08