如何使用斜杠在精神Lex模式

How to use a slash in Spirit Lex patterns?

本文关键字:Lex 模式 何使用      更新时间:2023-10-16

下面的代码使用

可以正常编译

clang++ -std=c++11 test.cpp -o test

但是当运行时抛出异常

的实例抛出后被调用"boost::词法分析程序::runtime_error"目前不支持what(): Lookahead('/')。

问题是输入和/或正则表达式(第12行和39行)中的斜杠(/),但我找不到解决方案如何正确地转义它。有提示吗?

#include <string>
#include <cstring>
#include <boost/spirit/include/lex.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace lex        = boost::spirit::lex;
namespace qi         = boost::spirit::qi;
namespace phoenix    = boost::phoenix;
std::string regex("FOO/BAR");
template <typename Type>
struct Lexer : boost::spirit::lex::lexer<Type> {
    Lexer() : foobar_(regex) {
        this->self.add(foobar_);
    }
    boost::spirit::lex::token_def<std::string> foobar_;
};
template <typename Iterator, typename Def>
struct Grammar
  : qi::grammar <Iterator, qi::in_state_skipper<Def> > {
    template <typename Lexer> Grammar(const Lexer & _lexer);
    typedef qi::in_state_skipper<Def> Skipper;
    qi::rule<Iterator, Skipper> rule_;
};
template <typename Iterator, typename Def>
template <typename Lexer>
Grammar<Iterator, Def>::Grammar(const Lexer & _lexer)
  : Grammar::base_type(rule_) {
    rule_ = _lexer.foobar_;
}
int main() {
    // INPUT
    char const * first("FOO/BAR");
    char const * last(first + strlen(first));
    // LEXER
    typedef lex::lexertl::token<const char *> Token;
    typedef lex::lexertl::lexer<Token> Type;
    Lexer<Type> l;
    // GRAMMAR
    typedef Lexer<Type>::iterator_type Iterator;
    typedef Lexer<Type>::lexer_def Def;
    Grammar<Iterator, Def> g(l);
    // PARSE
    bool ok = lex::tokenize_and_phrase_parse (
        first
      , last
      , l
      , g
      , qi::in_state("WS")[l.self]
    );
    // CHECK
    if (!ok || first != last) {
        std::cout << "Failed parsing input file" << std::endl;
        return 1;
    }
    return 0;
}

正如她所指出的那样,/很可能被用作前瞻性操作符,很可能采用flex的语法。不幸的是,Spirit没有使用更正常的向前看语法(并不是说我认为其他语法更优雅;它只会让人对regex语法的所有细微变化感到困惑)。

如果看re_tokeniser.hpp:

// Not an escape sequence and not inside a string, so
// check for meta characters.
switch (ch_)
{
    ...
    case '/':
        throw runtime_error("Lookahead ('/') is not supported yet.");
        break;
    ...
}

它认为你不在转义序列中,也不在字符串中,所以它检查元字符。/被认为是向前看的元字符(即使该功能没有实现),并且必须转义,尽管Boost文档根本没有提到这一点。

尝试用反斜杠(即"\/",如果使用原始字符串则为"/")转义/(不在输入中)。或者,其他人建议使用[/] .

我认为这是Spirit Lex文档中的一个错误,因为它没有指出/必须转义。


编辑:向sehe和cv_and_he致敬,他们帮助纠正了我之前的一些想法。如果他们在这里发布答案,一定要给他们一个+1。