拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何在antlr4中获取多个命令?

如何在antlr4中获取多个命令?

白鹭 - 2022-02-10 2166 0 0

我正在用 Java 开发一个 shell 实作,我正在使用 antlr4 来决议语法。我想一一决议输入的命令,并将它们存盘在一个阵列串列中,稍后我将在其中执行这些命令。

例如,“echo hello; echo world”的输入应该回传两个 Call 物件的阵列串列。如果有帮助,Call 物件代表一个简单的命令。

但是,visitChildren 方法的回传值正在被最新决议的命令覆写。如何决议一个命令,将其添加到我的阵列串列中,然后继续决议下一个命令等等?

命令转换器.java

package parse;

import java.util.ArrayList;

import app.ApplicationFactory;
import shell.ShellGrammarBaseVisitor;
import shell.ShellGrammarParser;

public class CommandConverter extends ShellGrammarBaseVisitor<Command> {
    
    ApplicationFactory appFactory = new ApplicationFactory();

    @Override
    public Command visitCommands(ShellGrammarParser.CommandsContext ctx) {
        //ArrayList<Command> commands = new ArrayList<>();
        return visitChildren(ctx);
    }
    @Override
    public Command visitAtomicCommand(ShellGrammarParser.AtomicCommandContext ctx) {
        int childCount = ctx.getChildCount();
        String appName = ctx.getChild(0).getText();
        ArrayList<String> appArgs = new ArrayList<>();
        if(childCount > 1) {
            for (int i = 1; i < childCount; i  ) {
                appArgs.add(ctx.getChild(i).getText());
            }
        }
        return new Call(appFactory.getApplication(appName), appArgs);
    }
}

ShellGrammar.g4(部分)

grammar ShellGrammar;

/*
 * Parser Rules
 */

commands : atomicCommand (';' atomicCommand )*

atomicCommand : NONSPECIAL (value)*;

value : (NONSPECIAL | DOUBLEQUOTED | SINGLEQUOTED);

/*
 * Lexer Rules
 */
NONSPECIAL : ~['";\r\n\t ] ;
DOUBLEQUOTED : '"' (~'"')* '"';
SINGLEQUOTED : '\'' (~'\'')* '\'';

WHITESPACE : [\r\n\t ]  -> skip ;

uj5u.com热心网友回复:

如果你大声读出来,这个定义没有多大意义:

public Command visitCommands(ShellGrammarParser.CommandsContext ctx) {

您正在访问,commands但希望得到Command回报??

在这个简单的例子中,最好记住访问者不需要处理访问每个背景关系型别(这对于完整语法来说非常罕见,因为找到适用于所有节点的公共回传型别被证明是困难的) . 您可以只覆写您实际打算访问的 Context 型别的方法。

在你的情况下,commands你是“顶级”规则,所以你从你的决议中回传的决议树节点(使用parser.commands();呼叫)将是一个CommandsContext

你可以做一些类似于:(pt你从决议中得到的节点在哪里。)

  for (AtomicCommandContext child : pt.children) {
   // handle the child command
   // could be adding it to a list
   // could be just processing the command 
  }

命令的好处是您负责为每个孩子呼叫访问者。 visitChildren只是一个方便的方法,它遍历所有为您呼叫访问者的孩子。

Visitor如果您想让访问者List<Command>从呼叫中回传 a,您可以覆写类中的一些方法visitChildren(),但上面的代码对于您的要求可能是最简单的。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *