首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在antlr4中获得多个命令?

如何在antlr4中获得多个命令?
EN

Stack Overflow用户
提问于 2021-12-13 19:17:01
回答 1查看 90关注 0票数 0

我正在用Java开发一个shell实现,并使用antlr4解析语法。我希望一个一个地解析输入命令,并将它们存储在一个数组中,稍后我将在其中执行这些命令。

例如,"echo hello;echo world“的输入应该返回由两个调用对象组成的数组。如果有帮助,则调用对象表示一个简单的命令。

但是,visitChildren方法的返回值正在被最新解析的命令覆盖。我如何解析一个命令,将它添加到我的数组列表中,然后继续解析下一个命令等等?

CommandConverter.java

代码语言:javascript
运行
复制
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 (部分)

代码语言:javascript
运行
复制
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 ;
EN

Stack Overflow用户

回答已采纳

发布于 2021-12-13 20:09:24

如果你大声读出来,这个定义就没什么意义了:

代码语言:javascript
运行
复制
public Command visitCommands(ShellGrammarParser.CommandsContext ctx) {

你正在访问commands,但希望得到Command作为回报??

在这个简单的例子中,最好记住访问者不需要处理访问每种上下文类型(这对于一个完整的语法是非常罕见的,因为找到一个适用于所有节点的通用返回类型是很困难的)。您只需重写实际要访问的上下文类型的方法。

在您的例子中,commands是您的“顶级”规则,因此您从解析中得到的解析树节点(使用parser.commands();调用)将是一个CommandsContext

您可以做一些类似于:(其中pt是从解析中得到的节点)。

代码语言:javascript
运行
复制
  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>,可以重写List<Command>类中的一些方法,但是上面的代码可能是您所要求的最简单的代码。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70339829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档