java - 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_]+$/)
}
}
解决方案
我没有仔细看它,但是在检查了 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
推荐阅读
- javascript - axios 设置 x-www-form-urlencoded 不起作用
- java - 带有java的Swagger-UI - 模型没有在继承结构中生成
- java - OpenCV - 在视频和图像上查找黑板边缘
- ios - SwiftUI 中的导航 - 将应用程序设置导航视图流程转换为选项卡视图导航流程
- c# - 将自定义标头/cookie 添加到错误请求 (400) ASP.Net Core
- reactjs - 根目录 reactjs
- spring-boot - 如何避免使用 Spring Ssecurity 和 SAML 登录页面?
- json - Jinja2 - 列表中的缩进和递归循环
- reactjs - 寻找一种巧妙的方式来动态渲染多个子组件
- android - 将 java 本机包导入 react-native 项目