后续问题 https://stackoverflow.com/questions/34229428/how-to-get-around-matching-boost-variant-return-types
所以,我一直在玩
Boost Mini C 教程 https://stackoverflow.com/questions/34022066/boost-mini-c-tutorial
我所做的是添加一条规则来解析字符串文字。目的是让我可以解析和编译类似的程序(功能已经内置):
int ret(int x) {
return x;
}
int main() {
int x = 5;
return ret(x)*2;
}
也 (want添加此功能),
string print(string s) {
return s;
}
int main() {
string foo = "bar";
print(foo);
return 0;
}
最后两个示例是否使用 gcc 进行编译并不重要。
所以,我添加的要点如下:
文件内表达式_def.hpp(已添加生产规则“quoted_string”):
quoted_string = '"' >> *('\\' >> char_ | ~char_('"')) >> '"'; // ADDED THIS
primary_expr =
uint_
| quoted_string // ADDED THIS
| function_call
| identifier
| bool_
| '(' > expr > ')'
;
within ast.hpp,已添加变体类型“std:string”:
typedef boost::variant<
nil
, bool
, unsigned int
, std::string // ADDED THIS
, identifier
, boost::recursive_wrapper<unary>
, boost::recursive_wrapper<function_call>
, boost::recursive_wrapper<expression>
>
operand;
这是添加的规则声明,以及它所冲突的规则:
qi::rule<Iterator, std::string(), skipper<Iterator> > identifier;
qi::rule<Iterator, std::string()> quoted_string; // declaring this without the skipper
// lets us avoid the lexeme[] incantation (thanks @sehe).
现在的问题是,编译器混淆了“quoted_string”的“标识符”,或者实际上只是一个 std::string。
我的猜测是,它们都有 std::string 签名返回类型这一事实是问题的原因,但我不知道这里有什么好的解决方法。此外,“identifier”结构有一个用于初始化的 std::string 类型的数据成员,因此编译器实际上无法区分两者,并且变体 std::string 最终成为更好的匹配。
现在,如果我将 std::string 更改为 char* ,如下所示:
typedef boost::variant<
nil
, bool
, unsigned int
, char* // CHANGED, YET AGAIN
, identifier
, boost::recursive_wrapper<unary>
, boost::recursive_wrapper<function_call>
, boost::recursive_wrapper<expression>
>
operand;
它将编译并使用整数,我打赌然后我无法解析字符串(事实上,VS 将调用 abort()) 应该注意的是,因为每个变体都需要重载,所以我的代码中包含以下内容:
bool compiler::operator()(std::string const& x)
{
BOOST_ASSERT(current != 0);
current->op(op_string, x);
return true;
}
and
void function::op(int a, std::string const& b)
{
code.push_back(a);
code.push_back(b.size());
for (uintptr_t ch : b)
{
code.push_back(ch);
}
size_ += 2 + b.size();
}
当我需要解析字符串时,这两种方法都可以顺利工作(当然会牺牲处理整数的能力)。
它们的整数等价物是(并且可以在编译器.cpp)
bool compiler::operator()(unsigned int x)
{
BOOST_ASSERT(current != 0);
current->op(op_int, x);
return true;
}
而且当然:
void function::op(int a, int b)
{
code.push_back(a);
code.push_back(b);
size_ += 2;
}
如果我必须将变体类型从 std::string 更改为 char*,那么我必须更新重载,并且由于 C 遗留问题,它看起来有点难看。
我知道这可能有点令人畏惧,并且没有真正吸引人去梳理源代码,但我向你保证事实并非如此。本编译器教程只是将字节码推入向量中,该向量在设计上仅处理整数。我正在尝试修改它以处理字符串,因此添加和重载,以及需要unintptr_t。任何熟悉该材料和/或 Boost 的人都可能确切地知道他们在看什么(呃,@sehe,呃!)。