java - 使用 ANTLR4 检查嵌套函数中数组的最大出现次数

标签 java antlr antlr4

我有以下语法文件用于解析嵌套函数。

语法:

grammar FunctionTokenizer;

parse     : function* EOF;
function  : ID '(' expr_list? ')';
expr_list : expr (',' expr)*;
expr      : expr subscript | function | STRING | NUMBER | ID;
subscript : '[' expr? ']';

STRING    : '"' ~'"'* '"';
NUMBER    : [0-9]+ ('.' [0-9]+)?;
ID        : [a-zA-Z_] [a-zA-Z_0-9]*;
SPACES    : [ \t\r\n]+ -> skip;

输入失败,因为它有方括号。我将词法分析器的正则表达式更改为:

ID        : [a-zA-Z_] [a-zA-Z_0-9\\[\\]]*;

但它给出了错误。

输入:

split(mul(add(input["data"][0]["name"][]["node"],input["data"][0]),input["data"][0]["name"][]["node"][]),",")

对于上面的输入,我正在检查哪个参数具有最大括号 [](empty) 或 [0-9] 方括号,数字忽略那些具有单引号和双引号的数字,例如 [ "1234"]['data']

对于上述输入最大数组为:3,因为参数 input["data"][0]["name"][]["node"][] 具有最大数组。

因此,我正在尝试实现访问者模式实现,但表达式列表未到达 visitExpr_list 方法。

以下是该项目的 GitHub 链接:

https://github.com/VIKRAMAS/CheckMaxArrayInNestedFunction/tree/master

VisitorImplementation 类:

public class FunctionValidateVisitorImpl  extends FunctionTokenizerBaseVisitor<String>  {


    @Override
    public String visitParse(FunctionTokenizerParser.ParseContext ctx) {
        ParseTree name = ctx.getChild(2);
        String visit = visit(name);
        System.err.println("visit1:::::::::::"+visit);
        return visit(name);
    }


    @Override
    public String visitFunction(FunctionTokenizerParser.FunctionContext ctx) {
        ParseTree name = ctx.getChild(2);
        String visit = visit(name);
        System.err.println("visit2:::::::::::"+visit);
        return visit;
    }


    @Override
    public String visitExpr_list(FunctionTokenizerParser.Expr_listContext ctx) {
        String s="";
        for (int i = 0; i < ctx.getChildCount(); i+=2) {
        if(ctx.getChild(i) instanceof FunctionTokenizerParser.Expr_listContext ) {
            String g=visit(ctx.getChild(i));
            System.err.println("visit3:::::::::::if "+i+"    "+g);
            s=s+g;
        }
        else {
            System.err.println("visit4:::::::::::else  "+i+"    "+ctx.getChild(i).getText());
            s=s+ctx.getChild(i).getText();
        }
        }
        return s;
    }


    public String visitSubscript(FunctionTokenizerParser.SubscriptContext ctx) {
        System.err.println("visit5:::::::::::");
        String s="";
        for (int i = 0; i < ctx.getChildCount(); i++) {
        if(ctx.getChild(i) instanceof FunctionTokenizerParser.SubscriptContext) {
            String g=visit(ctx.getChild(i));
            s=s+g;
        }
        else {
            s=s+ctx.getChild(i).getText();
        }
        }
        return s;
    }


    @Override
    public String visitExpr(FunctionTokenizerParser.ExprContext ctx) {
        System.err.println("visit6:::::::::::");
        String s="";
        for (int i = 0; i < ctx.getChildCount(); i++) {
            if(ctx.getChild(i) instanceof TerminalNodeImpl ) {
                s=s+ctx.getChild(i).getText();
            }
            else {
                String g=visit(ctx.getChild(i));

                s=s+g;
            }
        }

        return s;
    }



}

测试类:

public class FunctionValidate {


    public static void main(String[] args) {
        try {
            String input = "mul(add(input[\"data\"][0][\"name\"][][\"node\"],input[\"data\"][0]),input[\"data\"][0][\"name\"][][\"node\"][])";
            ANTLRInputStream str = new ANTLRInputStream(input);
            FunctionTokenizerLexer lexer = new FunctionTokenizerLexer(str);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            FunctionTokenizerParser parser = new FunctionTokenizerParser(tokens);
            parser.removeErrorListeners(); // remove ConsoleErrorListener 
            parser.addErrorListener(new VerboseListener());
             FunctionContext tree = parser.function();
            FunctionValidateVisitorImpl visitor = new FunctionValidateVisitorImpl();
            visitor.visit(tree);
            System.out.println("-->"+tree.toStringTree( parser ));
            AST ast=new AST(tree);
            System.out.println( "Improved ParseTree:\n" + ast.toString() );
            JFrame frame = new JFrame("Antlr AST");
            JPanel panel = new JPanel();
            TreeViewer viewr = new TreeViewer(Arrays.asList(
            parser.getRuleNames()),tree);
            viewr.setScale(1.5);
            panel.add(viewr);
            frame.add(panel);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(500,500);
            frame.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }



}

enter image description here

访问者实现对一个参数有效,但如果我传递多个参数,它就会失败。 输入:

split(rrr(test(input[\"data\"][0]),input[\"data\"]),input[\"data\"])[]

输出:

visit4:::::::::::else  0    rrr(test(input["data"][0]),input["data"])
visit4:::::::::::else  2    input["data"]
visit2:::::::::::rrr(test(input["data"][0]),input["data"])input["data"]

在表达式列表方法之后,直接执行else循环,但它应该调用visit方法。表达式列表条件实例失败,因此方法调用直接到达 else。

最佳答案

对于像 bar["foo"] 这样的输入,["foo"] 不是您想要粘贴到 bar 中的内容你的词法分析器。这是解析器应该将其识别为表达式的内容。

像这样怎么样:

expr      : expr subscript | function | STRING | NUMBER | ID;
subscript : '[' expr? ']';

这也将匹配 foo()[42]。如果您只想匹配下标前面的标识符,请将expr下标更改为ID下标

关于java - 使用 ANTLR4 检查嵌套函数中数组的最大出现次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61235587/

相关文章:

exception-handling - Antlr 错误/异常处理

java - 使用监听器的 ANTLR 4 解释器

java - 从线程中干净地退出。

java - JOption 上的变量显示 2 次

java - 获取 Antlr 规则的原始文本

c++ - 我如何在 Antlr4 的解析树中检测空格?

parsing - ANTLR4:导入和 tokenVocab 之间有什么区别吗?

javascript - 如何将 jsonobject 传递给 html 文件

Java InputStream 自动拆分套接字消息

gradle - 构建时如何确保在编译之前生成代码?