我正在用 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(),但上面的代碼對于您的要求可能是最簡單的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/387074.html
