gpt4 book ai didi

c++ - 你如何从 spirit 解析器输出原始的未解析代码(作为注释)

转载 作者:行者123 更新时间:2023-11-30 02:06:03 26 4
gpt4 key购买 nike

给定输入字符串:A = 23; B = 5,我目前得到(预期的)输出:

Output: 0xa0000023
Output: 0xa0010005
-------------------------

我想看到这个:

Output: 0xa0000023           // A = 23
Output: 0xa0010005 // B = 5
-------------------------

核心代码行是:

statement   = eps[_val = 0x50000000] >> identifier[_val += _1<<16] >>
"=" >> hex[_val += (_1 & 0x0000FFFF)];

其中标识符是 qi::symbols 表查找。

我的其余代码如下所示:

#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 <iostream>
#include <iomanip>
#include <ios>
#include <string>
#include <complex>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct reg16_ : qi::symbols<char,unsigned> {
reg16_() {
add ("A", 0) ("B", 1) ("C", 2) ("D", 3) ;
}
} reg16;

template <typename Iterator>
struct dash_script_parser : qi::grammar<Iterator, std::vector<unsigned>(), ascii::space_type> {
dash_script_parser() : dash_script_parser::base_type(start) {
using qi::hex;
using qi::_val;
using qi::_1;
using qi::eps;

identifier %= reg16;

start %= (statement % ";" );
statement = eps[_val = 0x50000000] >> identifier[_val += _1<<16]>> "=" >> hex[_val += (_1 & 0x0000FFFF)];
}
qi::rule<Iterator, std::vector<unsigned>(), ascii::space_type> start;
qi::rule<Iterator, unsigned(), ascii::space_type> statement;
qi::rule<Iterator, unsigned()> identifier;
};

int
main()
{
std::cout << "\t\tA parser for Spirit...\n\n" << "Type [q or Q] to quit\n\n";

dash_script_parser<std::string::const_iterator> g;
std::string str;
while (getline(std::cin, str))

{
if (str.empty() || str[0] == 'q' || str[0] == 'Q') break;

std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
std::vector<unsigned> strs;
bool r = phrase_parse(iter, end, g, boost::spirit::ascii::space, strs);
if (r && iter == end) {
for(std::vector<unsigned>::const_iterator it=strs.begin(); it<strs.end(); ++it)
std::cout << "Output: 0x" << std::setw(8) << std::setfill('0') << std::hex <<*it << "\n";
} else
std::cout << "Parsing failed\n";
}
return 0;
}

最佳答案

更新 更新的答案带来了iter_pos引起我的注意(来自 Boost Spirit Repository):

这基本上与下面的相同,但没有“滥用”语义 Action (使其更适合,尤其是自动属性传播。


我的直觉表明,首先将语句隔离到原始源迭代器范围内,然后再隔离地解析语句可能会更容易。这样一来,您就会在开头获得相应的源文本。

除此之外,这是我测试过的一种方法,它不会过多地破坏您的示例代码:


1。使属性类型成为结构

替换原语unsigned具有还包含源代码片段 verbatim 的结构,作为 string :

struct statement_t
{
unsigned value;
std::string source;
};

BOOST_FUSION_ADAPT_STRUCT(statement_t, (unsigned, value)(std::string, source));

2。让解析器填充这两个字段

好消息是,您已经在使用语义操作,所以它只是在此基础上构建。请注意,结果不是很漂亮,并且从转换为( fusion )仿函数中受益匪浅。但它非常清楚地展示了该技术:

start      %= (statement % ";" );
statement = qi::raw [
raw[eps] [ at_c<0>(_val) = 0x50000000 ]
>> identifier [ at_c<0>(_val) += _1<<16 ]
>> "=" >> hex [ at_c<0>(_val) += (_1 & 0x0000FFFF) ]
]
[ at_c<1>(_val) = construct<std::string>(begin(_1), end(_1)) ]
;

3。打印

所以,at_c<0>(_val)对应statement::value , 和 at_c<1>(_val)对应statement::source .这个稍微修改的输出循环:

for(std::vector<statement_t>::const_iterator it=strs.begin(); it<strs.end(); ++it)
std::cout << "Output: 0x" << std::setw(8) << std::setfill('0') << std::hex << it->value << " // " << it->source << "\n";

输出:

Output: 0x50000023 // A = 23
Output: 0x50010005 // B = 5

完整样本

#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 <iostream>
#include <iomanip>
#include <ios>
#include <string>
#include <complex>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
namespace phx = boost::phoenix;

struct reg16_ : qi::symbols<char,unsigned> {
reg16_() {
add ("A", 0) ("B", 1) ("C", 2) ("D", 3) ;
}
} reg16;

struct statement_t
{
unsigned value;
std::string source;
};

BOOST_FUSION_ADAPT_STRUCT(statement_t, (unsigned, value)(std::string, source));

template <typename Iterator>
struct dash_script_parser : qi::grammar<Iterator, std::vector<statement_t>(), ascii::space_type> {
dash_script_parser() : dash_script_parser::base_type(start) {
using qi::hex;
using qi::_val;
using qi::_1;
using qi::eps;
using qi::raw;

identifier %= reg16;

using phx::begin;
using phx::end;
using phx::at_c;
using phx::construct;

start %= (statement % ";" );
statement = raw [
raw[eps] [ at_c<0>(_val) = 0x50000000 ]
>> identifier [ at_c<0>(_val) += _1<<16 ]
>> "=" >> hex [ at_c<0>(_val) += (_1 & 0x0000FFFF) ]
]
[ at_c<1>(_val) = construct<std::string>(begin(_1), end(_1)) ]
;
}
qi::rule<Iterator, std::vector<statement_t>(), ascii::space_type> start;
qi::rule<Iterator, statement_t(), ascii::space_type> statement;
qi::rule<Iterator, unsigned()> identifier;
};

int
main()
{
std::cout << "\t\tA parser for Spirit...\n\n" << "Type [q or Q] to quit\n\n";

dash_script_parser<std::string::const_iterator> g;
std::string str;
while (getline(std::cin, str))

{
if (str.empty() || str[0] == 'q' || str[0] == 'Q') break;

std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
std::vector<statement_t> strs;
bool r = phrase_parse(iter, end, g, boost::spirit::ascii::space, strs);
if (r && iter == end) {
for(std::vector<statement_t>::const_iterator it=strs.begin(); it<strs.end(); ++it)
std::cout << "Output: 0x" << std::setw(8) << std::setfill('0') << std::hex << it->value << " // " << it->source << "\n";
} else
std::cout << "Parsing failed\n";
}
return 0;
}

关于c++ - 你如何从 spirit 解析器输出原始的未解析代码(作为注释),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9136734/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com