标签: boost-spirit

提升精神2.x:如何处理关键字和标识符?

美好的一天.

我过去一直在使用提升精神经典,现在我正在努力坚持更新的,提升精神2.x. 有人可以如此友善地指出我如何处理关键字?比如,我想区分"foo"和"int",其中"foo"是标识符,"int"只是一个关键字.我想保护我的语法免于错误的解析,比如"intfoo".

好的,我有

struct my_keywords : boost::spirit::qi::symbols<char, std::string> {
                my_keywords() {
                    add
                    ("void")
                    ("string")
                    ("float")
                    ("int")
                    ("bool")
                    //TODO: add others
                    ;
                }
            } keywords_table_;
Run Code Online (Sandbox Code Playgroud)

并且标识规则声明为:

boost::spirit::qi::rule<Iterator, std::string(),  ascii::space_type> ident;
ident = raw[lexeme[((alpha | char_('_')) >> *(alnum | char_('_'))) - keywords_table_]];
Run Code Online (Sandbox Code Playgroud)

并且,比方说,一些规则:

boost::spirit::qi::rule<Iterator, ident_decl_node(),  ascii::space_type> ident_decl;
ident_decl = ("void" | "float" | "string" | "bool") >> ident;
Run Code Online (Sandbox Code Playgroud)

如何正确地写它,说"void","float"等是关键字?提前致谢.

c++ boost-spirit

3
推荐指数
1
解决办法
2785
查看次数

在使用boost :: spirit进行解析时,我如何假设"默认值"?

假设我的语法定义为:

some_rule := a b [c [d]]
Run Code Online (Sandbox Code Playgroud)

where c,and d是可选的,如果没有给出,则默认为某个值(假设为14).如果没有给出值,我可以将其默认为14吗?我希望生产std::vector的产品总是4号.

我最接近的是如下:

qi::rule<Iterator, std::vector<int>(), ascii::space_type> some_rule;
some_rule %= int_ >> int_ >> -int_ >> -int_;

// ...

some_other_rule = some_rule[&some_callback_for_int_vectors];
Run Code Online (Sandbox Code Playgroud)

然后,对于未显示的可选值,我将获得0(我相信).然后我将最后的连续0改为14.这不仅错误,而且也不优雅.有一个更好的方法吗?

c++ boost-spirit

3
推荐指数
1
解决办法
474
查看次数

有没有办法将spirit :: lex字符串标记的内容与spirit :: qi语法中的文字进行匹配

我正在编写DSL并使用Boost Spirit词法分析器来标记我的输入.在我的语法中,我想要一个类似于此的规则(tok词法分析器在哪里):

header_block =
    tok.name >> ':' >> tok.stringval > ';' >>
    tok.description >> ':' >> tok.stringval > ';'
  ;
Run Code Online (Sandbox Code Playgroud)

而不是为语言指定保留字(例如"name","description")并处理词法分析器和语法之间的同步,我想只是将匹配的所有内容标记[a-zA-Z_]\w*为单个标记类型(例如tok.symbol),并让语法梳理出来.如果我没有使用词法分析器,我可能会这样做:

stringval = lexeme['"' >> *(char_ - '"') >> '"'];
header_block =
    lit("name") >> ':' >> stringval > ';' >>
    lit("description") >> ':' >> stringval > ';'
  ;
Run Code Online (Sandbox Code Playgroud)

使用词法分析器,我可以编译以下规则,但当然它匹配的比我想要的多 - 它不关心特定的符号值"name"和"description":

header_block =
    tok.symbol >> ':' >> tok.stringval > ';' >>
    tok.symbol >> ':' >> tok.stringval > ';'
  ;
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是这样的:

header_block = …
Run Code Online (Sandbox Code Playgroud)

c++ dsl boost-spirit boost-spirit-qi boost-spirit-lex

3
推荐指数
1
解决办法
529
查看次数

如何结合boost :: spirit :: lex和boost :: spirit :: qi?

