- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
解析表达式如下:
"asd {img} {ref I}sdkflsdlk {img} wmrwerml"
我有这样的代码:
struct CMyTag
{
std::string tagName;
std::string tagData;
};
BOOST_FUSION_ADAPT_STRUCT(::CMyTag, (std::string, tagName) (std::string, tagData));
struct fillMyTag
{
template <typename A, typename B = boost::spirit::unused_type, typename C = boost::spirit::unused_type, typename D = boost::spirit::unused_type>
struct result { typedef void type; };
void operator()(::CMyTag& _tag, const std::string& _name, const std::string& _type) const
{
_tag.tagName = _name;
_tag.tagData = _type;
}
};
template <typename Iterator>
struct testTag_grammar : qi::grammar<Iterator, std::vector<CMyTag>()>
{
testTag_grammar() :
testTag_grammar::base_type(data)
{
data = (text | imgtag | vartag | inctag | blktag | reftag) >> *data;
imgtagraw %= '{' >> qi::lit("img") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
imgtag = imgtagraw[op(qi::labels::_val, "img", boost::spirit::_1)];
vartagraw %= '{' >> qi::lit("var") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
vartag = vartagraw[op(qi::labels::_val, "var", boost::spirit::_1)];
inctagraw %= '{' >> qi::lit("inc") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
inctag = inctagraw[op(qi::labels::_val, "inc", boost::spirit::_1)];
blktagraw %= '{' >> qi::lit("blank") >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
blktag = blktagraw[op(qi::labels::_val, "blk", boost::spirit::_1)];
reftagraw %= '{' >> lexeme[("ref")] >> *(+qi::lit(' ') >> lexeme[+(char_ - '{' - '}')]) >> '}';
reftag = reftagraw[op(qi::labels::_val, "ref", boost::spirit::_1)];
textraw %= lexeme[+(char_ - '{' - '}')];
text = textraw[op(qi::labels::_val, "text", boost::spirit::_1)];
}
qi::rule<Iterator, std::string()> imgtagraw, vartagraw, inctagraw, blktagraw, reftagraw, textraw;
qi::rule<Iterator, CMyTag()> imgtag, vartag, inctag, blktag, reftag, text;
qi::rule<Iterator, std::vector<CMyTag>()> data;
boost::phoenix::function<fillMyTag> op;
};
解析器的使用:
testTag_grammar<std::string::iterator> l_gramar;
std::string l_test = "asd {img} {ref I}sdkflsdlk {img} wmrwerml";
std::vector<CMyTag> l_result;
bool result = qi::parse(l_test.begin(), l_test.end(), l_gramar, l_result);
因此,我希望获得 CmyTag 结构列表,但代码编译失败:
Error 1 error C2440: 'static_cast' : cannot convert from 'const std::vector<CMyTag,std::allocator<_Ty>>' to 'CMyTag' d:\lib\boost\include\boost-1_57\boost\spirit\home\qi\detail\assign_to.hpp 152 1 TestSpiritParser
当我更改要遵循的数据规则时:
data = ((text | imgtag | vartag | inctag | blktag | reftag)[opvec(qi::labels::_val, boost::spirit::_1)]) >> *data;
opvec 的定义:
struct fillMyVec
{
template <typename A, typename B = boost::spirit::unused_type, typename C = boost::spirit::unused_type, typename D = boost::spirit::unused_type>
struct result { typedef void type; };
void operator()(std::vector<CMyTag>& _tagvec, const CMyTag& _name) const
{
_tagvec.push_back(_name);
}
void operator()(std::vector<CMyTag>& _tagvec, std::vector<CMyTag>& _name) const
{
_tagvec.insert(_tagvec.end(), _name.begin(), _name.end());
}
};
boost::phoenix::function<fillMyVec> opvec;
代码开始编译成功,但作为运行的结果,我得到的列表中只有一项。同样在修改之前,当 CMytag 类型仅为 std::string 时,我得到了一个 std::string 列表,其中包含正确的项目数,
现在我不知道出了什么问题,也不知道如何解决问题
最佳答案
首先,我只能假设
data = (text | imgtag | vartag | inctag | blktag | reftag) >> *data;
是/meant/作为 (...) 表达式的 1 次或多次重复。写成
data = +(text | imgtag | vartag | inctag | blktag | reftag);
表示相同,但允许属性传播以匹配暴露属性类型。
有许多 lexeme[]
指令在不使用 skipper 时毫无用处
存在可疑的空格手动跳过,使用 skipper 可能会更好
如果您确实希望在“标签名称”后要求一个强制性空格,请考虑使用 operator&
运算符。这样你仍然可以使用 skipper 。
无论如何,您可能正在寻找类似 Qi Repository distinct()[]
parser directive 的内容
即使有 skipper
*(+lit(' ') >> lexeme[+(char_ - '{' - '}')])
没有意义,因为 lexeme[...]
会占用任何空间直到关闭 '}',因此第二次重复 *()
会永远不要申请。
See also Boost spirit skipper issues
规则之间有很多手动重复。考虑使用 qi::symbols
将输入映射到标签类型。
如果这样做,就更容易避免语义操作(好东西:Boost Spirit: "Semantic actions are evil"?)。即使没有,您也可以使用 qi::attr
将特定值公开为 type
值。
考虑添加调试信息(参见下面演示中的 BOOST_SPIRIT_DEBUG
)
我会将整个语法缩减为:
data = +( ('{' >> tag >> '}') | text );
tag = lexeme[type >> &char_(" {}")] >> lexeme[*~char_("{}")];
text = attr("text") >> lexeme[+~char_("{}")];
完成!不再有语义 Action ,不再有数十条基本相同的规则。不再有多重性不明确的复杂嵌套重复。 type
现在是一个 qi::symbols
解析器,它包含标签名称的映射:
type.add
("img", "img")
("var", "var")
("inc", "inc")
("blank", "blk")
("ref", "ref");
这是一个完整的演示:
//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
struct CMyTag
{
std::string tagName;
std::string tagData;
};
BOOST_FUSION_ADAPT_STRUCT(::CMyTag, (std::string, tagName) (std::string, tagData))
template <typename Iterator, typename Skipper = qi::space_type>
struct testTag_grammar : qi::grammar<Iterator, std::vector<CMyTag>(), Skipper>
{
testTag_grammar() :
testTag_grammar::base_type(data)
{
using namespace qi;
data = +( ('{' >> tag >> '}') | text );
type.add
("img", "img")
("var", "var")
("inc", "inc")
("blank", "blk")
("ref", "ref");
tag = lexeme[type >> &char_(" {}")] >> lexeme[*~char_("{}")];
text = attr("text") >> lexeme[+~char_("{}")];
BOOST_SPIRIT_DEBUG_NODES( (data) (tag) (text))
}
private:
qi::symbols<char, std::string> type;
qi::rule<Iterator, CMyTag(), Skipper> tag, text;
qi::rule<Iterator, std::vector<CMyTag>(), Skipper> data;
};
int main() {
testTag_grammar<std::string::const_iterator> l_gramar;
std::string const l_test = "asd {img} {ref I}sdkflsdlk {img} wmrwerml";
std::vector<CMyTag> l_result;
auto f = l_test.begin(), l = l_test.end();
bool result = qi::phrase_parse(f, l, l_gramar, qi::space, l_result);
if (result) {
std::cout << "Parse success: " << l_result.size() << "\n";
for (auto& v : l_result)
std::cout << "Name '" << v.tagName << "', Data '" << v.tagData << "'\n";
}
else {
std::cout << "Parse failed\n";
}
if (f!=l) {
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
}
打印
Parse success: 6
Name 'text', Data 'asd '
Name 'img', Data ''
Name 'ref', Data 'I'
Name 'text', Data 'sdkflsdlk '
Name 'img', Data ''
Name 'text', Data 'wmrwerml'
关于c++ - 编译 boost spirit 解析器时出现奇怪的 static_cast 编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30361656/
对引用 static_cast 的引用是否与指向指针 static_cast 的指针具有相同的运行时间成本? 例如 class B; class A: public class B; A obj; A
在下面的示例中,编译器接受 static_cast 向下转换,导致未定义的行为,而我认为 static_cast 完全是为了安全(C 风格转换无法提供) . #include class Base
在以下代码中(取自有效的 C++): class A { .... char& operator[](std::size_t position) // now just cal
我正在尝试理解 Pybind11 docs here 中使用的静态转换.具体来说,他们使用语法 static_cast(&Pet::set) 因为在我努力解释并应用到我自己的代码之前我还没有见过这种语
本题不涉及多态,即不涉及虚方法,不涉及虚基类。以防万一,我的案子不涉及这些。 假设我有一个类 Derived它有一个明确的可访问父类型 Base ,没有多态性(没有虚方法,没有虚基类),但可能涉及间接
我看到有人建议使用 static_cast(static_cast(p))而不是重新解释类型转换。 我不明白为什么这样更好,谁能解释一下? 为了便于讨论,这里有一个需要 reinterpret_cas
如果我执行以下操作,一切正常: char* cp = "abc"; void* vp = NULL; vp = static_cast(cp);//ok cp = static_cast(vp);//
让我们有一个名为 Y 的重载函数: void Y(int& lvalue) { cout void f(T&& x) { Y( static_cast(x) ); // Using sta
当你动态分配了一个 char * 类型的缓冲区并想将它转换为特定类型时,你是否应该使用类似的东西 reinterpret_cast(char *) 或者类似的东西 static_cast(static
这是来自 std::enable_if 教程中的示例。 这里有更多的上下文: // handle signed types template auto incr1(Int& target, Int a
我正在阅读 Scott Meyers 的 Effective C++ 3rd。 在第 3 项中: Use const whenever possible. In order to use const
我是 C++ 编程的初学者...我正在练习,遇到了这个问题...这里我尝试在复合运算符上使用 static_cast...我实际上正在尝试除两个整数并得到双倍的答案...这是代码: #include
如果我有两个类: 1) 员工 2) 工程师是派生 从员工 3) 经理是派生 从员工 我被告知(并自己尝试过)以下内容无法编译: Employee employee("John Smith"); Eng
我正在尝试实现一类数值 vector 。我正在使用类似于 STL vector 的 Qt 模板 QVector typedef float ArithmeticF; typedef QVector V
是否使用 static_cast 将 const unsigned char& 转换为 const unsigned long long& 已定义? constexpr unsigned char a
#include class A { public: A() { std::cout (a_obj); // This isn't safe. b_obj
我在我们的生产环境中遇到了以下代码结构(但是大大简化了)。 #include typedef struct { char entry[10]; } inn_struct; typedef s
我有以下两个类: class B; class A { public: A(); operator B() const; }; class B {
我有以下代码片段 class base { public: virtual void MyMethod() { std::cout (b); d->MyMeth
这是一个 discussion on stackoverflow四种显式转换中的一种。但我在投票最多的答案中遇到了一个问题。 引用自投票最多的 wiki 答案: static_cast can als
我是一名优秀的程序员,十分优秀!