ANTLR4 Как мне извлечь переменные выражения python

#java #python #variables #antlr4

#java #python #переменные #antlr4

Вопрос:

Используя следующую грамматику ANTLR: https://github.com/bkiers/python3-parser/blob/master/src/main/antlr4/nl/bigo/pythonparser/Python3.g4 Я хочу провести синтаксический анализ из заданного выражения, скажем:

 x.split(y, 3)
 

или

 x   y
 

Переменные x и y. Как бы мне этого добиться?

Я попробовал следующий подход, но он кажется громоздким, поскольку я должен добавить все встроенные функции python:

Определите интерфейс прослушивателя

 const listener = new MyPythonListener()
antlr.tree.ParseTreeWalker.DEFAULT.walk(listener, abstractTree)
 

Используйте регулярное выражение сопоставление с шаблоном:

 const symbolicNames = ['TRUE', 'FALSE', 'NUMEBRS', 'STRING', 'LIST', 'TUPLE', 'DICTIONARY', 'INT', 'LONG', 'FLOAT', 'COMPLEX',
'BOOL', 'STR', 'INT', 'RANGE', 'NONE', 'LEN']

class MyPythonListener extends Python3Listener {
    variables = []

    enterExpr(ctx) {
        const text = this.getElementText(ctx)
        if (text amp;amp; this.verifyIsVariable(text)) {
            this.variables.push(text)
        }
    }

