为C实现fork-merge解析器

时间:2014-09-02 21:18:25

标签: refactoring automated-refactoring

我正在尝试使用Java为C实现fork-merge解析器。每当我找到#if指令时,我都需要分叉解析器。例如:

  

int x = #if 3; #else 4; #ENDIF

上述陈述应解析如下:

首先我为#if创建一个新的解析器并在#if语句下读入所有内容,在上面的例子中,直接读取值3会抛出语法错误,在这种情况下我应该读回所有已经存在的标记读。我该怎么做?

1 个答案:

答案 0 :(得分:0)

好吧,您可以使用任何标准解析器,并在遇到#if时复制其状态。然后一个版本沿#if的分支下移,另一个版本沿着#else的分支。 (没有#else?假装你看到#if cond lexemes #else #endif)。

如果预处理器条件不会出现在不错的地方,那么生活就会变得混乱:

    void p()
    {   if (x<2)
         { y =
    #if cond
       3; } else { x=
    #else
        7;
    #endif
    }

解析可以在每个条件子部分的末尾以完全不同的状态结束。结果是:您需要扩展预处理器条件,以便它们包含干净的语言结构。

这种方法的一个严重问题是,如果你每次看到#if时都会进行分叉,那么你最终会得到N ^ ifs的2 ^ N分叉。很容易找到包含数十个条件的C代码; 2 ^ 24 - &gt; 1600万,所以这快速失控。

所以当你点击#endif时,你需要一种方法将合并再次解析回来。这并不容易;我们用GLR解析器完成了这个,但答案非常复杂,并且在这里不容易适应。本技术论文讨论了如何为LR解析器执行此合并:http://www.lirmm.fr/~ducour/Doc-objets/ECOOP2012/PLDI/pldi/p323.pdf

还有第二个并发症:想象

     #if  cond1
         stuff1
     #else
     #if cond2
         stuff4
     #else
         stuff5
     #endif
     #endif

现在你需要在解析器中分叉解析器。更糟糕的是,stuff4有一个条件,它是cond1和cond2的结合,但stuff5具有cond1和cond2的条件。 ~cond2。实际上,您需要计算并保留每个解析(和生成的子树)出现的条件。您需要进行某种符号条件计算才能执行此操作,并且您需要特别处理组合条件完全错误的情况(只需跳过内容)。有趣的是,我们的GLR解决方案和上述技术论文都同意使用BDD这是一个好主意。

如果你想进行重构,你需要在有条件的情况下确定名称的含义:

     #if cond1
        float x;
     #else
        char* x;
     #endif

     ...
     x=
     #if cond1
       3.7
     #else
       "foobar"
     #endif
     ;

这需要具有带符号的条件信息的符号表。有关如何处理此问题的详细信息,请参阅我的技术文章http://www.rcost.unisannio.it/mdipenta/papers/scam2002.pdf

要进行重构,您需要在所有这些之上进行控制和数据流分析。

查看我的bio以获取我们试图完成所有这些工具的工具。我们认为,我们已经完成了条件解析部分。剩下的还在空中。