Skip to content

Commit b08ba1d

Browse files
committed
оптимизация построителя парсера + инициализации токенайзера
1 parent 818bf88 commit b08ba1d

File tree

1 file changed

+17
-49
lines changed

1 file changed

+17
-49
lines changed

src/main/java/com/github/_1c_syntax/bsl/parser/Tokenizer.java

Lines changed: 17 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,21 @@
2222
package com.github._1c_syntax.bsl.parser;
2323

2424
import com.github._1c_syntax.utils.Lazy;
25-
import org.antlr.v4.runtime.CharStream;
2625
import org.antlr.v4.runtime.CharStreams;
2726
import org.antlr.v4.runtime.CommonToken;
2827
import org.antlr.v4.runtime.CommonTokenStream;
2928
import org.antlr.v4.runtime.ConsoleErrorListener;
30-
import org.antlr.v4.runtime.IntStream;
3129
import org.antlr.v4.runtime.Lexer;
3230
import org.antlr.v4.runtime.Parser;
3331
import org.antlr.v4.runtime.Token;
3432
import org.antlr.v4.runtime.TokenStream;
3533
import org.antlr.v4.runtime.atn.PredictionMode;
36-
import org.apache.commons.io.IOUtils;
3734

38-
import java.io.IOException;
39-
import java.io.InputStream;
35+
import java.lang.reflect.Constructor;
4036
import java.lang.reflect.InvocationTargetException;
41-
import java.lang.reflect.Method;
42-
import java.nio.charset.StandardCharsets;
43-
import java.util.ArrayList;
44-
import java.util.Arrays;
4537
import java.util.List;
46-
import java.util.Optional;
38+
import java.util.Map;
39+
import java.util.concurrent.ConcurrentHashMap;
4740

4841
import static java.util.Objects.requireNonNull;
4942
import static org.antlr.v4.runtime.Token.EOF;
@@ -56,31 +49,22 @@
5649
*/
5750
public abstract class Tokenizer<T extends BSLParserRuleContext, P extends Parser> {
5851

59-
private final InputStream content;
52+
private final String content;
6053
private final Lexer lexer;
6154
private final Lazy<CommonTokenStream> tokenStream = new Lazy<>(this::computeTokenStream);
6255
private final Lazy<List<Token>> tokens = new Lazy<>(this::computeTokens);
6356
private final Lazy<T> ast = new Lazy<>(this::computeAST);
6457
private final Class<P> parserClass;
6558
protected P parser;
6659

67-
private final Optional<Method> setInputStreamMethod;
60+
private static final Map<Class<?>, Constructor<?>> CONSTRUCTORS = new ConcurrentHashMap<>();
6861

6962
protected Tokenizer(String content, Lexer lexer, Class<P> parserClass) {
70-
this(IOUtils.toInputStream(content, StandardCharsets.UTF_8), lexer, parserClass);
71-
}
72-
73-
protected Tokenizer(InputStream content, Lexer lexer, Class<P> parserClass) {
7463
requireNonNull(content);
7564
requireNonNull(lexer);
7665
this.content = content;
7766
this.lexer = lexer;
7867
this.parserClass = parserClass;
79-
var methods = lexer.getClass().getMethods();
80-
setInputStreamMethod = Arrays.stream(methods)
81-
.filter(method -> "setInputStream".equals(method.getName())
82-
&& method.getParameterCount() == 1
83-
&& method.getParameterTypes()[0] == IntStream.class).findFirst();
8468
}
8569

8670
/**
@@ -102,8 +86,7 @@ public T getAst() {
10286
}
10387

10488
private List<Token> computeTokens() {
105-
List<Token> tokensTemp = new ArrayList<>(getTokenStream().getTokens());
106-
89+
var tokensTemp = getTokenStream().getTokens();
10790
var lastToken = tokensTemp.get(tokensTemp.size() - 1);
10891
if (lastToken.getType() == EOF && lastToken instanceof CommonToken commonToken) {
10992
commonToken.setChannel(Lexer.HIDDEN);
@@ -117,7 +100,6 @@ private T computeAST() {
117100
parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
118101
try {
119102
parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
120-
return rootAST();
121103
} catch (Exception ex) {
122104
parser.reset(); // rewind input stream
123105
parser.getInterpreter().setPredictionMode(PredictionMode.LL);
@@ -128,32 +110,11 @@ private T computeAST() {
128110
protected abstract T rootAST();
129111

130112
private CommonTokenStream computeTokenStream() {
131-
132-
CharStream input;
133-
134-
try (
135-
var ubis = new UnicodeBOMInputStream(content);
136-
) {
137-
ubis.skipBOM();
138-
input = CharStreams.fromStream(ubis);
139-
} catch (IOException e) {
140-
throw new RuntimeException(e);
141-
}
142-
143-
if (setInputStreamMethod.isPresent()) {
144-
try {
145-
setInputStreamMethod.get().invoke(lexer, input);
146-
} catch (IllegalAccessException | InvocationTargetException e) {
147-
throw new RuntimeException(e);
148-
}
149-
} else {
150-
lexer.setInputStream(input);
151-
}
152-
113+
lexer.setInputStream(CharStreams.fromString(content));
153114
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);
154-
155115
var tempTokenStream = new CommonTokenStream(lexer);
156116
tempTokenStream.fill();
117+
157118
return tempTokenStream;
158119
}
159120

@@ -163,11 +124,18 @@ protected CommonTokenStream getTokenStream() {
163124
return tokenStreamUnboxed;
164125
}
165126

127+
@SuppressWarnings("unchecked")
166128
private P createParser(CommonTokenStream tokenStream) {
167129
try {
168-
return parserClass.getDeclaredConstructor(TokenStream.class)
130+
return (P) CONSTRUCTORS.computeIfAbsent(parserClass, (Class<?> k) -> {
131+
try {
132+
return parserClass.getDeclaredConstructor(TokenStream.class);
133+
} catch (NoSuchMethodException e) {
134+
throw new RuntimeException(e);
135+
}
136+
})
169137
.newInstance(tokenStream);
170-
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
138+
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
171139
throw new RuntimeException(e);
172140
}
173141
}

0 commit comments

Comments
 (0)