在Python中使用ANTLR4解析数学表达式

5jvtdoz2  于 2023-03-11  发布在  Python
关注(0)|答案(1)|浏览(156)

我是ANTLR4的新手,我正在尝试使用ANTLR解析Python中的分数表达式,然后将它们更改为Python可以理解的结构。使用ANTLR而不是regex的主要原因是嵌套模式的递归。
在我的例子中,分数的结构是\\frac{a}{b},我想要的格式是(a/b)。已经有类似的项目做过,比如latex2symy,但我正在努力理解它是如何工作的。
解析器可以在python中找到匹配项。例如,对于\frac{1}{2},它返回(result_ (expr (fraction \frac { 1 } { 2 })))。结果来自一个“树”,我可以提取它的一部分,如数字(1和2),然后用(1/2)的形式替换它们吗?
下面是我生成的语法文件:

grammar frac_gram;

options{
    language=Python3;
}

/*
 * Parser Rules
 */

result_    :   expr+ ;
expr       :   fraction;

integer :   INT;
fraction:   FRAC L_BRACE integer R_BRACE L_BRACE integer R_BRACE;

/*
 * Lexer Rules
 */

FRAC:  '\\frac';
L_BRACE: '{';
R_BRACE: '}';
INT :   [0-9]+ ;         // match integers
WS  :   [ \t]+ -> skip ; // toss out whitespace

Python代码:

import sys
from antlr4 import *
from antlr4.InputStream import InputStream
from frac_gram_grammarLexer import frac_gram_grammarLexer
from frac_gram_grammarParser import frac_gram_grammarParser
from frac_gram_grammarVisitor import frac_gram_grammarVisitor

def main(argv):
    input_stream = InputStream(argv)
    lexer = frac_gram_grammarLexer(input_stream)
    token_stream = CommonTokenStream(lexer)
    parser = frac_gram_grammarParser(token_stream)

    tree = parser.result_()

    lisp_tree_str = tree.toStringTree(recog=parser)
    print(lisp_tree_str)

    visitor = frac_gram_grammarVisitor()
    visitor.visit(tree)

if __name__ == '__main__':
    main('\\frac{1}{2}')
vm0i2vca

vm0i2vca1#

经过大量的搜索,我发现解决办法是命名语法文件中的分子和分母部分,即。

fraction:   FRAC L_BRACE upper=integer R_BRACE L_BRACE lower=integer R_BRACE;

因此,我将分子命名为upper,将分母命名为lower,然后在ANTLR解析器根据其属性对其进行解析后,可以在Python中提取它

def convert_fraction(result_of_parser):
   #print(result_of_parser.toStringTree())
   numerator_ = result_of_parser.upper
   denominator_ = result_of_parser.lower
   return sympy.Mul(numerator_ , sympy.Pow(denominator_ , -1, evaluate=False), evaluate=False)

相关问题