首页 > 解决方案 > ANTLR4 如何提取 python 表达式变量

问题描述

使用以下 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 && this.verifyIsVariable(text)) {
            this.variables.push(text)
        }
    }

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

标签: javapythonvariablesantlr4

解决方案


我没有仔细看它,但是在检查了 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 repo 中:https ://github.com/bkiers/python3-parser/blob/master/src/main/java/ nl/bigo/pythonparser/Builder.java


推荐阅读