我希望在语义动作代码发现问题时停止令牌解析器.
如果x> 10
在语法上是正确的,但如果x不存在,解析器应该停止
语法规则和语义动作看起来像这样
condition
= ( tok.identifier >> tok.oper_ >> tok.value )
[
boost::phoenix::bind( &cRuleKit::AddCondition, &myRulekit,
boost::spirit::_1, boost::spirit::_2, boost::spirit::_3 )
]
;
Run Code Online (Sandbox Code Playgroud)
所以现在我添加一个检查标识符的存在
condition
= ( tok.identifier[boost::bind(&cRuleKit::CheckIdentifier, &myRulekit, ::_1, ::_3 ) ]
>> tok.oper_ >> tok.value )
[
boost::phoenix::bind( &cRuleKit::AddCondition, &myRulekit,
boost::spirit::_1, boost::spirit::_2, boost::spirit::_3 )
]
;
Run Code Online (Sandbox Code Playgroud)
这有效!
我并不为优雅而激动.语法语法现在很难阅读,混合使用boost :: bind和boost :: phoenix :: bind非常令人困惑.
我怎样才能改进它?我想从phoenix :: bind获取'hit'参数,以便我可以在cRuleKit :: AddCondition()中进行检查,因此保持语法和动作分离并避免使用boost :: bind.
答案是使用占位符_pass
condition
= ( tok.identifier >> tok.oper_ >> tok.value )
[
boost::phoenix::bind( &cRuleKit::AddCondition, &myRulekit,
boost::spirit::_pass, boost::spirit::_1, …
Run Code Online (Sandbox Code Playgroud) 我试图简单地在这个答案中找到精神解析器:
删除xor
运算符和逻辑。我看不到怎么做,我尝试使用
expr_ = or_.alias();
or_ = (and__ >> "or" >> or_ )[ _val = phx::construct<binop<op_or >>(_1, _2) ] | and_ [ _val = _1 ];
and_ = (not_ >> "and" >> and_) [ _val = phx::construct<binop<op_and>>(_1, _2) ] | not_ [ _val = _1 ];
not_ = ("not" > simple ) [ _val = phx::construct<unop <op_not>>(_1) ] | simple [ _val = _1 ];
Run Code Online (Sandbox Code Playgroud)
对于规则定义,但我收到一条我不明白的神秘编译器消息:
test\test.cpp `boost::spirit::_2' cannot appear in a constant-expression
Run Code Online (Sandbox Code Playgroud)
如果有人能阐明一些观点,我将不胜感激。
这是日志:
compiler: …
Run Code Online (Sandbox Code Playgroud) 我有以下代码我需要解析一个字符串并将其移动到如下定义的结构:
#include "boost\spirit\include\classic.hpp"
#include "boost\spirit\include\qi.hpp"
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <regex>
#include <string>
#include <boost\chrono.hpp>
#include <ctype.h>
#include <iostream>
struct my_struct
{
std::string s1;
std::string s2;
std::string s3;
std::string s4;
std::string s5;
std::string s6;
std::string s7;
std::string s8;
std::string s9;
std::string s10;
std::string s11;
};
BOOST_FUSION_ADAPT_STRUCT(
my_struct,
(std::string, s1 )
(std::string, s2 )
(std::string, s3 )
(std::string, s4 )
(std::string, s5 )
(std::string, s6 )
(std::string, …
Run Code Online (Sandbox Code Playgroud) boost boost-spirit boost-fusion string-parsing boost-spirit-qi
我有以下解析规则:
filter = (input >> (qi::repeat(0,2)[char_(';') >> input]))
Run Code Online (Sandbox Code Playgroud)
input
是一个规则,返回一个std::vector<int>
我将vec
简称为的向量.
问题是:filter
规则返回什么复合属性?
我试过了:
fusion::vector <vec,std::vector <fusion::vector <char,vec> > >
Run Code Online (Sandbox Code Playgroud)
但它失败了,我不知道为什么.
我如何在 boost 精神解析器中添加警告。
编辑: ...可以报告位置问题
例如,如果我有一个整数解析器:
('0' >> oct)
| int_
Run Code Online (Sandbox Code Playgroud)
我希望能够做这样的事情:
('0' >> oct)
| "-0" --> trigger warning("negative octal values are not supported, it will be interpreted as negative decimal value and the leading 0 will be ignored")
| int_
Run Code Online (Sandbox Code Playgroud) 我想跟踪unicode字符串的输入位置和输入行.
对于位置,我存储一个迭代器,以便std::distance
在所需的位置开始和使用.只要输入不是unicode,这就可以正常工作.使用unicode符号,位置会移动,即ä
在输入流中占用两个空格,并且位置关闭1.因此,我切换到了boost::u8_to_u32_iterator
,这样可以正常工作.
对于我使用的线boost::spirit::line_pos_iterator
也很好用.
我的问题是将两个概念结合起来使用行迭代器和unicode迭代器.允许在unicode字符串上使用pos和line的另一种解决方案当然也是受欢迎的.
这是unicode解析器的一个小例子; 如上所述我想另外包装迭代器,boost::spirit::line_pos_iterator
但甚至不编译.
#define BOOST_SPIRIT_USE_PHOENIX_V3
#define BOOST_SPIRIT_UNICODE
#include <boost/regex/pending/unicode_iterator.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <iostream>
#include <string>
//==============================================================================
std::string to_utf8(const std::u32string& input) {
return std::string(
boost::u32_to_u8_iterator<std::u32string::const_iterator>(input.begin()),
boost::u32_to_u8_iterator<std::u32string::const_iterator>(input.end()));
}
//==============================================================================
int main() {
std::string input(u8"Hallo äöüß");
typedef boost::u8_to_u32_iterator<std::string::const_iterator> iterator_type;
iterator_type first(input.begin()), last(input.end());
qi::rule<iterator_type, std::u32string()> string_u32 = *(qi::char_ - qi::eoi);
qi::rule<iterator_type, std::string()> string =
string_u32[qi::_val …
Run Code Online (Sandbox Code Playgroud) 我的问题其实很简单.我目前正在研究一种语言解析器,它可以解析嵌入式DSL的元语言.这对我来说非常有趣,因为它可能用HTML和嵌入式JavaScript/CSS解析网站.我想设计一些具有最小DSL的类似系统,用于特定用例.
boost :: spirit是否能够做类似的事情?我只是不知道boost :: spirit如何处理词法分析器生成或者它是否是无扫描器解析器.
提前致谢!
我有一个Qi语法定义,用于解析输入。后来我有了一个Karma生成器,其输出方式应该与输入类似。
这有可能吗?解析器语法似乎可以自动转换为生成器语法(??)。
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <iostream>
int main(){
//test input
std::string s = "Xx 1.233 pseudo";
//input variables
std::string element;
double mass;
std::string pseudo;
auto GRAMMAR =
boost::spirit::qi::lexeme[+(boost::spirit::qi::char_ - ' ' - '\n')]
>> boost::spirit::qi::double_
>> boost::spirit::qi::lexeme[+(boost::spirit::qi::char_ - ' ' - '\n')];
bool r = boost::spirit::qi::phrase_parse(
s.begin(), s.end(),
GRAMMAR,
boost::spirit::qi::space, element, mass, pseudo
);
std::cout << boost::spirit::karma::format(
GRAMMAR ??? is it possible?
,
element,
mass,
pseudo
);
}
Run Code Online (Sandbox Code Playgroud) 为了提高性能,我希望更换:
template<class T> std::string ToStringFixed(const T x, const unsigned int width = 8)
{
std::stringstream ss;
ss << std::setprecision(width) << std::fixed << x;
return ss.str();
}
Run Code Online (Sandbox Code Playgroud)
有了Boost Karma的实现,因为我们的项目已经使用了Boost,它看起来比上面的天真解决方案有显着的性能提升.
就像是:
std::string ToString(double d)
{
using boost::spirit::karma::double_;
using boost::spirit::ascii::space;
using boost::spirit::karma::generate;
std::string s
std::back_insert_iterator<std::string> sink(s);
generate(sink, double_, d);
return s;
}
Run Code Online (Sandbox Code Playgroud)
这是从以下网站采用的:http://thisthread.blogspot.com/2011/04/generating-text-with-spirit-karma.html似乎走在正确的轨道上,但我不清楚如何控制精度,或者如果这样的解决方案对于浮点类型可以是模板友好的而不使用类型特征.(通过C++ 14使用的答案是可以接受的.)
我正在尝试使用Boost :: Spirit解析字符串,但是我无法使其正常工作。从今天开始,我没有使用Boost :: Spirit的经验。
该字符串由用“;”分隔的命令组成。这些命令是
“ INC someInteger”
“ BOMB第一整数第二整数”
“移动第一整数第二整数第三第三整数”
“ MSG someString”
“等待”
我设法做到了这一点:
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix/phoenix.hpp>
using namespace boost::spirit;
int main() {
std::string testInput = "MOVE 1 2 43;BOMB 0 3;INC 6;MOVE 2 3 99;MOVE 1 2 6";
typedef std::string::iterator iter;
using boost::phoenix::ref;
iter start = testInput.begin();
std::vector<int> IncCommands;
std::vector<std::pair<int, int>> BombCommands;
std::vector<std::tuple<int, int, int>> MoveCommands;
qi::rule<iter, std::vector<int>(), ascii::space_type> nextIncrease = ("INC " >> qi::int_);
//qi::rule<iter, std::vector<std::pair<int, int>>(), ascii::space_type> nextBomb = ("BOMB " >> qi::int_ …
Run Code Online (Sandbox Code Playgroud) boost-spirit ×10
boost ×8
c++ ×8
parsing ×3
boost-fusion ×1
performance ×1
qi ×1
std ×1
unicode ×1