1

我有一个项目(SCC),它有点像 C++ 的 REPL。在布什提示我可以做

scc '2+2'

或者更复杂一点:

scc  'double x = 0.5;  sin(x)'

这相当于:

scc  'double x = 0.5;  cout << sin(x) << endl;'

如果最后一个(也是唯一可能的)语句表达式没有以分号终止,则将其发送到std::cout. 我的问题是关于从 C++ 代码片段中解析出最后一条语句。我很清楚 C++ 解析有多么困难。用简单的 sed 脚本通过查找 last 来解析 last 语句';'最初对我来说已经足够了。但是现在项目比小型个人项目大,我需要一个更好的解析器。

下面是我当前 SED 解析器的迷你单元测试。您可以看到我用来进行解析的 SED 正则表达式:

    cat  <<EOF  | sed    's/$//;s/[ \t]*$//;s/\(.*[;}]\)*\([^;}]\+$\)/\0    ==>>  \1   PRINT(\2);/'


    print
    no-print;
    OK;  print
    OK;  no-print;
    OK;  no-print;  print
    FAIL;   while(a){b;}  no-print
    FAIL;   while(a)  no-print
    OK;     for(a;b;c) {no-print}
    FAIL;   for(a;b;c) no-print
    OK;     {}
    OK;     {no-print-code-block;}
    FAIL;  print_rvalue_t{1}
    FAIL;   f(int{1})
    FAIL;   f(";")
    FAIL;   f(';')
    FAIL;   f("}")
    EOF

-line之后的第一行cat是空行。第二行是一个空格线。3rd - 不以 - 结尾的语句';'应该被打印出来。第 4 - 2 语句片段。等等。如果有FAIL- 解析器将在这一行失败。输出如下所示:

    print   ==>>     PRINT(print);
    no-print;
    OK;  print      ==>>  OK;   PRINT(  print);
    OK;  no-print;
    OK;  no-print;  print   ==>>  OK;  no-print;   PRINT(  print);
    FAIL;     while(a){b;}  print     ==>>  OK;       while(a){b;}   PRINT(  no-print);
    FAIL;   while(a)  no-print      ==>>  FAIL;   PRINT(    while(a)  no-print);
    OK;     for(a;b;c) {no-print}
    FAIL;   for(a;b;c) no-print     ==>>  FAIL;     for(a;b;   PRINT(c) no-print);
    OK;     {}
    OK;     {no-print-code-block;}
    FAIL;  print_rvalue_t{1}
    FAIL;   f(int{1})       ==>>  FAIL;     f(int{1}   PRINT());
    FAIL;   f(";")  ==>>  FAIL;     f(";   PRINT("));
    FAIL;   f(';')  ==>>  FAIL;     f(';   PRINT('));
    FAIL;   f("}")  ==>>  FAIL;     f("}   PRINT("));

没有==>>标记的行是未经修改就通过解析器的行。在标记被转换后的片段,最后一条语句被包裹在PRINT( ). 如您所见,当前的 SED 解析器不是很好。

所以我正在寻找更好的东西。即使解析时不是 100% 正确,我也会接受答案。更好的 SED 脚本对我来说已经足够了。正确的做法可能是使用真正的解析器(来自 CLANG 之类的东西),但我有点担心这项工作的复杂性。

我试图在 boost/xpressive - http://github.com/lvv/scc/blob/master/sccpp.h中编写一个解析器。当然,它不是真正的 C++ 解析器。这只是为了一件事而做的快速破解:解析最后一条语句。它能够完成上述所有单元测试。但不幸的是,对于较长的片段,它的速度非常慢。

问题是:如何制作更好的解析器?

4

1 回答 1

1

正确的做法可能是使用真正的解析器(来自像 CLANG 之类的东西),但我有点担心这项工作的复杂性

不算太高。一个简单的事实是,C++ 就像 HTML——你需要一个真正的库来完成它,所以除非你想花费数年时间开发自己的库,否则几乎唯一的方法就是使用现有的 C++ 解析器。在这方面,Clang 是唯一的选择。因此,无论您发现它多么复杂,您都别无选择。

于 2012-09-13T10:41:41.110 回答