    verifyIsVariable(leafText) {
        return !leafText.includes('"') amp;amp; !leafText.includes(''') amp;amp; isNaN(leafText) amp;amp;
            !symbolicNames.includes(leafText.toUpperCase()) amp;amp; leafText.match(/^[0-9a-zA-Z_] $/)
    }
}
 

Комментарии:

1. Вы не можете использовать эту грамматику для извлечения переменных. Вы можете создать грамматику ANTLR на основе грамматики / спецификации, с которой вы связались, а затем использовать эту грамматику ANTLR для извлечения переменных. Грамматика ANTLR, скорее всего, не является переводом спецификации 1 к 1, поэтому ответа на ваш вопрос нет, если вы не видите грамматику ANTLR. Итак, не могли бы вы опубликовать свою грамматику ANTLR?

2. Кстати, может быть проще использовать собственный пакет синтаксического анализа / ast Python для извлечения таких вещей из кода Python: docs.python.org/3/library/ast.html

3. Спасибо за ответ, это грамматика ANTLR, которую я использую: github.com/bkiers/python3-parser — спасибо, что поделились этим как открытым исходным кодом

4. Пожалуйста. В README в этом репозитории я ссылаюсь на класс, который дает пример, как извлекать вещи из дерева синтаксического анализа. Не могли бы вы отредактировать свой собственный вопрос и добавить то, что вы пробовали сами?

5. @BartKiers Я отредактировал вопрос и добавил один подход, который я попробовал, используя прослушиватель сопоставление с образцом. Я также попробовал другой вариант, создав упрощенное дерево и получив листья, но это не выглядит многообещающим, любое предложение о том, как бы вы решили такую проблему, приветствуется, поскольку у меня недостаточно опыта, чтобы начать что-то многообещающее, и я нигде не могу найти подходящее руководство. Спасибо!

Ответ №1:

Я не смотрел на это слишком внимательно, но после проверки дерева синтаксического анализа кода Python:

 def some_method_name(some_param_name):
    x.split(y, 3)
 

похоже, что имена переменных являются дочерними элементами правила atom:

 atom
 : '(' ( yield_expr | testlist_comp )? ')' 
 | '[' testlist_comp? ']'  
 | '{' dictorsetmaker? '}' 
 | NAME 
 | number 
 | str  
 | '...' 
 | NONE
 | TRUE
 | FALSE
 ;
 

где NAME имя переменной.

Итак, вы могли бы сделать что-то вроде этого:

 String source = "def some_method_name(some_param_name):n    x.split(y, 3)n";
Python3Lexer lexer = new Python3Lexer(CharStreams.fromString(source));
Python3Parser parser = new Python3Parser(new CommonTokenStream(lexer));

ParseTreeWalker.DEFAULT.walk(new Python3BaseListener() {
    @Override
    public void enterAtom(Python3Parser.AtomContext ctx) {
        if (ctx.NAME() != null) {
            System.out.println(ctx.NAME().getText());
        }
    }
}, parser.file_input());
 

который будет печатать:

 x
y
 

а не имена методов и параметров.

Опять же: не тщательно протестировано, я оставляю это для вас. Вы можете довольно распечатать дерево синтаксического анализа следующим образом:

 String source = "def some_method_name(some_param_name):n    x.split(y, 3)n";
Python3Lexer lexer = new Python3Lexer(CharStreams.fromString(source));
Python3Parser parser = new Python3Parser(new CommonTokenStream(lexer));

System.out.println(new Builder.Tree(source).toStringASCII());
 

чтобы самостоятельно проверить, где в дереве синтаксического анализа находятся интересующие вас узлы. Приведенный выше код будет напечатан:

 '- file_input
   |- stmt
   |  '- compound_stmt
   |     '- funcdef
   |        |- def
   |        |- some_method_name
   |        |- parameters
   |        |  |- (
   |        |  |- typedargslist
   |        |  |  '- tfpdef
   |        |  |     '- some_param
   |        |  '- )
   |        |- :
   |        '- suite
   |           |- <NEWLINE>
   |           |- <INDENT>
   |           |- stmt
   |           |  '- simple_stmt
   |           |     |- small_stmt
   |           |     |  '- expr_stmt
   |           |     |     '- testlist_star_expr
   |           |     |        '- test
   |           |     |           '- or_test
   |           |     |              '- and_test
   |           |     |                 '- not_test
   |           |     |                    '- comparison
   |           |     |                       '- star_expr
   |           |     |                          '- expr
   |           |     |                             '- xor_expr
   |           |     |                                '- and_expr
   |           |     |                                   '- shift_expr
   |           |     |                                      '- arith_expr
   |           |     |                                         '- term
   |           |     |                                            '- factor
   |           |     |                                               '- power
   |           |     |                                                  |- atom
   |           |     |                                                  |  '- x
   |           |     |                                                  |- trailer
   |           |     |                                                  |  |- .
   |           |     |                                                  |  '- split
   |           |     |                                                  '- trailer
   |           |     |                                                     |- (
   |           |     |                                                     |- arglist
   |           |     |                                                     |  |- argument
   |           |     |                                                     |  |  '- test
   |           |     |                                                     |  |     '- or_test
   |           |     |                                                     |  |        '- and_test
   |           |     |                                                     |  |           '- not_test
   |           |     |                                                     |  |              '- comparison
   |           |     |                                                     |  |                 '- star_expr
   |           |     |                                                     |  |                    '- expr
   |           |     |                                                     |  |                       '- xor_expr
   |           |     |                                                     |  |                          '- and_expr
   |           |     |                                                     |  |                             '- shift_expr
   |           |     |                                                     |  |                                '- arith_expr
   |           |     |                                                     |  |                                   '- term
   |           |     |                                                     |  |                                      '- factor
   |           |     |                                                     |  |                                         '- power
   |           |     |                                                     |  |                                            '- atom
   |           |     |                                                     |  |                                               '- y
   |           |     |                                                     |  |- ,
   |           |     |                                                     |  '- argument
   |           |     |                                                     |     '- test
   |           |     |                                                     |        '- or_test
   |           |     |                                                     |           '- and_test
   |           |     |                                                     |              '- not_test
   |           |     |                                                     |                 '- comparison
   |           |     |                                                     |                    '- star_expr
   |           |     |                                                     |                       '- expr
   |           |     |                                                     |                          '- xor_expr
   |           |     |                                                     |                             '- and_expr
   |           |     |                                                     |                                '- shift_expr
   |           |     |                                                     |                                   '- arith_expr
   |           |     |                                                     |                                      '- term
   |           |     |                                                     |                                         '- factor
   |           |     |                                                     |                                            '- power
   |           |     |                                                     |                                               '- atom
   |           |     |                                                     |                                                  '- number
   |           |     |                                                     |                                                     '- integer
   |           |     |                                                     |                                                        '- 3
   |           |     |                                                     '- )
   |           |     '- <NEWLINE>
   |           '- <DEDENT>
   '- <EOF>
 

Обратите внимание, что Builder.Tree класс не является частью библиотеки ANTLR, он находится в репозитории / my, на который вы ссылались в своем вопросе: https://github.com/bkiers/python3-parser/blob/master/src/main/java/nl/bigo/pythonparser/Builder.java