Allow XPath matching by literal or symbolic name (fixes #579)
This commit is contained in:
parent
0be4a3aaeb
commit
35bbdfb65c
|
@ -38,6 +38,7 @@ import org.antlr.v4.runtime.misc.Nullable;
|
|||
import org.antlr.v4.runtime.misc.Utils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
@ -46,8 +47,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
|
||||
public static final int EOF=-1;
|
||||
|
||||
private static final Map<String[], Map<String, Integer>> tokenTypeMapCache =
|
||||
new WeakHashMap<String[], Map<String, Integer>>();
|
||||
private static final Map<Vocabulary, Map<String, Integer>> tokenTypeMapCache =
|
||||
new WeakHashMap<Vocabulary, Map<String, Integer>>();
|
||||
private static final Map<String[], Map<String, Integer>> ruleIndexMapCache =
|
||||
new WeakHashMap<String[], Map<String, Integer>>();
|
||||
|
||||
|
@ -91,18 +92,26 @@ public abstract class Recognizer<Symbol, ATNInterpreter extends ATNSimulator> {
|
|||
*/
|
||||
@NotNull
|
||||
public Map<String, Integer> getTokenTypeMap() {
|
||||
String[] tokenNames = getTokenNames();
|
||||
if (tokenNames == null) {
|
||||
throw new UnsupportedOperationException("The current recognizer does not provide a list of token names.");
|
||||
}
|
||||
|
||||
Vocabulary vocabulary = getVocabulary();
|
||||
synchronized (tokenTypeMapCache) {
|
||||
Map<String, Integer> result = tokenTypeMapCache.get(tokenNames);
|
||||
Map<String, Integer> result = tokenTypeMapCache.get(vocabulary);
|
||||
if (result == null) {
|
||||
result = Utils.toMap(tokenNames);
|
||||
result = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < getATN().maxTokenType; i++) {
|
||||
String literalName = vocabulary.getLiteralName(i);
|
||||
if (literalName != null) {
|
||||
result.put(literalName, i);
|
||||
}
|
||||
|
||||
String symbolicName = vocabulary.getSymbolicName(i);
|
||||
if (symbolicName != null) {
|
||||
result.put(symbolicName, i);
|
||||
}
|
||||
}
|
||||
|
||||
result.put("EOF", Token.EOF);
|
||||
result = Collections.unmodifiableMap(result);
|
||||
tokenTypeMapCache.put(tokenNames, result);
|
||||
tokenTypeMapCache.put(vocabulary, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -42,6 +42,7 @@ public class TestXPath extends BaseTest {
|
|||
"DIV : '/' ;\n" +
|
||||
"ADD : '+' ;\n" +
|
||||
"SUB : '-' ;\n" +
|
||||
"RETURN : 'return' ;\n" +
|
||||
"ID : [a-zA-Z]+ ; // match identifiers\n" +
|
||||
"INT : [0-9]+ ; // match integers\n" +
|
||||
"NEWLINE:'\\r'? '\\n' -> skip; // return newlines to parser (is end-statement signal)\n" +
|
||||
|
@ -67,7 +68,8 @@ public class TestXPath extends BaseTest {
|
|||
"//ID", // any ID in tree
|
||||
"//expr/primary/ID",// any ID child of a primary under any expr
|
||||
"//body//ID", // any ID under a body
|
||||
"//'return'", // any 'return' literal in tree
|
||||
"//'return'", // any 'return' literal in tree, matched by literal name
|
||||
"//RETURN", // any 'return' literal in tree, matched by symbolic name
|
||||
"//primary/*", // all kids of any primary
|
||||
"//func/*/stat", // all stat nodes grandkids of any func node
|
||||
"/prog/func/'def'", // all def literal kids of func kid of prog
|
||||
|
@ -90,6 +92,7 @@ public class TestXPath extends BaseTest {
|
|||
"[y, x]",
|
||||
"[x, y, x]",
|
||||
"[return]",
|
||||
"[return]",
|
||||
"[3, 4, y, 1, 2, x]",
|
||||
"[stat, stat, stat, stat]",
|
||||
"[def, def]",
|
||||
|
|
Loading…
Reference in New Issue