まあ、私はAPIで遊んだし、それほど難しいことでもありませんでした。状態が入力されたときに認識された文法の領域の前後に、すべての状態番号を文法ファイルのコピーに挿入するコードを次に示します。正直なところ、間隔がnullのときの意味がわからない。これは、およそ3分の1の州の場合のようです。
ファイルに挿入するコードは、xor_eq's answerからそのまま引き継がれています。答えるために時間を割いて
private static String GRAMMAR_FILE_NAME = "JavaSimple.g4";
private static String EDITED_GRAMMAR_FILE_NAME = "JavaSimple_edited.g4";
private static void insertStateNumbersIntoGrammar() throws IOException, RecognitionException {
copyGrammarFile();
// Load tokens
ANTLRInputStream input = new ANTLRFileStream(GRAMMAR_FILE_NAME);
ANTLRv4Lexer lexer = new ANTLRv4Lexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
// Load Grammar
String contents = new String(Files.readAllBytes(Paths.get(GRAMMAR_FILE_NAME)));
Grammar g = new Grammar(contents);
List<Insert> inserts = new ArrayList<Insert>();
boolean before = false;
for (ATNState state : g.atn.states) {
int stateNr = state.stateNumber;
Interval interval = g.getStateToGrammarRegion(stateNr);
if (interval != null) {
Token token = before ? tokens.get(interval.a) : tokens.get(interval.b);
int i = before ? token.getStartIndex() : token.getStopIndex() + 1;
String stateStr = "[" + stateNr + "]";
long insertSize = calcInsertLengthBefore(inserts, i);
insert(EDITED_GRAMMAR_FILE_NAME, i + insertSize, stateStr.getBytes());
inserts.add(new Insert(i, stateStr));
}
}
}
private static int calcInsertLengthBefore(List<Insert> inserts, int index) {
return inserts.stream()
.filter(insert -> insert.index < index)
.flatMapToInt(insert -> IntStream.of(insert.state.length()))
.sum();
}
private static void insert(String filename, long offset, byte[] content) throws IOException {
RandomAccessFile r = new RandomAccessFile(new File(filename), "rw");
RandomAccessFile rtemp = new RandomAccessFile(new File(filename + "~"), "rw");
long fileSize = r.length();
FileChannel sourceChannel = r.getChannel();
FileChannel targetChannel = rtemp.getChannel();
sourceChannel.transferTo(offset, (fileSize - offset), targetChannel);
sourceChannel.truncate(offset);
r.seek(offset);
r.write(content);
long newOffset = r.getFilePointer();
targetChannel.position(0L);
sourceChannel.transferFrom(targetChannel, newOffset, (fileSize - offset));
sourceChannel.close();
targetChannel.close();
}
private static void copyGrammarFile() {
File source = new File(GRAMMAR_FILE_NAME);
File target = new File(EDITED_GRAMMAR_FILE_NAME);
try {
Files.copy(source.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
private static class Insert {
final Integer index;
final String state;
Insert(int index, String state) {
this.index = index;
this.state = state;
}
}
ありがとう:
このコードの結果は次のようになります。 2番目の方法は、挿入するテキストの保存方法です。問題は、挿入するときに**を選択することです。私はあなたが間違っているのは、有効な入力だけを解析すると言っていると思います。 Antlr4はHoney Badgerと呼ばれ、あなたが与えるものは何でもかまいません)。そして、私は文法のその位置に一致する州の番号を得るためにユーザーが入力したところまで解析する必要があります。 – MyiEye
ええ、もしそれが唯一の必要ならば、ANTLRは実際にはあなたがそれをフィードしているが、適切であると思う方法でエラーノードを生成するので、それは動作する可能性があります。 – Raven
どのようにして国家番号を取得し、文法のどの部分を参照できるのか分かりますか? – MyiEye