0

I wonder if it is possible to change the parser at runtime given it does not change the compound attribute.

Lets say I want to be able to modify at runtime the character of my parser that detects whether I have to join a line from ; to ~. Both are just characters and since the c++ types and the template instantiations dont vary (in both cases we are talking about a char) I think there must be some way, but I dont find it. So is this possible?

My concrete situation is that I am calling the X3 parser via C++/CLI and have the need that the character shall be adjustable from .NET. I hope the following example is enough to be able to understand my problem.

http://coliru.stacked-crooked.com/a/1cc2f2836dbfaa46

Kind regards

codingdave
  • 1,207
  • 16
  • 23

1 Answers1

1

You cannot change the parser at runtime (except a DSO trick I described under your other question https://stackoverflow.com/a/56135824/3621421), but you can make your parser context-sensitive via semantic actions and/or stateful parsers (like x3::symbols).

The state for semantic actions (or probably for your custom parser) can also be stored in a parser context. However, usually I see that folks use global or function local variables for this purpose.

A simple example:

#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

int main()
{
    char const* s = "sep=,\n1,2,3", * e = s + std::strlen(s);
    auto p = "sep=" >> x3::with<struct sep_tag, char>('\0')[
         x3::char_[([](auto& ctx) { x3::get<struct sep_tag>(ctx) = _attr(ctx); })] >> x3::eol
      >> x3::int_ % x3::char_[([](auto& ctx) { _pass(ctx) = x3::get<struct sep_tag>(ctx) == _attr(ctx); })]
    ];
    if (parse(s, e, p) && s == e)
        std::cout << "OK\n";
    else
        std::cout << "Failed\n";
}
Nikita Kniazev
  • 3,728
  • 2
  • 16
  • 30
  • Thank you for this answer. You mention x3::symbols but unfortunately dont show an example how to use it. It took me some time to understand what the sample does, very impressive. I dont need to tackle such a difficult situation. The only thing I need is to be able to modify or substitute a symbols parser which only constitutes a part of a line. So `line_parser = char_+|parser_foo|symbols_parser;` and I only get the keywords of symbols_parser with the constructor of my parser. – codingdave May 15 '19 at 21:39