我有一个词法分析器,基于该词法分析器,我现在想要创建一个使用此词法分析器生成的标记的语法.我尝试调整一些我发现的例子,现在我有一些编译和工作至少一点点的东西,但我的一个应该失败的测试不会.现在我想知道为什么,我也想知道我在那里做了什么(我想要理解 - 我只是从一些例子中复制了一些代码,但这并没有真正提高理解力).

词法:

#include <boost/spirit/include/lex_lexertl.hpp>

namespace lex = boost::spirit::lex;

enum LexerIDs { ID_IDENTIFIER, ID_WHITESPACE, ID_INTEGER, ID_FLOAT, ID_PUNCTUATOR };

template <typename Lexer>
struct custom_lexer : lex::lexer<Lexer>
{
    custom_lexer()
        : identifier("[a-zA-Z_][a-zA-Z0-9_]*")
        , white_space("[ \\t\\n]+")
        , integer_value("[1-9][0-9]*")
        , hex_value("0[xX][0-9a-fA-F]+")
        , float_value("[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?")
        , float_value2("[0-9]+\\.([eE][+-]?[0-9]+)?")
        , punctuator("\\[|\\]|\\(|\\)|\\.|&>|\\*\\*|\\*|\\+|-|~|!|\\/|%|<<|>>|<|>|<=|>=|==|!=|\\^|&|\\||\\^\\^|&&|\\|\\||\\?|:|,")// [ ] ( ) . &> ** * + - ~ ! / % << >> < > <= >= == != ^ & | ^^ && || ? : ,
    {
        using boost::spirit::lex::_start;
        using boost::spirit::lex::_end;

        this->self.add …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-qi boost-spirit-lex

3
推荐指数
1
解决办法
1993
查看次数

新标准的功能是否会对C++ 11中的boost库实现产生重大影响?

新标准的功能是否会对C++ 11中boost库实现产生重大影响?

鉴于存在可变参数模板,特别感兴趣的是boost::variant(BOOST_VARIANT_LIMIT_TYPES)和boost::spirit部分库.

有关于此的好文章吗?

c++ boost boost-spirit boost-variant c++11

3
推荐指数
1
解决办法
590
查看次数

boost :: spirit可选解析为融合自适应结构

如果有结构

struct price
{
   int chicken;
   int cow;
   bool in_stock;
   std::string place;
};
Run Code Online (Sandbox Code Playgroud)

使用boost :: fusion进行调整.如果需要解析它,但可选择用于in_stock和place.例如

template <typename it, typename skipper = qi::space_type>
struct p : qi::grammar<it, price(), skipper>
{
    p() : p::base_type(p_instance)
    {
        using namespace qi;
        psr %= int_ > int_ > -bool_ > -('"' > char_ % ',' > '"');
    }
  private:
      qi::rule<it,price(),skipper> limit;
};
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用.如果输入是,则抛出异常"2 3 \"Chili\"".什么是解决方案?

c++ boost-spirit

3
推荐指数
1
解决办法
1347
查看次数

在Qi中使用Boost Phoenix引用语法中的上一个匹配项

我是Boost Spirit的新手。理想情况下,我想使用Phoenix来确保语法中的两个值相同。我想要工作的简明版本是两个整数相等的元组。

我想解析一个字符串“ 14,14,test”,但由于“ 14,12,test”失败,因为14不等于12。我想打印以下代码:

Good: (14 14 test)
Fail
Run Code Online (Sandbox Code Playgroud)

目前,由于我允许qi :: int_解析第二个值而没有任何检查,因此两个输入都将通过。

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/include/qi_matches.hpp>

#include <string>
#include <vector>
#include <algorithm>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;


int main(){


    std::vector<std::string> test_inputs = {"14,14,test","14,12,test"};

    std::for_each(test_inputs.begin(),test_inputs.end(),[](const std::string& input){
        boost::fusion::vector<int,int,std::string> result;
        int i(0);

        auto res = qi::parse(input.begin(),input.end(),
            //works but also parses "14,12,test"
            qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_ >> qi::lit(",") >> +qi::char_,
            //Fails to compile
            //qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::val(i)) …
Run Code Online (Sandbox Code Playgroud)

c++ boost boost-spirit boost-spirit-qi c++11

3
推荐指数
1
解决办法
636
查看次数

语法平衡问题

是否有可能强制Boost.Spirit Qi以这种方式运行,生成的语法可以根据一些运行时可计算的条件/规则/速率进行调整?例如,输入由语言构造组成,这些构造在解析期间导致不同的替代方案,一些更频繁,另一些 - 更少.但是替代方案的顺序会影响效率,即语法的运行时最优性.在某些情况下,不可能事先确定在任意输入(可能强烈聚集)的情况下将更频繁地选择哪种替代方案.

我知道可以qi::symbols在运行时附加符号,但对于其他一些解析器来说,类似的行为是可取的.

c++ boost-spirit boost-spirit-qi tree-balancing

3
推荐指数
1
解决办法
123
查看次数

使用boost spirit X3高效地解析普通文件

我是C++和Boost Spirit X3的新手.对于我的项目,我将两个文件中的地理社交图解析为具有以下结构,其中boost boost X3为boost图.

我有一个有效的实施.由于我之前没有任何图书馆的经验,我想知道你对这种方法的看法,以及你是否建议采取不同的方法.

在图形文件中,每条边有一条线.解析边缘时,我必须创建图形的节点,以防以前没有看到节点.我使用语义操作,每次遇到node-id时都会检查该节点是否已经在图中.阅读完一行后,我使用语义动作然后添加边缘.

在位置文件中,在给定时间每个节点的已知位置有一行.我存储了图中节点已知的第一个位置(使用自定义boost图属性).

我必须提出具体问题,但很乐意接受任何想法和建议:

  • 是否可以像使用图形文件一样使用嵌套语义操作?这会伤害性能吗?
  • 是否建议使用Spirit X3一次解析整个文件,还是应该使用Spirit X3单独解析每一行?

图表(表示图中的边)

[user1]     [user2]
0           3
Run Code Online (Sandbox Code Playgroud)

地点

[user]  [check-in time]         [latitude]      [longitude]     [location id]
0       2010-10-19T23:55:27Z    30.2359091167   -97.7951395833      22847
Run Code Online (Sandbox Code Playgroud)

Spirit X3解析代码

// Parse the gowalla edge file
boost::spirit::istream_iterator file_iterator(edge_file), eof;

x3::phrase_parse(file_iterator, eof,
        // Begin grammar
        (
         *((x3::int_[add_vertex] >> x3::int_[add_vertex])[add_edge])
        ),
        // End grammar
        x3::space
        );

// Fail if we couldn't parse the whole edges file
if (file_iterator != eof) {
    std::cerr << "Couldn't parse whole edges file" << …
Run Code Online (Sandbox Code Playgroud)

c++ boost-spirit boost-graph boost-spirit-x3

3
推荐指数
1
解决办法
899
查看次数

使用boost spirit x3在单独的解析器中链接错误

我是currentyl试图将我的提升精神x3解析器分成不同的_def和.cpp文件使用BOOST_SPIRIT_DEFINE/DECLARE/INSTANTIATE,但我不断收到链接错误. 这里是我的解析器分离.

链接器错误读取

<artificial>:(.text.startup+0xbb): undefined reference to `bool kyle::parser::impl::parse_rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type>, boost::spirit::x3::unused_type const>(boost::spirit::x3::rule<kyle::parser::impl::identifier_class, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, false>, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> const&, boost::spirit::x3::unused_type const&)'
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我怎样才能让我的例子有效?

  • config.hpp:

    #include <boost/spirit/home/x3.hpp>
    
    namespace kyle{
    namespace parser{
    
    namespace x3 = boost::spirit::x3;
    
    typedef std::string::const_iterator iterator_type;
    typedef x3::phrase_parse_context<x3::ascii::space_type>::type context_type;
    
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • literals.cpp:

    #include "literals_def.hpp"
    #include "config.hpp"
    #include <boost/spirit/home/x3.hpp>
    
    
    namespace kyle { …
    Run Code Online (Sandbox Code Playgroud)

c++ linker-errors boost-spirit boost-spirit-x3

3
推荐指数
2
解决办法
523
查看次数