22
22
package com .github ._1c_syntax .bsl .parser ;
23
23
24
24
import com .github ._1c_syntax .utils .Lazy ;
25
- import org .antlr .v4 .runtime .CharStream ;
26
25
import org .antlr .v4 .runtime .CharStreams ;
27
26
import org .antlr .v4 .runtime .CommonToken ;
28
27
import org .antlr .v4 .runtime .CommonTokenStream ;
29
28
import org .antlr .v4 .runtime .ConsoleErrorListener ;
30
- import org .antlr .v4 .runtime .IntStream ;
31
29
import org .antlr .v4 .runtime .Lexer ;
32
30
import org .antlr .v4 .runtime .Parser ;
33
31
import org .antlr .v4 .runtime .Token ;
34
32
import org .antlr .v4 .runtime .TokenStream ;
35
33
import org .antlr .v4 .runtime .atn .PredictionMode ;
36
- import org .apache .commons .io .IOUtils ;
37
34
38
- import java .io .IOException ;
39
- import java .io .InputStream ;
35
+ import java .lang .reflect .Constructor ;
40
36
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 ;
45
37
import java .util .List ;
46
- import java .util .Optional ;
38
+ import java .util .Map ;
39
+ import java .util .concurrent .ConcurrentHashMap ;
47
40
48
41
import static java .util .Objects .requireNonNull ;
49
42
import static org .antlr .v4 .runtime .Token .EOF ;
56
49
*/
57
50
public abstract class Tokenizer <T extends BSLParserRuleContext , P extends Parser > {
58
51
59
- private final InputStream content ;
52
+ private final String content ;
60
53
private final Lexer lexer ;
61
54
private final Lazy <CommonTokenStream > tokenStream = new Lazy <>(this ::computeTokenStream );
62
55
private final Lazy <List <Token >> tokens = new Lazy <>(this ::computeTokens );
63
56
private final Lazy <T > ast = new Lazy <>(this ::computeAST );
64
57
private final Class <P > parserClass ;
65
58
protected P parser ;
66
59
67
- private final Optional < Method > setInputStreamMethod ;
60
+ private static final Map < Class <?>, Constructor <?>> CONSTRUCTORS = new ConcurrentHashMap <>() ;
68
61
69
62
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 ) {
74
63
requireNonNull (content );
75
64
requireNonNull (lexer );
76
65
this .content = content ;
77
66
this .lexer = lexer ;
78
67
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 ();
84
68
}
85
69
86
70
/**
@@ -102,8 +86,7 @@ public T getAst() {
102
86
}
103
87
104
88
private List <Token > computeTokens () {
105
- List <Token > tokensTemp = new ArrayList <>(getTokenStream ().getTokens ());
106
-
89
+ var tokensTemp = getTokenStream ().getTokens ();
107
90
var lastToken = tokensTemp .get (tokensTemp .size () - 1 );
108
91
if (lastToken .getType () == EOF && lastToken instanceof CommonToken commonToken ) {
109
92
commonToken .setChannel (Lexer .HIDDEN );
@@ -117,7 +100,6 @@ private T computeAST() {
117
100
parser .removeErrorListener (ConsoleErrorListener .INSTANCE );
118
101
try {
119
102
parser .getInterpreter ().setPredictionMode (PredictionMode .SLL );
120
- return rootAST ();
121
103
} catch (Exception ex ) {
122
104
parser .reset (); // rewind input stream
123
105
parser .getInterpreter ().setPredictionMode (PredictionMode .LL );
@@ -128,32 +110,11 @@ private T computeAST() {
128
110
protected abstract T rootAST ();
129
111
130
112
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 ));
153
114
lexer .removeErrorListener (ConsoleErrorListener .INSTANCE );
154
-
155
115
var tempTokenStream = new CommonTokenStream (lexer );
156
116
tempTokenStream .fill ();
117
+
157
118
return tempTokenStream ;
158
119
}
159
120
@@ -163,11 +124,18 @@ protected CommonTokenStream getTokenStream() {
163
124
return tokenStreamUnboxed ;
164
125
}
165
126
127
+ @ SuppressWarnings ("unchecked" )
166
128
private P createParser (CommonTokenStream tokenStream ) {
167
129
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
+ })
169
137
.newInstance (tokenStream );
170
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e ) {
138
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e ) {
171
139
throw new RuntimeException (e );
172
140
}
173
141
}
0 commit comments