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

wurstscript / WurstScript / 228

29 Nov 2023 05:00PM UTC coverage: 62.48% (-0.09%) from 62.574%
228

push

circleci

web-flow
Show dialog for choosing game path, cleanup (#1083)

* show dialog for choosing game path

* cleanup code

* remove logs and refactor

* remove confusing mpq error, make some mpq loads readonly

17295 of 27681 relevant lines covered (62.48%)

0.62 hits per line

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

56.12
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.util.regex.Matcher;
27
import java.util.regex.Pattern;
28

29
public class WurstParser {
30
    private static final int MAX_SYNTAX_ERRORS = 15;
31
    private final ErrorHandler errorHandler;
32
    private final WurstGui gui;
33
    private boolean removeSugar = true;
1✔
34

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

40
    public void setRemoveSugar(boolean removeSugar) {
41
        this.removeSugar = removeSugar;
×
42
    }
×
43

44
    public CompilationUnit parse(Reader reader, String source, boolean hasCommonJ) {
45
        return parseWithAntlr(reader, source, hasCommonJ);
1✔
46
    }
47

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

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

61
                int errorCount = 0;
1✔
62

63

64

65
                @Override
66
                public void syntaxError(@SuppressWarnings("null") Recognizer<?, ?> recognizer, @SuppressWarnings("null") Object offendingSymbol, int line,
67
                                        int charPositionInLine,
68
                                        @SuppressWarnings("null") String msg, @SuppressWarnings("null") RecognitionException e) {
69

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

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

93
                    if (posStop >= input.size()) {
1✔
94
                        posStop = input.size() - 1;
1✔
95
                    }
96

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

104
                    errorCount++;
1✔
105
                    if (errorCount > MAX_SYNTAX_ERRORS) {
1✔
106
                        throw new TooManyErrorsException();
×
107
                    }
108
                }
1✔
109

110
            };
111
            lexer.setErrorListener(l);
1✔
112
            parser.removeErrorListeners();
1✔
113
            parser.addErrorListener(l);
1✔
114

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

117
            if (lexer.getTabWarning() != null) {
1✔
118
                CompileError warning = lexer.getTabWarning();
1✔
119
                warning = new CompileError(warning.getSource().withFile(source), warning.getMessage(), CompileError.ErrorType.WARNING);
1✔
120
                gui.sendError(warning);
1✔
121
            }
122

123
            CompilationUnit root = new AntlrWurstParseTreeTransformer(source, errorHandler, lexer.getLineOffsets(), lexer.getCommentTokens(), true).transform(cu);
1✔
124
            if (this.removeSugar) {
1✔
125
                removeSyntacticSugar(root, hasCommonJ);
1✔
126
            }
127
            root.getCuInfo().setIndentationMode(lexer.getIndentationMode());
1✔
128
            return root;
1✔
129

130
        } catch (IOException e) {
×
131
            WLogger.severe(e);
×
132
            throw new Error(e);
×
133
        } catch (TooManyErrorsException e) {
×
134
            WLogger.info("Stopped parsing file " + source + ", too many errors");
×
135
            return emptyCompilationUnit();
×
136
        }
137
    }
138

139

140
    public CompilationUnit parseJurst(Reader reader, String source, boolean hasCommonJ) {
141
        return parseJurstWithAntlr(reader, source, hasCommonJ);
1✔
142
    }
143

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

155
                int errorCount = 0;
1✔
156

157
                @Override
158
                public void syntaxError(@SuppressWarnings("null") Recognizer<?, ?> recognizer, @SuppressWarnings("null") Object offendingSymbol, int line,
159
                                        int charPositionInLine,
160
                                        @SuppressWarnings("null") String msg, @SuppressWarnings("null") RecognitionException e) {
161

162
                    LineOffsets offsets = lexer.getLineOffsets();
×
163
                    int pos;
164
                    int posStop;
165
                    if (offendingSymbol instanceof Token) {
×
166
                        Token token = (Token) offendingSymbol;
×
167
                        pos = token.getStartIndex();
×
168
                        posStop = token.getStopIndex() + 1;
×
169
                    } else {
×
170
                        pos = offsets.get(line) + charPositionInLine;
×
171
                        posStop = pos + 1;
×
172
                    }
173

174
                    msg = "line " + line + ": " + msg;
×
175

176
                    Matcher matcher = pattern.matcher(input.getText(new Interval(pos, posStop)));
×
177
                    while (pos > 0 && matcher.matches()) {
×
178
                        pos--;
×
179
                    }
180
                    CompileError err = new CompileError(new WPos(source, offsets, pos, posStop), msg);
×
181
                    gui.sendError(err);
×
182

183

184
                    errorCount++;
×
185
                    if (errorCount > MAX_SYNTAX_ERRORS) {
×
186
                        throw new TooManyErrorsException();
×
187
                    }
188
                }
