美好的一天.
我过去一直在使用提升精神经典,现在我正在努力坚持更新的,提升精神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"等是关键字?提前致谢.
假设我的语法定义为:
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.这不仅错误,而且也不优雅.有一个更好的方法吗?
我正在编写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) 我有一个词法分析器,基于该词法分析器,我现在想要创建一个使用此词法分析器生成的标记的语法.我尝试调整一些我发现的例子,现在我有一些编译和工作至少一点点的东西,但我的一个应该失败的测试不会.现在我想知道为什么,我也想知道我在那里做了什么(我想要理解 - 我只是从一些例子中复制了一些代码,但这并没有真正提高理解力).
词法:
#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++ 11中的boost库实现产生重大影响?
鉴于存在可变参数模板,特别感兴趣的是boost::variant(BOOST_VARIANT_LIMIT_TYPES)和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\"".什么是解决方案?
我是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) 是否有可能强制Boost.Spirit Qi以这种方式运行,生成的语法可以根据一些运行时可计算的条件/规则/速率进行调整?例如,输入由语言构造组成,这些构造在解析期间导致不同的替代方案,一些更频繁,另一些 - 更少.但是替代方案的顺序会影响效率,即语法的运行时最优性.在某些情况下,不可能事先确定在任意输入(可能强烈聚集)的情况下将更频繁地选择哪种替代方案.
我知道可以qi::symbols在运行时附加符号,但对于其他一些解析器来说,类似的行为是可取的.
我是C++和Boost Spirit X3的新手.对于我的项目,我将两个文件中的地理社交图解析为具有以下结构,其中boost boost X3为boost图.
我有一个有效的实施.由于我之前没有任何图书馆的经验,我想知道你对这种方法的看法,以及你是否建议采取不同的方法.
在图形文件中,每条边有一条线.解析边缘时,我必须创建图形的节点,以防以前没有看到节点.我使用语义操作,每次遇到node-id时都会检查该节点是否已经在图中.阅读完一行后,我使用语义动作然后添加边缘.
在位置文件中,在给定时间每个节点的已知位置有一行.我存储了图中节点已知的第一个位置(使用自定义boost图属性).
我必须提出具体问题,但很乐意接受任何想法和建议:
图表(表示图中的边)
[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) 我是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)