【问题标题】:How to use a slash in Spirit Lex patterns?如何在 Spirit Lex 模式中使用斜线?
【发布时间】:2015-07-14 13:47:27
【问题描述】:

下面的代码可以正常编译

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

但是运行的时候会抛出异常

在抛出一个实例后调用终止 'boost::lexer::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;
}

【问题讨论】:

  • 我想说简化一下,这样它就可以在没有/ 的情况下工作(即让它只读取和解析FOOBAR)。然后,一旦您开始工作,请尝试重新添加 /

标签: c++ boost boost-spirit boost-spirit-lex


【解决方案1】:

作为sehe points out/ 可能旨在用作前瞻运算符,可能会在the syntax of flex 之后使用。不幸的是,Spirit 不会使用更多的normal lookahead syntax(并不是说我认为其他语法更优雅;它只是与正则表达式语法中的所有细微变化混淆)。

如果你看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;
    ...
}

它认为您不在转义序列中,也不在字符串中,因此它正在检查元字符。 / 被认为是前瞻的元字符(即使该功能未实现),并且必须转义,despite the Boost docs not mentioning that at all

尝试使用反斜杠(即"\\/",或"\/",如果使用原始字符串)转义/(不在输入中)。或者,others have suggested using [/]

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


编辑: 感谢sehecv_and_he,他们帮助纠正了我之前的一些想法。如果他们在此处发布答案,请务必给他们 +1。

【讨论】:

  • 我尝试使用“\\/”、“\/”和“[]”来转义斜线。没有解决办法。
  • 不过,它失败并出现不同的错误。 (特别是:Assertion failed: (std::size_t(~0) != state), function set_lexer_state, file /usr/local/include/boost/spirit/home/lex/qi/state_switcher.hpp, line 87.)。我不太了解 Spirit,但听起来您的词法分析器/解析器中还有另一个问题。这个答案对于解决斜线问题应该是正确的。对于另一个问题......我不知道该说什么。
  • 这不是有序的选择。也提到 PEG 规范符号是一个红鲱鱼,因为我们在这里没有指定语法。我们正在指定令牌模式。他们使用正则表达式的一个子集:boost.org/doc/libs/1_58_0/libs/spirit/doc/html/spirit/lex/…(顺便提一下,这就是错误消息的建议)
  • @Cornstalks 新错误是由于“WS”状态不存在并且船长尝试使用它。 This example 尝试添加所述状态并且似乎有效。
  • @sehe 我也不知道,但有点谷歌搜索让我认为错误是指 Spirit.Lex 不支持 this feature 的 flex。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多