我正在创建一个 CLI,但无法解析这样的代码:
io.print("Hello World!");
我将如何在不滥用 if 语句逐个字符解析代码的情况下解析这样的内容?
我希望控制台在窗口上打印这个:
Hello World!
我正在创建一个 CLI,但无法解析这样的代码:
io.print("Hello World!");
我将如何在不滥用 if 语句逐个字符解析代码的情况下解析这样的内容?
我希望控制台在窗口上打印这个:
Hello World!
从技术上讲,这可以解决您的问题,如下所述:
std::map< std::string, std::function<void()> > program_map;
void define_programs() {
program_map[ "io.print("Hello World!");\n" ] = []{
std::cout << "Hello World!\n";
};
program_map[ "io.print("Goodbye World!");\n" ] = []{
std::cout << "Goodbye World!\n";
};
};
int main() {
// load parser:
define_programs();
// read program from user:
std::string s;
std::cin >> s;
// compile and execute:
if (program_map.find( s ) != program_map.end()) {
(*program_map.find( s ))();
} else {
std::cout << "ERROR: unknown program.\n";
}
}
但它可能无法解决您想要解决的问题。
通常,解析 C 或 C++ 类语言需要大量工作。您可以通过制作更易于解析的语言来使您的工作更轻松(类似 LISP 的语法非常容易解析)。
如果您确实想解析类似 C/C++ 的语言,我建议您学习语法和词法分析器。有完整的本科课程以为比 C/C++ 更简单的语言编写编译器结束——尤其是 C++ 是一种很难解析的语言,通常你不希望完全遵循它的约定。
为您的语法设计语法和编写词法分析器(或教授预先编写的词法分析器)应该齐头并进。
当我设计玩具语言时,我通常让它们像 LISP,因为像 LISP 的语言真的很容易使用。所以你有一个命令初始化器(
,一个命令,一个参数列表(可能是 futher (
'd),当你到达匹配的)
.
所以相当于你的代码是:
(io print "Hello World")
现在我有了io
命令(对象实例将是各种“命令”)和方法 print(它从插槽 2 读取),以及所述方法“Hello World”的参数。结果,如果我感觉功能正常,那将是一个打印的程序Hello World
——如果不是,它会作为副作用执行此操作并返回错误代码或不返回任何内容。
然后我会围绕它编写一个环境来定义一些命令(包括“make object”),可能是某种引用语法(所以我可以定义 lambdas)等等。我最终会得到一种设计不佳的语言, 次优的, 小部分 common lisp 的受限实现, 这是传统的。
只有在我可以做类似上述的事情之后,我才会考虑为像 C/C++ 这样更难解析的语言编写一个解析器。即便如此,我还是先将上面的玩具语言重写为一些词法分析/解析框架,然后在同一个框架中编写我的 C/C++ 类语言。
这就是你在 C++ 中编写 HelloWorld 的方式:
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
该字符串将在编译时进行解析,因此无需担心打印效率低下。
如果我误解了你的问题(我只知道 CLI 代表命令行界面),而你真的想解析 C++ 源代码。我建议您阅读有关 yacc 之类的工具的教程,并从开源 C 语法开始。
这是一个很好的 yacc 教程: http ://www.ds9a.nl/lex-yacc/cvs/lex-yacc-howto.html
这是语法的一个很好的起点:http: //www.computing.surrey.ac.uk/research/dsrg/fog/CxxGrammar.y