×
189

190
            };
191
            lexer.addErrorListener(l);
1✔
192
            parser.removeErrorListeners();
1✔
193
            parser.addErrorListener(l);
1✔
194

195
            de.peeeq.wurstscript.jurst.antlr.JurstParser.CompilationUnitContext cu = parser.compilationUnit(); // begin parsing at init rule
1✔
196
            CompilationUnit root = new AntlrJurstParseTreeTransformer(source, errorHandler, lexer.getLineOffsets()).transform(cu);
1✔
197
            if (this.removeSugar) {
1✔
198
                removeSyntacticSugar(root, hasCommonJ);
1✔
199
            }
200
            return root;
1✔
201

202
        } catch (IOException e) {
×
203
            WLogger.severe(e);
×
204
            throw new Error(e);
×
205
        } catch (TooManyErrorsException e) {
×
206
            WLogger.info("Stopped parsing file " + source + ", too many errors");
×
207
            return emptyCompilationUnit();
×
208
        }
209
    }
210

211
    public CompilationUnit parseJass(Reader reader, String source, boolean hasCommonJ) {
212
        return parseJassAntlr(reader, source, hasCommonJ);
1✔
213
    }
214

215
    private CompilationUnit parseJassAntlr(Reader reader, final String source, boolean hasCommonJ) {
216
        try {
217
            CharStream input = CharStreams.fromReader(reader);
1✔
218
            // create a lexer that feeds off of input CharStream
219
            final ExtendedJassLexer lexer = new ExtendedJassLexer(input);
1✔
220
            // create a buffer of tokens pulled from the lexer
221
            TokenStream tokens = new CommonTokenStream(lexer);
1✔
222
            // create a parser that feeds off the tokens buffer
223
            JassParser parser = new JassParser(tokens);
1✔
224
            ANTLRErrorListener l = new BaseErrorListener() {
1✔
225

226
                int errorCount = 0;
1✔
227

228
                @Override
229
                public void syntaxError(@SuppressWarnings("null") Recognizer<?, ?> recognizer, @SuppressWarnings("null") Object offendingSymbol, int line,
230
                                        int charPositionInLine,
231
                                        @SuppressWarnings("null") String msg, @SuppressWarnings("null") RecognitionException e) {
232

233
                    LineOffsets offsets = lexer.getLineOffsets();
×
234
                    int pos;
235
                    int posStop;
236
                    if (offendingSymbol instanceof Token) {
×
237
                        Token token = (Token) offendingSymbol;
×
238
                        pos = token.getStartIndex();
×
239
                        posStop = token.getStopIndex() + 1;
×
240
                    } else {
×
241
                        pos = offsets.get(line) + charPositionInLine;
×
242
                        posStop = pos + 1;
×
243
                    }
244

245
                    msg = "line " + line + ": " + msg;
×
246

247
                    Matcher matcher = pattern.matcher(input.getText(new Interval(pos, posStop)));
×
248
                    while (pos > 0 && matcher.matches()) {
×
249
                        pos--;
×
250
                    }
251
                    CompileError err = new CompileError(new WPos(source, offsets, pos, posStop), msg);
×
252
                    gui.sendError(err);
×
253

254

255
                    errorCount++;
×
256
                    if (errorCount > MAX_SYNTAX_ERRORS) {
×
257
                        throw new TooManyErrorsException();
×
258
                    }
259
                }
×
260

261
            };
262
            lexer.addErrorListener(l);
1✔
263
            parser.removeErrorListeners();
1✔
264
            parser.addErrorListener(l);
1✔
265

266
            JassParser.CompilationUnitContext cu = parser.compilationUnit(); // begin parsing at init rule
1✔
267
            CompilationUnit root = new AntlrJassParseTreeTransformer(source, errorHandler, lexer.getLineOffsets()).transform(cu);
1✔
268
            removeSyntacticSugar(root, hasCommonJ);
1✔
269
            return root;
1✔
270

271
        } catch (IOException e) {
×
272
            WLogger.severe(e);
×
273
            throw new Error(e);
×
274
        } catch (TooManyErrorsException e) {
×
275
            WLogger.info("Stopped parsing file " + source + ", too many errors");
×
276
            return emptyCompilationUnit();
×
277
        }
278
    }
279

280

281
    public CompilationUnit emptyCompilationUnit() {
282
        return Ast.CompilationUnit(new CompilationUnitInfo(errorHandler), Ast.JassToplevelDeclarations(), Ast.WPackages());
×
283
    }
284

285
    private void removeSyntacticSugar(CompilationUnit root, boolean hasCommonJ) {
286
        new SyntacticSugar().removeSyntacticSugar(root, hasCommonJ);
1✔
287
    }
1✔
288

289
    static class TooManyErrorsException extends RuntimeException {
×
290
    }
291
}
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