Синтаксический анализ кода Python с неизвестными типами - PullRequest
0 голосов
/ 05 марта 2019

Как мне разобрать синтаксически правильный C файл, содержащий одну функцию, но с неопределенными типами ?Файл автоматически имеет отступ (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" Есть много переходов "многие-к-одному", и метки часто выходят из своего блока (ужасно, я знаю: 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([...]). Стандартный синтаксический анализатор языка Python C не работает (например, pycparser выдает синтаксическую ошибку) из-за неизвестных типов

1 Ответ

0 голосов
/ 05 марта 2019

Pyparsing включает простой синтаксический анализатор C как часть его примеров , вот парсер, который обработает ваш пример кода, и немного больше (включает поддержку for операторов).

Это , а не очень хороший C-парсер.Он распространяется широко, если, в то время, и делает условия как просто строки во вложенных скобках.Но это может дать вам начало извлечения интересующих вас битов.

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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...