【问题标题】:C++ - Parse like C++? [closed]C++ - 像 C++ 一样解析? [关闭]
【发布时间】:2013-04-26 18:28:11
【问题描述】:

我正在创建 CLI,但无法解析如下代码:

io.print("Hello World!");

如何在不滥用 if 语句逐个字符解析代码的情况下解析这样的内容?

我希望控制台在窗口上打印这个:

Hello World!

【问题讨论】:

  • 传统上,您首先编写一个标记器(或找到一个合适的标记器)和一个将标记组合成 AST 或“理解”语法的语法,然后评估该语法。
  • 我已经使用字符串向量和字符串流编写了我的标记器。所以我能做的就是使用 IF 语句?
  • 首先,您不想编写 C++ 编译器。要么设计一种更简单的语言,要么嵌入/生成现有的 C++ 编译器。对于典型的脚本任务,前者几乎是无限可取的。
  • @JerryCoffin 同意,尽管对于典型的脚本任务,使用现有语言几乎是无限可取的!
  • 这个问题是在问一个类似于“我如何写Quake?我在屏幕上画了一个像素”的问题。 -- 回答“如何为像 C++ 这样的语言编写完整的编译器”的范围相当大。

标签: c++ windows console codeblocks


【解决方案1】:

从技术上讲,这可以解决您所描述的问题:

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 的语言真的很容易使用。所以你有一个命令初始化器(、一个命令、一个参数列表(可能是('d),当你到达匹配的)时,命令就会执行。

所以你的代码相当于:

(io print "Hello World")

现在我有了 io 命令(对象实例是“命令”的种类),带有方法 print(它从插槽 2 中读取),以及所述方法“Hello World”的参数。结果,如果我感觉功能正常,那将是一个打印 Hello World 的程序 - 如果不是,它会作为副作用执行此操作并返回错误代码或不返回任何内容。

然后我会围绕它编写一个环境来定义一些命令(包括“make object”),可能是某种引用语法(所以我可以定义 lambdas)等等。我最终会得到一种语言对一小部分 common lisp 的设计不佳、次优、受限的实现,这是传统的。

只有在我能够完成上述操作后,我才会考虑为 C/C++ 等更难解析的语言编写解析器。即便如此,我还是先将上面的玩具语言重写为一些词法分析/解析框架,然后在同一个框架中编写我的 C/C++ 类语言。

【讨论】:

    【解决方案2】:

    这就是你在 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

    【讨论】:

    • 我认为他正在尝试编写一个 C++ 程序,以另一种(可能是临时)语言解析和执行代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 2010-09-05
    • 1970-01-01
    • 2011-08-24
    • 2010-09-17
    相关资源
    最近更新 更多