简单解析器和生成器 我需要从C++对象中解析并生成一些文本。
语法是:简单解析器和生成器 我需要从C++对象中解析并生成一些文本。,c++,parsing,tokenize,boost-spirit,C++,Parsing,Tokenize,Boost Spirit,语法是: command #param #param #param 有一组命令,其中一些没有参数等。 参数主要是数字 问题是:我是否应该用激励精神来完成这项任务?或者只是简单地将每行求值函数标记为从字符串调用,并与命令进行比较,读取其他参数并从中创建cpp对象 如果您建议使用Spirit或任何其他解决方案,如果您能提供一些与我的问题类似的示例,那就太好了。我已经阅读并尝试了Boost Spirit文档中的所有示例。对于简单格式化、易于测试的输入,标记化应该足够了。 当标记化时,您可以从输入中读
command #param #param #param
有一组命令,其中一些没有参数等。
参数主要是数字
问题是:我是否应该用激励精神来完成这项任务?或者只是简单地将每行求值函数标记为从字符串调用,并与命令进行比较,读取其他参数并从中创建cpp对象
如果您建议使用Spirit或任何其他解决方案,如果您能提供一些与我的问题类似的示例,那就太好了。我已经阅读并尝试了Boost Spirit文档中的所有示例。对于简单格式化、易于测试的输入,标记化应该足够了。
当标记化时,您可以从输入中读取一行并将其放入stringstream(iss)中。从iss中,您读取第一个单词并将其传递给命令工厂,该工厂为您创建正确的命令。然后可以将iss传递给新命令的readInParameters函数,这样每个命令都可以解析自己的参数并检查所有参数是否有效 未测试的代码示例:
std::string line;
std::getline(inputStream, line);
std::istringstream iss(line);
std::string strCmd;
iss >> strCmd;
try
{
std::unique_ptr<Cmd> newCmd = myCmdFactory(strCmd);
newCmd->readParameters(iss);
newCmd->execute();
//...
}
catch (std::exception& e)
{
std::cout << "Issue with received command: " << e.what() << "\n";
}
std::字符串行;
std::getline(inputStream,line);
标准::istringstream iss(线);
std::字符串strCmd;
iss>>strCmd;
尝试
{
std::unique_ptr newCmd=myCmdFactory(strCmd);
newCmd->readParameters(iss);
newCmd->execute();
//...
}
捕获(标准::异常&e)
{
std::cout对于简单格式化、易于测试的输入,标记化应该足够了。
当标记化时,您可以从输入中读取一行并将其放入stringstream(iss)中。从iss中,您读取第一个单词并将其传递给一个命令工厂,该工厂为您创建正确的命令。然后您可以将iss传递给新命令的readInParameters函数,以便每个命令都可以解析自己的参数并检查所有参数是否有效
未测试的代码示例:
std::string line;
std::getline(inputStream, line);
std::istringstream iss(line);
std::string strCmd;
iss >> strCmd;
try
{
std::unique_ptr<Cmd> newCmd = myCmdFactory(strCmd);
newCmd->readParameters(iss);
newCmd->execute();
//...
}
catch (std::exception& e)
{
std::cout << "Issue with received command: " << e.what() << "\n";
}
std::字符串行;
std::getline(inputStream,line);
标准::istringstream iss(线);
std::字符串strCmd;
iss>>strCmd;
尝试
{
std::unique_ptr newCmd=myCmdFactory(strCmd);
newCmd->readParameters(iss);
newCmd->execute();
//...
}
捕获(标准::异常&e)
{
std::cout我或多或少精确地实现了这个问题
使用Boost Spirit的完整工作示例程序(需要非常相似的语法)如下:。您只需要删除语法的/execute
文本,因此请从
到
示例脚本
WriteLine "bogus"
Write "here comes the answer: "
Write 42
Write 31415e-4
Write "that is the inverse of" 24 "and answers nothing"
Shutdown "Bye" 9
Shutdown "Test default value for retval"
现在,执行后会产生以下输出:
WriteLine('bogus');
Write(string: 'here comes the answer: ');
Write(double: 42);
Write(double: 3.1415);
Write(string: 'that is the inverse of');
Write(double: 24);
Write(string: 'and answers nothing');
Shutdown(reason: 'Bye', retval: 9)
Shutdown(reason: 'Test default value for retval', retval: 0)
完整代码
出于存档目的:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <fstream>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
///////////////////////////////////
// 'domain classes' (scriptables)
struct Echo
{
void WriteLine(const std::string& s) { std::cout << "WriteLine('" << s << "');" << std::endl; }
void WriteStr (const std::string& s) { std::cout << "Write(string: '" << s << "');" << std::endl; }
void WriteInt (int i) { std::cout << "Write(int: " << i << ");" << std::endl; }
void WriteDbl (double d) { std::cout << "Write(double: " << d << ");" << std::endl; }
void NewLine () { std::cout << "NewLine();" << std::endl; }
} echoService;
struct Admin
{
void Shutdown(const std::string& reason, int retval)
{
std::cout << "Shutdown(reason: '" << reason << "', retval: " << retval << ")" << std::endl;
// exit(retval);
}
} adminService;
void execute(const std::string& command)
{
typedef std::string::const_iterator It;
It f(command.begin()), l(command.end());
using namespace qi;
using phx::bind;
using phx::ref;
rule<It, std::string(), space_type> stringlit = lexeme[ '"' >> *~char_('"') >> '"' ];
try
{
if (!phrase_parse(f,l, /*"/execute" >*/ (
(lit("WriteLine")
> stringlit [ bind(&Echo::WriteLine, ref(echoService), _1) ])
| (lit("Write") >> +(
double_ [ bind(&Echo::WriteDbl, ref(echoService), _1) ] // the order matters
| int_ [ bind(&Echo::WriteInt, ref(echoService), _1) ]
| stringlit [ bind(&Echo::WriteStr, ref(echoService), _1) ]
))
| (lit("NewLine") [ bind(&Echo::NewLine, ref(echoService)) ])
| (lit("Shutdown") > (stringlit > (int_ | attr(0)))
[ bind(&Admin::Shutdown, ref(adminService), _1, _2) ])
), space))
{
if (f!=l) // allow whitespace only lines
std::cerr << "** (error interpreting command: " << command << ")" << std::endl;
}
}
catch (const expectation_failure<It>& e)
{
std::cerr << "** (unexpected input '" << std::string(e.first, std::min(e.first+10, e.last)) << "') " << std::endl;
}
if (f!=l)
std::cerr << "** (warning: skipping unhandled input '" << std::string(f,l) << "')" << std::endl;
}
int main()
{
std::ifstream ifs("input.txt");
std::string command;
while (std::getline(ifs/*std::cin*/, command))
execute(command);
}
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间phx=boost::phoenix;
///////////////////////////////////
//“域类”(脚本)
结构回声
{
void WriteLine(const std::string&s){std::cout我对问题“”或多或少地实现了这一点
使用Boost Spirit的完整工作示例程序(需要非常相似的语法)如下:。您只需要删除语法的/execute
文本,因此请从
到
示例脚本
WriteLine "bogus"
Write "here comes the answer: "
Write 42
Write 31415e-4
Write "that is the inverse of" 24 "and answers nothing"
Shutdown "Bye" 9
Shutdown "Test default value for retval"
现在,执行后会产生以下输出:
WriteLine('bogus');
Write(string: 'here comes the answer: ');
Write(double: 42);
Write(double: 3.1415);
Write(string: 'that is the inverse of');
Write(double: 24);
Write(string: 'and answers nothing');
Shutdown(reason: 'Bye', retval: 9)
Shutdown(reason: 'Test default value for retval', retval: 0)
完整代码
出于存档目的:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <fstream>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
///////////////////////////////////
// 'domain classes' (scriptables)
struct Echo
{
void WriteLine(const std::string& s) { std::cout << "WriteLine('" << s << "');" << std::endl; }
void WriteStr (const std::string& s) { std::cout << "Write(string: '" << s << "');" << std::endl; }
void WriteInt (int i) { std::cout << "Write(int: " << i << ");" << std::endl; }
void WriteDbl (double d) { std::cout << "Write(double: " << d << ");" << std::endl; }
void NewLine () { std::cout << "NewLine();" << std::endl; }
} echoService;
struct Admin
{
void Shutdown(const std::string& reason, int retval)
{
std::cout << "Shutdown(reason: '" << reason << "', retval: " << retval << ")" << std::endl;
// exit(retval);
}
} adminService;
void execute(const std::string& command)
{
typedef std::string::const_iterator It;
It f(command.begin()), l(command.end());
using namespace qi;
using phx::bind;
using phx::ref;
rule<It, std::string(), space_type> stringlit = lexeme[ '"' >> *~char_('"') >> '"' ];
try
{
if (!phrase_parse(f,l, /*"/execute" >*/ (
(lit("WriteLine")
> stringlit [ bind(&Echo::WriteLine, ref(echoService), _1) ])
| (lit("Write") >> +(
double_ [ bind(&Echo::WriteDbl, ref(echoService), _1) ] // the order matters
| int_ [ bind(&Echo::WriteInt, ref(echoService), _1) ]
| stringlit [ bind(&Echo::WriteStr, ref(echoService), _1) ]
))
| (lit("NewLine") [ bind(&Echo::NewLine, ref(echoService)) ])
| (lit("Shutdown") > (stringlit > (int_ | attr(0)))
[ bind(&Admin::Shutdown, ref(adminService), _1, _2) ])
), space))
{
if (f!=l) // allow whitespace only lines
std::cerr << "** (error interpreting command: " << command << ")" << std::endl;
}
}
catch (const expectation_failure<It>& e)
{
std::cerr << "** (unexpected input '" << std::string(e.first, std::min(e.first+10, e.last)) << "') " << std::endl;
}
if (f!=l)
std::cerr << "** (warning: skipping unhandled input '" << std::string(f,l) << "')" << std::endl;
}
int main()
{
std::ifstream ifs("input.txt");
std::string command;
while (std::getline(ifs/*std::cin*/, command))
execute(command);
}
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间phx=boost::phoenix;
///////////////////////////////////
//“域类”(脚本)
结构回声
{
void WriteLine(常量std::string&s){std::cout如果你想学习Spirit,请继续。否则这绝对足够简单,我只需要手动标记。看看boost::wave。下面是一个示例,如果你想学习Spirit,请继续。否则这绝对足够简单,我只需手动标记。看看boost::wave。下面是示例