为什么下面的代码会在运行时崩溃(它会给出堆栈溢出错误)?
#include <boost/any.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace qi = boost::spirit::qi;
// Helper structs
// types
enum class types { void_t, int_t, double_t, bool_t, string_t };
struct types_ : qi::symbols<char, types>
{
types_()
{
add
("void" , types::void_t)
("int" , types::int_t)
("double" , types::double_t)
("bool" , types::bool_t)
("string" , types::string_t)
;
}
} type;
inline
std::ostream& operator<<(std::ostream& os, const types& type)
{
switch (type)
{
case types::void_t:
os << "void";
break;
case types::int_t:
os << "int";
break;
case types::double_t:
os << "double";
break;
case types::bool_t:
os << "bool";
break;
case types::string_t:
os << "string";
break;
}
return os;
}
// assignment_operators
enum class assignment_operators { basic, addition, subtraction, multiplication, division, modulo, bitwise_and, bitwise_or, bitwise_xor, bitwise_left_shift, bitwise_right_shift };
struct assignment_operators_ : boost::spirit::qi::symbols<char, assignment_operators>
{
assignment_operators_()
{
add
("=" , assignment_operators::basic)
("+=" , assignment_operators::addition)
("-=" , assignment_operators::subtraction)
("*=" , assignment_operators::multiplication)
("/=" , assignment_operators::division)
("%=" , assignment_operators::modulo)
("&=" , assignment_operators::bitwise_and)
("|=" , assignment_operators::bitwise_or)
("^=" , assignment_operators::bitwise_xor)
("<<=" , assignment_operators::bitwise_left_shift)
(">>=" , assignment_operators::bitwise_right_shift)
;
}
} assignment_operator;
inline
std::ostream& operator<<(std::ostream& os, const assignment_operators& assignment_operator)
{
switch (assignment_operator)
{
case assignment_operators::basic:
os << "=";
break;
case assignment_operators::addition:
os << "+=";
break;
case assignment_operators::subtraction:
os << "-=";
break;
case assignment_operators::multiplication:
os << "*=";
break;
case assignment_operators::division:
os << "/=";
break;
case assignment_operators::modulo:
os << "%=";
break;
case assignment_operators::bitwise_and:
os << "&=";
break;
case assignment_operators::bitwise_or:
os << "|=";
break;
case assignment_operators::bitwise_xor:
os << "^=";
break;
case assignment_operators::bitwise_left_shift:
os << "<<=";
break;
case assignment_operators::bitwise_right_shift:
os << ">>=";
break;
}
return os;
}
// relational_operators
enum class relational_operators { equal_to, not_equal_to, greater_than, less_than, greater_than_or_equal_to, less_than_or_equal_to };
struct relational_operators_ : boost::spirit::qi::symbols<char, relational_operators>
{
relational_operators_()
{
add
("==" , relational_operators::equal_to)
("!=" , relational_operators::not_equal_to)
(">" , relational_operators::greater_than)
("<" , relational_operators::less_than)
(">=" , relational_operators::greater_than_or_equal_to)
("<=" , relational_operators::less_than_or_equal_to)
;
}
} relational_operator;
inline
std::ostream& operator<<(std::ostream& os, const relational_operators& relational_operator)
{
switch (relational_operator)
{
case relational_operators::equal_to:
os << "==";
break;
case relational_operators::not_equal_to:
os << "!=";
break;
case relational_operators::greater_than:
os << ">";
break;
case relational_operators::less_than:
os << "<";
break;
case relational_operators::greater_than_or_equal_to:
os << ">=";
break;
case relational_operators::less_than_or_equal_to:
os << "<=";
break;
}
return os;
}
// parameter
BOOST_FUSION_DEFINE_STRUCT(
(), parameter,
(types, type)
(std::string, name)
)
// function_call
BOOST_FUSION_DEFINE_STRUCT(
(), function_call,
(std::string, name)
(std::vector<boost::any>, actual_parameters)
)
// variable_definition
BOOST_FUSION_DEFINE_STRUCT(
(), variable_definition,
(std::string, name)
(boost::any, initializer)
)
// variables_definitions
BOOST_FUSION_DEFINE_STRUCT(
(), variables_definitions,
(types, type)
(std::vector<::variable_definition>, variables)
)
// return_expression
BOOST_FUSION_DEFINE_STRUCT(
(), return_statement,
(boost::any, value)
)
// assignment_expression
BOOST_FUSION_DEFINE_STRUCT(
(), assignment_expression,
(std::string, name)
(assignment_operators, op)
(boost::any, value)
)
// relational_expression
BOOST_FUSION_DEFINE_STRUCT(
(), relational_expression,
(boost::any, left)
(relational_operators, op)
(boost::any, right)
)
// function
typedef boost::any expressions_types;
BOOST_FUSION_DEFINE_STRUCT(
(), function,
(types, ret_type)
(std::string, name)
(std::vector<parameter>, parameters)
(std::vector<expressions_types>, expressions)
)
// preprocessor_directive
BOOST_FUSION_DEFINE_STRUCT(
(), include_preprocessor_directive,
(std::string, file)
)
BOOST_FUSION_DEFINE_STRUCT(
(), define_preprocessor_directive,
(std::string, name)
(boost::any, value)
)
BOOST_FUSION_DEFINE_STRUCT(
(), property_preprocessor_directive,
(std::string, name)
(boost::any, value)
)
typedef boost::variant<::include_preprocessor_directive, ::define_preprocessor_directive, ::property_preprocessor_directive> preprocessor_directives_t;
// mql source
typedef boost::variant<::function, preprocessor_directives_t, ::variables_definitions> mql_source_elements_types;
BOOST_FUSION_DEFINE_STRUCT(
(), mql_source,
(std::vector<mql_source_elements_types>, mql_source_elements)
)
template <typename Iterator, typename Skipper>
struct mql_parser : qi::grammar<Iterator, mql_source(), Skipper>
{
mql_parser() : mql_parser::base_type(start_)
{
identifier_ %= qi::alpha >> *qi::alnum; // foo, bar, some1var
literal_ %= qi::int_ // 1
| qi::double_ // 1.5
| qi::bool_ // true
| ('\'' >> qi::char_ >> '\'') // 's'
| qi::as_string[qi::lexeme['"' >> +(qi::char_ - '"') >> '"']]; // "str"
relational_expression_ %= expression_ >> relational_operator >> expression_; // i == 0
assignment_expression_ %= identifier_ >> assignment_operator >> expression_; // i = 1
expression_ %= relational_expression_ | identifier_ | function_call_ | literal_ | ('(' >> expression_ >> ')');
function_call_ %= identifier_ >> '(' >> (expression_ % ',') >> ')';
variable_definition_ %= identifier_ >> -('=' >> expression_); // int i = 0
variables_definitions_ %= type >> (variable_definition_ % ','); // int i = 0, j = 1
return_statement_ %= "return" >> -(expression_);
param_ %= type >> -identifier_;
function_definition_ %= type >> identifier_ >> '(' >> (param_ % ',') >> ')' >> '{' >> (expression_ % ';') >> ';' >> '}'; // void foo(int bar, double) { foo(); int i = 0; }
include_preprocessor_directive_ %= '#' >> qi::lit("include") >> qi::lexeme[+qi::graph]; // #include <WinUser32.mqh>
define_preprocessor_directive_ %= '#' >> qi::lit("define") >> identifier_ >> literal_; // #define FOO 0
property_preprocessor_directive_ %= '#' >> qi::lit("property") >> identifier_ >> -literal_; // #property stacksize 1024
preprocessor_directive_ %= include_preprocessor_directive_ | define_preprocessor_directive_ | property_preprocessor_directive_; // #include <WinUser32.mqh>
start_ %= qi::eps >> +(function_definition_ | preprocessor_directive_ | (variables_definitions_ >> ';')); // void foo(int bar, double) { foo(); } void bar(int baz, double) { foo(); }
}
qi::rule<Iterator, std::string() > identifier_;
qi::rule<Iterator, parameter() , Skipper> param_;
qi::rule<Iterator, function_call() , Skipper> function_call_;
qi::rule<Iterator, boost::any() , Skipper> literal_;
qi::rule<Iterator, variable_definition() , Skipper> variable_definition_;
qi::rule<Iterator, variables_definitions() , Skipper> variables_definitions_;
qi::rule<Iterator, return_statement() , Skipper> return_statement_;
qi::rule<Iterator, assignment_expression() , Skipper> assignment_expression_;
qi::rule<Iterator, relational_expression() , Skipper> relational_expression_;
qi::rule<Iterator, expressions_types() , Skipper> expression_;
qi::rule<Iterator, function() , Skipper> function_definition_;
qi::rule<Iterator, include_preprocessor_directive() , Skipper> include_preprocessor_directive_;
qi::rule<Iterator, define_preprocessor_directive() , Skipper> define_preprocessor_directive_;
qi::rule<Iterator, property_preprocessor_directive() , Skipper> property_preprocessor_directive_;
qi::rule<Iterator, preprocessor_directives_t() , Skipper> preprocessor_directive_;
qi::rule<Iterator, mql_source() , Skipper> start_;
};
std::string get_file_content(const boost::filesystem::path& file_path)
{
std::string file_content;
boost::filesystem::ifstream f(file_path);
if (f)
{
file_content.append(
(std::istreambuf_iterator<char>(f))
, std::istreambuf_iterator<char>()
);
}
return file_content;
}
int main()
{
const std::string& input_data = get_file_content("input.txt");
mql_source mql_src;
auto itr = input_data.begin();
auto end = input_data.end();
qi::rule<decltype(itr)> skipper =
qi::ascii::space
| ("//" >> *(qi::char_ - qi::eol) >> qi::eol | qi::blank)
| ("/*" >> *(qi::char_ - "*/") >> "*/");
mql_parser<decltype(itr), decltype(skipper)> g;
bool res = qi::phrase_parse(
itr
, end
, g
, skipper
, mql_src
);
if (res && itr == end)
{
std::cout << "Parsing succeeded \n";
}
else
{
std::cout << "Parsing failed \n";
}
}
输入数据:
#include <WinUser32.mqh>
void foo(int bar, double baz) { int lol = 0; }
有什么想法可以解决吗?
最佳答案
你看到的是左递归。
左递归不与 PEG 语法混合。看看这两条规则:
expression_ %= relational_expression_ | identifier_ | function_call_ | literal_ | ('(' >> expression_ >> ')');
relational_expression_ %= expression_ >> relational_operator >> expression_; // i == 0
展开关系表达式:
expression_ %= expression_ >> ...
你能发现问题吗? spirit 贪婪地从左到右匹配。所以你告诉它,要检查输入是否可能是一个表达式_,首先检查它是否...它可能是一个表达式_:)
因此,通过使左节点更具限制性来修复它:
simple_expr_ %= identifier_ | function_call_ | literal_ | ('(' >> expression_ >> ')');
expression_ %= relational_expression_ | simple_expr_;
relational_expression_ %= simple_expr_ >> relational_operator >> expression_; // i == 0
当然,这里你需要额外的规则:
qi::rule simple_expr_;
语法中还有其他问题阻止它解析,因此您需要查看 BOOST_SPIRIT_DEBUG,但我没有时间为您的 AST 类型添加流运算符
关于c++ - 提振 spirit ,递归和堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21773660/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj
我经常迷上ruby的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=
出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t
我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc
我有这个ruby代码:defget_sumnreturn0ifn似乎正在为999之前的值工作。当我尝试9999时,它给了我这个:stackleveltoodeep(SystemStackError)所以,我添加了这个:RubyVM::InstructionSequence.compile_option={:tailcall_optimization=>true,:trace_instruction=>false}但什么也没发生。我的ruby版本是:ruby1.9.3p392(2013-02-22revision39386)[x86_64-darwin12.2.1]我还增加了机器的堆栈大