用于c ++的“简单”解析器

时间:2012-09-13 03:16:15

标签: c++ regex parsing compiler-construction sed

我有一个项目(SCC),有点像REPL for C ++。在丛林提示我可以做

scc '2+2'

或者稍微复杂一点:

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

相当于:

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

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

下面是我当前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

cat之后的第一行 - 换行为空行。第二行是一个空行。 第3条 - 未以';'终止的陈述 - 应打印出来。 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 ++ 解析器。这只是一个快速的黑客只做一件事:解析最后的声明。它是 能够进行以上所有单元测试。但不幸的是,对于更长的片段而言 无法忍受的慢。

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

1 个答案:

答案 0 :(得分:1)

  

正确的方法可能是使用真正的解析器(来自   像CLANG这样的东西)但我有点担心复杂性   这项努力

高。简单的事实是C ++就像HTML一样 - 你需要一个真正的库才能做到这一点,所以除非你想花费数年时间开发自己的,否则几乎唯一的方法就是使用现有的C ++解析器。 Clang是这方面唯一的选择。无论你找到它多么复杂,你别无选择。