【问题标题】:Python parse indented C file with unknown typesPython解析具有未知类型的缩进C文件
【发布时间】:2019-03-04 22:06:04
【问题描述】:

如何解析语法正确包含单个函数但具有未定义类型的 C 文件?该文件使用this service 自动缩进(4 个空格),每个块关键字下方都有括号,即类似

if ( condition1 )
{
    func1( int hi );
    unktype foo;
    do
    {
        if ( condition2 )
            goto LABEL_1;
    }
    while ( condition3 );
}
else
{
    float a = bar(baz, 0);
LABEL_1:
    int foobar = (int)a;
}

第一行是原型,第二行是“{”。所有行都以 \n 结尾。最后一行只是“}\n” 有很多多对一的 goto,标签通常不在他们的范围内(可怕,我知道 :D) 我只关心结构信息,即块和语句类型。这是我想要得到的(打印时,为清楚起见添加了缩进):

[If(condition = [condition1], 
    bodytrue = ["func1( int hi );", 
                "unktype foo;" 
                DoWhile(condition = [condition3], 
                        body = [
                                SingleLineIf(condition = [condition2],
                                             bodytrue =["goto LABEL_1;"], 
                                             bodyelse = []
                                )
                                ]
                )
    ]
    bodyelse = ["float a = bar(baz, 0);",
               "int foobar = (int)a;"
    ]
)]

带有条件 1、条件 2 和条件 3 字符串。其他构造也一样。 标签可以丢弃。我还需要包含与任何特殊语句无关的块,例如Block([...]). 由于未知类型,标准 C 语言 Python 解析器不起作用(例如 pycparser 给出语法错误)

【问题讨论】:

  • 您将不得不猜测,因为实际上不可能在这些约束下明确解析 C。通常可以做出相当不错的猜测,但您仍然需要猜测。
  • 例如,(a)&b 是按位运算还是指针转换?谁知道呢!
  • 考虑为此编写一个词法分析器。 en.wikipedia.org/wiki/Lexical_analysis.
  • 在 C 中写入空格字符可以被忽略,只要它们不在字符串中并且不分割标记。
  • 你到底在问什么?我的意思是,由于提供的代码不符合目前的 C 语言,因此现有的解析器拒绝它也就不足为奇了。因此,如果您需要解析它,那么您需要修改代码或准备自己的解析器。我怀疑你是后者,但在这种情况下,隐含的问题太宽泛了。

标签: python c parsing


【解决方案1】:

Pyparsing 包括 a simple C parser as part of its examples,这是一个解析器,它将处理您的示例代码,以及更多内容(包括对 for 语句的支持)。

不是一个非常好的 C 解析器。它广泛地刷过 if、while 和 do 条件,就像嵌套括号中的字符串一样。但它可能会让您开始提取您感兴趣的部分。

import pyparsing as pp

IF, WHILE, DO, ELSE, FOR = map(pp.Keyword, "if while do else for".split())
SEMI, COLON, LBRACE, RBRACE = map(pp.Suppress, ';:{}')

stmt_body = pp.Forward()
single_stmt = pp.Forward()
stmt_block = stmt_body | single_stmt

if_condition = pp.ungroup(pp.nestedExpr('(', ')'))
while_condition = if_condition()
for_condition = if_condition()

if_stmt = pp.Group(IF 
           + if_condition("condition") 
           + stmt_block("bodyTrue")
           + pp.Optional(ELSE + stmt_block("bodyElse"))
           )
do_stmt = pp.Group(DO 
           + stmt_block("body") 
           + WHILE 
           + while_condition("condition")
           + SEMI
           )
while_stmt = pp.Group(WHILE + while_condition("condition")
              + stmt_block("body"))
for_stmt = pp.Group(FOR + for_condition("condition")
            + stmt_block("body"))
other_stmt = (~(LBRACE | RBRACE) + pp.SkipTo(SEMI) + SEMI)
single_stmt <<= if_stmt | do_stmt | while_stmt | for_stmt | other_stmt
stmt_body <<= pp.nestedExpr('{', '}', content=single_stmt)

label = pp.pyparsing_common.identifier + COLON

parser = pp.OneOrMore(stmt_block)
parser.ignore(label)

sample = """
if ( condition1 )
{
    func1( int hi );
    unktype foo;
    do
    {
        if ( condition2 )
            goto LABEL_1;
    }
    while ( condition3 );
}
else
{
    float a = bar(baz, 0);
LABEL_1:
    int foobar = (int)a;
}
"""

print(parser.parseString(sample).dump())

打印:

[['if', 'condition1', ['func1( int hi )', 'unktype foo', ['do', [['if', 'condition2', 'goto LABEL_1']], 'while', 'condition3']], 'else', ['float a = bar(baz, 0)', 'int foobar = (int)a']]]
[0]:
  ['if', 'condition1', ['func1( int hi )', 'unktype foo', ['do', [['if', 'condition2', 'goto LABEL_1']], 'while', 'condition3']], 'else', ['float a = bar(baz, 0)', 'int foobar = (int)a']]
  - bodyElse: ['float a = bar(baz, 0)', 'int foobar = (int)a']
  - bodyTrue: ['func1( int hi )', 'unktype foo', ['do', [['if', 'condition2', 'goto LABEL_1']], 'while', 'condition3']]
    [0]:
      func1( int hi )
    [1]:
      unktype foo
    [2]:
      ['do', [['if', 'condition2', 'goto LABEL_1']], 'while', 'condition3']
      - body: [['if', 'condition2', 'goto LABEL_1']]
        [0]:
          ['if', 'condition2', 'goto LABEL_1']
          - bodyTrue: 'goto LABEL_1'
          - condition: 'condition2'
      - condition: 'condition3'
  - condition: 'condition1'

【讨论】:

  • 这看起来很有希望,真的很酷!几乎是我想要得到的。非常感谢保罗 :)
猜你喜欢
  • 1970-01-01
  • 2010-12-23
  • 2013-10-09
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多