• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wurstscript / WurstScript / 196

09 Oct 2023 10:49PM UTC coverage: 63.447% (+0.006%) from 63.441%
196

push

circleci

web-flow
small performance fixes (#1079)

17146 of 27024 relevant lines covered (63.45%)

0.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.97
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/WurstParser.java
1
package de.peeeq.wurstscript;
2

3
import de.peeeq.wurstscript.antlr.JassParser;
4
import de.peeeq.wurstscript.antlr.WurstLexer;
5
import de.peeeq.wurstscript.antlr.WurstParser.CompilationUnitContext;
6
import de.peeeq.wurstscript.ast.Ast;
7
import de.peeeq.wurstscript.ast.CompilationUnit;
8
import de.peeeq.wurstscript.attributes.CompilationUnitInfo;
9
import de.peeeq.wurstscript.attributes.CompileError;
10
import de.peeeq.wurstscript.attributes.ErrorHandler;
11
import de.peeeq.wurstscript.gui.WurstGui;
12
import de.peeeq.wurstscript.jass.AntlrJassParseTreeTransformer;
13
import de.peeeq.wurstscript.jass.ExtendedJassLexer;
14
import de.peeeq.wurstscript.jurst.AntlrJurstParseTreeTransformer;
15
import de.peeeq.wurstscript.jurst.ExtendedJurstLexer;
16
import de.peeeq.wurstscript.jurst.antlr.JurstParser;
17
import de.peeeq.wurstscript.parser.WPos;
18
import de.peeeq.wurstscript.parser.antlr.AntlrWurstParseTreeTransformer;
19
import de.peeeq.wurstscript.parser.antlr.ExtendedWurstLexer;
20
import de.peeeq.wurstscript.utils.LineOffsets;
21
import org.antlr.v4.runtime.*;
22
import org.antlr.v4.runtime.misc.Interval;
23

24
import java.io.IOException;
25
import java.io.Reader;
26
import java.io.StringReader;
27
import java.util.regex.Matcher;
28
import java.util.regex.Pattern;
29

30
public class WurstParser {
31
    private static final int MAX_SYNTAX_ERRORS = 15;
32
    private final ErrorHandler errorHandler;
33
    private final WurstGui gui;
34

35
    public WurstParser(ErrorHandler errorHandler, WurstGui gui) {
1✔
36
        this.errorHandler = errorHandler;
1✔
37
        this.gui = gui;
1✔
38
    }
1✔
39

40
    public CompilationUnit parse(Reader reader, String source, boolean hasCommonJ) {
41
        return parseWithAntlr(reader, source, hasCommonJ);
1✔
42
    }
43

44
    private static final Pattern pattern = Pattern.compile("\\s*");
1✔
45

46
    private CompilationUnit parseWithAntlr(Reader reader, final String source, boolean hasCommonJ) {
47
        try {
48
            CharStream input = CharStreams.fromReader(reader);
1✔
49
            // create a lexer that feeds off of input CharStream
50
            final ExtendedWurstLexer lexer = new ExtendedWurstLexer(input);
1✔
51
            // create a buffer of tokens pulled from the lexer
52
            TokenStream tokens = new CommonTokenStream(lexer);
1✔
53
            // create a parser that feeds off the tokens buffer
54
            de.peeeq.wurstscript.antlr.WurstParser parser = new de.peeeq.wurstscript.antlr.WurstParser(tokens);
1✔
55
            ANTLRErrorListener l = new BaseErrorListener() {
1✔
56

57
                int errorCount = 0;
1✔
58

59

60

61
                @Override
62
                public void syntaxError(@SuppressWarnings("null") Recognizer<?, ?> recognizer, @SuppressWarnings("null") Object offendingSymbol, int line,
63
                                        int charPositionInLine,
64
                                        @SuppressWarnings("null") String msg, @SuppressWarnings("null") RecognitionException e) {
65

66
                    // try to improve error message
67
                    if (e instanceof NoViableAltException) {
1✔
68
                        NoViableAltException ne = (NoViableAltException) e;
1✔
69
                        if (ne.getStartToken().getType() == WurstLexer.HOTDOC_COMMENT) {
1✔
70
                            msg = "Hotdoc comment is in invalid position, it can " +
×
71
                                    "only appear before function definitions, classes, and " +
72
                                    "other elements that can be documented.";
73
                            offendingSymbol = ne.getStartToken();
×
74
                        }
75
                    }
76

77
                    LineOffsets offsets = lexer.getLineOffsets();
1✔
78
                    int pos;
79
                    int posStop;
80
                    if (offendingSymbol instanceof Token) {
1✔
81
                        Token token = (Token) offendingSymbol;
1✔
82
                        pos = token.getStartIndex();
1✔
83
                        posStop = token.getStopIndex() + 1;
1✔
84
                    } else {
1✔
85
                        pos = offsets.get(line) + charPositionInLine;
1✔
86
                        posStop = pos + 1;
1✔
87
                    }
88

89
                    if (posStop >= input.size()) {
1✔
90
                        posStop = input.size() - 1;
1✔
91
                    }
92

93
                    Matcher matcher = pattern.matcher(input.getText(new Interval(pos, posStop)));
1✔
94
                    while (pos > 0 && matcher.matches()){
1✔
95
                        pos--;
1✔
96
                    }
97
                    CompileError err = new CompileError(new WPos(source, offsets, pos, posStop), msg);
1✔
98
                    gui.sendError(err);
1✔
99

100
                    errorCount++;
1✔
101
                    if (errorCount > MAX_SYNTAX_ERRORS) {
1✔
102
                        throw new TooManyErrorsException();
×
103
                    }
104
                }
1✔
105

106
            };
107
            lexer.setErrorListener(l);
1✔
108
            parser.removeErrorListeners();
1✔
109
            parser.addErrorListener(l);
1✔
110

111
            CompilationUnitContext cu = parser.compilationUnit(); // begin parsing at init rule
1✔
112

113
            if (lexer.getTabWarning() != null) {
1✔
114
                CompileError warning = lexer.getTabWarning();
1✔
115
                warning = new CompileError(warning.getSource().withFile(source), warning.getMessage(), CompileError.ErrorType.WARNING);
1✔
116
                gui.sendError(warning);
1✔
117
            }
118

119
            CompilationUnit root = new AntlrWurstParseTreeTransformer(source, errorHandler, lexer.getLineOffsets()).transform(cu);
1✔
120
            removeSyntacticSugar(root, hasCommonJ);
1✔
121
            root.getCuInfo().setIndentationMode(lexer.getIndentationMode());
1✔
122
            return root;
1✔
123

124
        } catch (IOException e) {
×
125
            WLogger.severe(e);
×
126
            throw new Error(e);
×
127
        } catch (TooManyErrorsException e) {
×
128
            WLogger.info("Stopped parsing file " + source + ", too many errors");
×
129
            return emptyCompilationUnit();
×
130
        }
131
    }
132

133

134
    public CompilationUnit parseJurst(Reader reader, String source, boolean hasCommonJ) {
135
        return parseJurstWithAntlr(reader, source, hasCommonJ);
1✔
136
    }
137

138
    private CompilationUnit parseJurstWithAntlr(Reader reader, final String source, boolean hasCommonJ) {
139
        try {
140
            CharStream input = CharStreams.fromReader(reader);
1✔
141
            // create a lexer that feeds off of input CharStream
142
            final ExtendedJurstLexer lexer = new ExtendedJurstLexer(input);
1✔
143
            // create a buffer of tokens pulled from the lexer
144
            TokenStream tokens = new CommonTokenStream(lexer);
1✔
145
            // create a parser that feeds off the tokens buffer
146
            JurstParser parser = new JurstParser(tokens);
1✔
147
            ANTLRErrorListener l = new BaseErrorListener() {
1✔
148

149
                int errorCount = 0;
1✔
150

151
                @Override
152
                public void syntaxError(@SuppressWarnings("null") Recognizer<?, ?> recognizer, @SuppressWarnings("null") Object offendingSymbol, int line,
153
                                        int charPositionInLine,
154
                                        @SuppressWarnings("null") String msg, @SuppressWarnings("null") RecognitionException e) {
155

156
                    LineOffsets offsets = lexer.getLineOffsets();
×
157
                    int pos;
158
                    int posStop;
159
                    if (offendingSymbol instanceof Token) {
×
160
                        Token token = (Token) offendingSymbol;
×
161
                        pos = token.getStartIndex();
×
162
                        posStop = token.getStopIndex() + 1;
×
163
                    } else {
×
164
                        pos = offsets.get(line) + charPositionInLine;
×
165
                        posStop = pos + 1;
×
166
                    }
167

168
                    msg = "line " + line + ": " + msg;
×
169

170
                    Matcher matcher = pattern.matcher(input.getText(new Interval(pos, posStop)));
×
171
                    while (pos > 0 && matcher.matches()) {
×
172
                        pos--;
×
173
                    }
174
                    CompileError err = new CompileError(new WPos(source, offsets, pos, posStop), msg);
×
175
                    gui.sendError(err);
×
176

177

178
                    errorCount++;
×
179
                    if (errorCount > MAX_SYNTAX_ERRORS) {
×
180
                        throw new TooManyErrorsException();
×
181
                    }
182
                }
×
183

184
            };
185
            lexer.addErrorListener(l);
1✔
186
            parser.removeErrorListeners();
1✔
187
            parser.addErrorListener(l);
1✔
188

189
            de.peeeq.wurstscript.jurst.antlr.JurstParser.CompilationUnitContext cu = parser.compilationUnit(); // begin parsing at init rule
1✔
190
            CompilationUnit root = new AntlrJurstParseTreeTransformer(source, errorHandler, lexer.getLineOffsets()).transform(cu);
1✔
191
            removeSyntacticSugar(root, hasCommonJ);
1✔
192
            return root;
1✔
193

194
        } catch (IOException e) {
×
195
            WLogger.severe(e);
×
196
            throw new Error(e);
×
197
        } catch (TooManyErrorsException e) {
×
198
            WLogger.info("Stopped parsing file " + source + ", too many errors");
×
199
            return emptyCompilationUnit();
×
200
        }
201
    }
202

203
    public CompilationUnit parseJass(Reader reader, String source, boolean hasCommonJ) {
204
        return parseJassAntlr(reader, source, hasCommonJ);
1✔
205
    }
206

207
    private CompilationUnit parseJassAntlr(Reader reader, final String source, boolean hasCommonJ) {
208
        try {
209
            CharStream input = CharStreams.fromReader(reader);
1✔
210
            // create a lexer that feeds off of input CharStream
211
            final ExtendedJassLexer lexer = new ExtendedJassLexer(input);
1✔
212
            // create a buffer of tokens pulled from the lexer
213
            TokenStream tokens = new CommonTokenStream(lexer);
1✔
214
            // create a parser that feeds off the tokens buffer
215
            JassParser parser = new JassParser(tokens);
1✔
216
            ANTLRErrorListener l = new BaseErrorListener() {
1✔
217

218
                int errorCount = 0;
1✔
219

220
                @Override
221
                public void syntaxError(@SuppressWarnings("null") Recognizer<?, ?> recognizer, @SuppressWarnings("null") Object offendingSymbol, int line,
222
                                        int charPositionInLine,
223
                                        @SuppressWarnings("null") String msg, @SuppressWarnings("null") RecognitionException e) {
224

225
                    LineOffsets offsets = lexer.getLineOffsets();
×
226
                    int pos;
227
                    int posStop;
228
                    if (offendingSymbol instanceof Token) {
×
229
                        Token token = (Token) offendingSymbol;
×
230
                        pos = token.getStartIndex();
×
231
                        posStop = token.getStopIndex() + 1;
×
232
                    } else {
×
233
                        pos = offsets.get(line) + charPositionInLine;
×
234
                        posStop = pos + 1;
×
235
                    }
236

237
                    msg = "line " + line + ": " + msg;
×
238

239
                    Matcher matcher = pattern.matcher(input.getText(new Interval(pos, posStop)));
×
240
                    while (pos > 0 && matcher.matches()) {
×
241
                        pos--;
×
242
                    }
243
                    CompileError err = new CompileError(new WPos(source, offsets, pos, posStop), msg);
×
244
                    gui.sendError(err);
×
245

246

247
                    errorCount++;
×
248
                    if (errorCount > MAX_SYNTAX_ERRORS) {
×
249
                        throw new TooManyErrorsException();
×
250
                    }
251
                }
×
252

253
            };
254
            lexer.addErrorListener(l);
1✔
255
            parser.removeErrorListeners();
1✔
256
            parser.addErrorListener(l);
1✔
257

258
            JassParser.CompilationUnitContext cu = parser.compilationUnit(); // begin parsing at init rule
1✔
259
            CompilationUnit root = new AntlrJassParseTreeTransformer(source, errorHandler, lexer.getLineOffsets()).transform(cu);
1✔
260
            removeSyntacticSugar(root, hasCommonJ);
1✔
261
            return root;
1✔
262

263
        } catch (IOException e) {
×
264
            WLogger.severe(e);
×
265
            throw new Error(e);
×
266
        } catch (TooManyErrorsException e) {
×
267
            WLogger.info("Stopped parsing file " + source + ", too many errors");
×
268
            return emptyCompilationUnit();
×
269
        }
270
    }
271

272

273
    public CompilationUnit emptyCompilationUnit() {
274
        return Ast.CompilationUnit(new CompilationUnitInfo(errorHandler), Ast.JassToplevelDeclarations(), Ast.WPackages());
×
275
    }
276

277
    private void removeSyntacticSugar(CompilationUnit root, boolean hasCommonJ) {
278
        new SyntacticSugar().removeSyntacticSugar(root, hasCommonJ);
1✔
279
    }
1✔
280

281
    static class TooManyErrorsException extends RuntimeException {
×
282
    }
283
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc