- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下规则:
rule<std::string::const_iterator, std::string()> t_ffind, t_sim, t_hash, t_state;
t_ffind = hold[(attr('$') >> t_sim >> t_hash >> t_state)] | t_sim;
这意味着我可以单独找到 t_sim
或者后面跟着 t_hash
和 t_state
,如果它是单独的 t_ffind
将采用 t_sim
的确切值,在其他情况下,我还将在字符串的开头插入一个标记字符。
但如果我这样写规则,我将解析 t_sim
两次,所以我将规则修改为:
t_ffind = t_sim >> -(qi::hold[t_hash >> t_state]);
但如果 (t_hash >> t_state)
存在,插入字符的问题仍然存在,我认为解决方案可能是最后的一些语义操作:
t_ffind = t_sim >> -(qi::hold[t_hash >> t_state])[];
但我找不到如何做到这一点,如果有其他不涉及语义操作的解决方案会更好。
最佳答案
我会说“向一些不相关的属性添加魔法字符”的想法构成了一个有问题的设计选择。一般来说,我建议将解析和程序逻辑分开。所以我会解析成
namespace ast {
struct t_ffind {
std::string t_sim;
boost::optional<std::string> t_hash, t_state; // or whatever the types are
};
}
或者,如果您真的没有理由将散列/状态标记建模到单独的字段中,您可以这样做
namespace ast {
struct t_ffind {
std::string t_sim_hash_state;
bool sim_only;
};
}
但是从语义操作中设置 sim_only
会变得更复杂。这越来越接近您面临的问题。
只是为了好玩,让我们看看我们能做什么。首先,优化 t_sim
的重复解析听起来像是过早的优化。但也许您可以使用语义操作来更改 _val
:
t_ffind %= t_sim >> -(as_string[t_hash >> t_state] [ insert(_val, begin(_val), '$') ]);
请注意使用 as_string[]
将 t_hash 和 t_state 的属性粘合在一起,因此自动属性传播会继续工作。我强烈怀疑这显然比解析 t_sim
两次对性能的影响更大。
你可以尝试从 Spirit 争取更多的控制权:
t_ffind = (t_sim >> -(as_string[t_hash >> t_state]))
[ if_(_2) [ _val = '$' + _1 + *_2 ].else_ [ _val = _1 ] ];
仍然使用as_string
中间拼接。你可以放弃它:
t_ffind = (t_sim >> -(t_hash >> t_state))
[ if_(_2)
[ _val = '$' + _1 + at_c<0>(*_2) + at_c<1>(*_2) ]
.else_
[ _val = _1 ]
];
到现在为止,我们为了获得很少的 yield (如果有的话)已经离谱得很远了。我建议要么
用天真的方式写:
t_ffind = hold[(attr('$') >> t_sim >> t_hash >> t_state)] | t_sim;
修复您的 AST 以反射(reflect)您正在解析的内容
手动编写解析器
所有上述变体:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
int main() {
using namespace boost::spirit::qi;
rule<std::string::const_iterator, std::string()>
t_sim = "sim",
t_hash = +digit,
t_state = raw[lit("on")|"off"],
t_ffind;
for (auto initialize_t_ffind : std::vector<std::function<void()> > {
[&] { t_ffind = hold[(attr('$') >> t_sim >> t_hash >> t_state)] | t_sim; },
[&] {
// this works:
using boost::phoenix::insert;
using boost::phoenix::begin;
t_ffind %= t_sim >> -(as_string[t_hash >> t_state] [ insert(_val, begin(_val), '$') ]);
},
[&] {
// this works too:
using boost::phoenix::if_;
t_ffind = (t_sim >> -(as_string[t_hash >> t_state]))
[ if_(_2)
[ _val = '$' + _1 + *_2 ]
.else_
[ _val = _1 ]
];
},
[&] {
// "total control":
using boost::phoenix::if_;
using boost::phoenix::at_c;
t_ffind = (t_sim >> -(t_hash >> t_state))
[ if_(_2)
[ _val = '$' + _1 + at_c<0>(*_2) + at_c<1>(*_2) ]
.else_
[ _val = _1 ]
];
} })
{
initialize_t_ffind();
for (std::string const s : { "sim78off", "sim" })
{
auto f = s.begin(), l = s.end();
std::string result;
if (parse(f, l, t_ffind, result)) {
std::cout << "Parsed: '" << result << "'\n";
} else {
std::cout << "Parse failed\n";
}
if (f != l) {
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
}
}
}
打印:
Parsed: '$sim78off'
Parsed: 'sim'
Parsed: '$sim78off'
Parsed: 'sim'
Parsed: '$sim78off'
Parsed: 'sim'
Parsed: '$sim78off'
Parsed: 'sim'
关于c++ - 灵气中如何在字符串属性开头插入一个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36503667/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!