LALR 解析:从生成的解析表中检索语法规则

逆向工程 反编译
2021-06-28 23:38:53

我有一个相当古老的 C 公司解析器/编译器代码,它是从古老的 Yacc 生成的,原始语法源丢失了(作为中间文件),ytab.c解析器生成的文件的唯一结果这段遗留代码需要修改,但我无法从头开始重新编码。

通过“古老的 Yacc”,我的意思是解析器正在使用名为yyact, yypact, yypgo, yyr1, yyr2, yytoks, yyexca, yychk, 的表yydef

是否可以通过推导解析表来机械地检索/重新生成解析规则以重建语法?

我可以使用相同的古老 Yacc 处理的表达式解析器的小样本示例:

yytabelem yyexca[] ={
-1, 1,
    0, -1,
    -2, 0,
-1, 21,
    261, 0,
    -2, 8,
    };
yytabelem yyact[]={

    13,     9,    10,    11,    12,    23,     8,    22,    13,     9,
    10,    11,    12,     9,    10,    11,    12,     1,     2,    11,
    12,     6,     7,     4,     3,     0,    16,     5,     0,    14,
    15,     0,     0,     0,    17,    18,    19,    20,    21,     0,
     0,    24 };
yytabelem yypact[]={

  -248, -1000,  -236,  -261,  -236,  -236, -1000, -1000,  -248,  -236,
  -236,  -236,  -236,  -236,  -253, -1000,  -263,  -245,  -245, -1000,
 -1000,  -249, -1000,  -248, -1000 };
yytabelem yypgo[]={

     0,    17,    24 };
yytabelem yyr1[]={

     0,     1,     1,     1,     2,     2,     2,     2,     2,     2,
     2,     2,     2 };
yytabelem yyr2[]={

     0,     8,    12,     0,     6,     6,     6,     6,     6,     6,
     4,     2,     2 };
yytabelem yychk[]={

 -1000,    -1,   266,    -2,   259,   263,   257,   258,   267,   262,
   263,   264,   265,   261,    -2,    -2,    -1,    -2,    -2,    -2,
    -2,    -2,   260,   268,    -1 };
yytabelem yydef[]={

     3,    -2,     0,     0,     0,     0,    11,    12,     3,     0,
     0,     0,     0,     0,     0,    10,     1,     4,     5,     6,
     7,    -2,     9,     3,     2 };

yytoktype yytoks[] =
{
    "NAME", 257,
    "NUMBER",   258,
    "LPAREN",   259,
    "RPAREN",   260,
    "EQUAL",    261,
    "PLUS", 262,
    "MINUS",    263,
    "TIMES",    264,
    "DIVIDE",   265,
    "IF",   266,
    "THEN", 267,
    "ELSE", 268,
    "LOW",  269,
    "UMINUS",   270,
    "-unknown-",    -1  /* ends search */
};

我想找回

stmt    : IF exp THEN stmt
        | IF exp THEN stmt ELSE stmt
        | /*others*/
        ;

exp     : exp PLUS exp
        | exp MINUS exp
        | exp TIMES exp
        | exp DIVIDE exp
        | exp EQUAL exp
        | LPAREN exp RPAREN
        | MINUS exp
        | NAME
        | NUMBER
        ;

此示例的完整解析器可用作 gist,它显示一个yyreds包含规则表作为调试信息,该信息不在我试图反转的解析器中。

注意:我以前在 SO 上问过这个问题,并被建议在 RE 中问它。有什么帮助吗?

PS:我不熟悉 RE 问题标签,请随时更正。

1个回答

我没有实际的答案。我听说过一些关于这样做的工具的传言,但没有看到任何具体的东西。但是,我找到了一个应该非常有用的页面:

理解 GNU Bison 生成的 C 解析器

本文档试图描述 Bison 2.3 生成的 C 中 LALR(1) 解析器的实现。我使用了一个简单的语法来演示解析器的工作和解析表的性质。您还会发现这些表格与 Aho、Sethi 和 Ullman 合着的畅销书“编译器 - 原理、技术和工具”(也称为“龙之书”)和许多其他关于编译器设计的书籍中给出的未压缩表格方案的比较.

在这里看到它

编辑:找到了一个声称可以做到的脚本!

http://nah6.com/~itsme/cvs-xdadevtools/perlutils/yydecode.pl

但是,它似乎旨在与另一组表格一起使用。不过,它可能对开始有用。