Browse Source

- Statements can now also store comments before and after them

- Added comment & partial whitespace preservation to the file formatter
Stan Hebben 6 years ago
parent
commit
2078d3f1cc
25 changed files with 450 additions and 94 deletions
  1. 56
    0
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/CommentFormatter.java
  2. 9
    0
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FileFormatter.java
  3. 89
    34
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/StatementFormatter.java
  4. 49
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/WhitespaceInfo.java
  5. 38
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/WhitespacePostComment.java
  6. 1
    1
      Parser/src/main/java/org/openzen/zenscript/lexer/TokenStream.java
  7. 47
    0
      Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenStream.java
  8. 8
    2
      Parser/src/main/java/org/openzen/zenscript/parser/ParsedFile.java
  9. 61
    14
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatement.java
  10. 11
    4
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementBlock.java
  11. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementBreak.java
  12. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementContinue.java
  13. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementDoWhile.java
  14. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementExpression.java
  15. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementForeach.java
  16. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementIf.java
  17. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementLock.java
  18. 4
    4
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementNull.java
  19. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementReturn.java
  20. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementThrow.java
  21. 4
    2
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementTryCatch.java
  22. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementVar.java
  23. 4
    3
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementWhile.java
  24. 26
    0
      Shared/src/main/java/org/openzen/zenscript/shared/StringUtils.java
  25. 3
    0
      Shared/src/main/java/org/openzen/zenscript/shared/TagDictionary.java

+ 56
- 0
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/CommentFormatter.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.formatter;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class CommentFormatter {
13
+	private CommentFormatter() {}
14
+	
15
+	public static String[] format(String[] comments) {
16
+		if (comments.length == 0)
17
+			return comments;
18
+		
19
+		boolean isInMultilineComment = false;
20
+		String[] result = new String[comments.length];
21
+		for (int i = 0; i < comments.length; i++) {
22
+			String comment = comments[i];
23
+			if (isInMultilineComment) {
24
+				if (!comment.startsWith("*"))
25
+					comment = "* " + comment;
26
+				comment = " " + comment;
27
+			}
28
+			
29
+			result[i] = comment;
30
+			
31
+			int index = 0;
32
+			while (true) {
33
+				if (!isInMultilineComment && comment.indexOf("//", index) > 0)
34
+					break;
35
+				
36
+				int newIndexOpen = comment.indexOf("/*", index);
37
+				if (newIndexOpen >= 0) {
38
+					isInMultilineComment = true;
39
+					index = newIndexOpen;
40
+				} else {
41
+					break;
42
+				}
43
+				
44
+				int newIndexClose = comment.indexOf("*/", newIndexOpen);
45
+				if (newIndexClose >= 0) {
46
+					isInMultilineComment = false;
47
+					index = newIndexClose;
48
+				} else {
49
+					break;
50
+				}
51
+			}
52
+		}
53
+		
54
+		return result;
55
+	}
56
+}

+ 9
- 0
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FileFormatter.java View File

12
 import java.util.Map;
12
 import java.util.Map;
13
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
13
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
14
 import org.openzen.zenscript.codemodel.ScriptBlock;
14
 import org.openzen.zenscript.codemodel.ScriptBlock;
15
+import org.openzen.zenscript.codemodel.WhitespacePostComment;
15
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
16
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
16
 import org.openzen.zenscript.codemodel.statement.Statement;
17
 import org.openzen.zenscript.codemodel.statement.Statement;
17
 
18
 
41
 		StringBuilder output = new StringBuilder();
42
 		StringBuilder output = new StringBuilder();
42
 		importer.write(output);
43
 		importer.write(output);
43
 		output.append(scriptFormatter.toString().trim());
44
 		output.append(scriptFormatter.toString().trim());
45
+		
46
+		WhitespacePostComment postComment = script.getTag(WhitespacePostComment.class);
47
+		if (postComment != null) {
48
+			for (String comment : CommentFormatter.format(postComment.comments)) {
49
+				output.append("\n").append(comment);
50
+			}
51
+		}
52
+		
44
 		return output.toString();
53
 		return output.toString();
45
 	}
54
 	}
46
 	
55
 	

+ 89
- 34
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/StatementFormatter.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.formatter;
6
 package org.openzen.zenscript.formatter;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
9
+import org.openzen.zenscript.codemodel.WhitespacePostComment;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
10
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.statement.BlockStatement;
11
 import org.openzen.zenscript.codemodel.statement.BlockStatement;
10
 import org.openzen.zenscript.codemodel.statement.BreakStatement;
12
 import org.openzen.zenscript.codemodel.statement.BreakStatement;
51
 
53
 
52
 	@Override
54
 	@Override
53
 	public Void visitBlock(BlockStatement statement) {
55
 	public Void visitBlock(BlockStatement statement) {
54
-		beginBlock();
56
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
57
+		beginBlock(whitespace);
55
 		
58
 		
56
 		String oldIndent = indent;
59
 		String oldIndent = indent;
57
 		indent = oldIndent + settings.indent;
60
 		indent = oldIndent + settings.indent;
58
 		for (Statement subStatement : statement.statements) {
61
 		for (Statement subStatement : statement.statements) {
59
 			format(ParentStatementType.NONE, subStatement);
62
 			format(ParentStatementType.NONE, subStatement);
60
 		}
63
 		}
64
+		
65
+		WhitespacePostComment postComment = statement.getTag(WhitespacePostComment.class);
66
+		if (postComment != null) {
67
+			writePostComments(postComment.comments);
68
+		}
69
+		
61
 		indent = oldIndent;
70
 		indent = oldIndent;
62
-		endBlock();
71
+		
72
+		endBlock(whitespace);
63
 		return null;
73
 		return null;
64
 	}
74
 	}
65
 
75
 
66
 	@Override
76
 	@Override
67
 	public Void visitBreak(BreakStatement statement) {
77
 	public Void visitBreak(BreakStatement statement) {
68
-		beginSingleLine();
78
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
79
+		beginSingleLine(whitespace);
69
 		result.append("break");
80
 		result.append("break");
70
-		if (statement.target != null)
81
+		if (statement.target.label != null)
71
 			result.append(' ').append(statement.target.label);
82
 			result.append(' ').append(statement.target.label);
72
 		result.append(";");
83
 		result.append(";");
73
-		endSingleLine();
84
+		endSingleLine(whitespace);
74
 		return null;
85
 		return null;
75
 	}
86
 	}
76
 
87
 
77
 	@Override
88
 	@Override
78
 	public Void visitContinue(ContinueStatement statement) {
89
 	public Void visitContinue(ContinueStatement statement) {
79
-		beginSingleLine();
90
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
91
+		beginSingleLine(whitespace);
80
 		result.append("continue");
92
 		result.append("continue");
81
-		if (statement.target != null)
93
+		if (statement.target.label != null)
82
 			result.append(' ').append(statement.target.label);
94
 			result.append(' ').append(statement.target.label);
83
 		result.append(";");
95
 		result.append(";");
84
-		endSingleLine();
96
+		endSingleLine(whitespace);
85
 		return null;
97
 		return null;
86
 	}
98
 	}
87
 
99
 
88
 	@Override
100
 	@Override
89
 	public Void visitDoWhile(DoWhileStatement statement) {
101
 	public Void visitDoWhile(DoWhileStatement statement) {
90
-		beginSingleLine();
102
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
103
+		beginSingleLine(whitespace);
91
 		result.append("do");
104
 		result.append("do");
92
 		if (statement.label != null) {
105
 		if (statement.label != null) {
93
 			if (settings.spaceBeforeLabelColon)
106
 			if (settings.spaceBeforeLabelColon)
101
 		result.append(" while ");
114
 		result.append(" while ");
102
 		appendCondition(statement.condition);
115
 		appendCondition(statement.condition);
103
 		result.append(";");
116
 		result.append(";");
104
-		endSingleLine();
117
+		endSingleLine(whitespace);
105
 		return null;
118
 		return null;
106
 	}
119
 	}
107
 
120
 
108
 	@Override
121
 	@Override
109
 	public Void visitEmpty(EmptyStatement statement) {
122
 	public Void visitEmpty(EmptyStatement statement) {
110
-		beginSingleLine();
123
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
124
+		beginSingleLine(whitespace);
111
 		result.append(";\n");
125
 		result.append(";\n");
112
-		endSingleLine();
126
+		endSingleLine(whitespace);
113
 		return null;
127
 		return null;
114
 	}
128
 	}
115
 
129
 
116
 	@Override
130
 	@Override
117
 	public Void visitExpression(ExpressionStatement statement) {
131
 	public Void visitExpression(ExpressionStatement statement) {
118
-		beginSingleLine();
132
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
133
+		beginSingleLine(whitespace);
119
 		result.append(statement.expression.accept(expressionFormatter).value)
134
 		result.append(statement.expression.accept(expressionFormatter).value)
120
 			  .append(";");
135
 			  .append(";");
121
-		endSingleLine();
136
+		endSingleLine(whitespace);
122
 		return null;
137
 		return null;
123
 	}
138
 	}
124
 
139
 
125
 	@Override
140
 	@Override
126
 	public Void visitForeach(ForeachStatement statement) {
141
 	public Void visitForeach(ForeachStatement statement) {
127
-		beginSingleLine();
142
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
143
+		beginSingleLine(whitespace);
128
 		result.append("for ");
144
 		result.append("for ");
129
 		for (int i = 0; i < statement.loopVariables.length; i++) {
145
 		for (int i = 0; i < statement.loopVariables.length; i++) {
130
 			if (i > 0)
146
 			if (i > 0)
135
 		result.append(" in ");
151
 		result.append(" in ");
136
 		result.append(statement.list.accept(expressionFormatter).value);
152
 		result.append(statement.list.accept(expressionFormatter).value);
137
 		format(ParentStatementType.LOOP, statement.content);
153
 		format(ParentStatementType.LOOP, statement.content);
138
-		endSingleLine();
154
+		endSingleLine(whitespace);
139
 		return null;
155
 		return null;
140
 	}
156
 	}
141
 
157
 
142
 	@Override
158
 	@Override
143
 	public Void visitIf(IfStatement statement) {
159
 	public Void visitIf(IfStatement statement) {
160
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
144
 		ParentStatementType position = this.position;
161
 		ParentStatementType position = this.position;
145
-		beginSingleLine();
162
+		beginSingleLine(whitespace);
146
 		result.append("if ");
163
 		result.append("if ");
147
 		appendCondition(statement.condition);
164
 		appendCondition(statement.condition);
148
 		format(statement.onElse == null ? ParentStatementType.IF : ParentStatementType.IF_WITH_ELSE, statement.onThen);
165
 		format(statement.onElse == null ? ParentStatementType.IF : ParentStatementType.IF_WITH_ELSE, statement.onThen);
150
 			result.append("else");
167
 			result.append("else");
151
 			format(ParentStatementType.ELSE, statement.onElse);
168
 			format(ParentStatementType.ELSE, statement.onElse);
152
 		}
169
 		}
153
-		endSingleLine();
170
+		endSingleLine(whitespace);
154
 		return null;
171
 		return null;
155
 	}
172
 	}
156
 
173
 
157
 	@Override
174
 	@Override
158
 	public Void visitLock(LockStatement statement) {
175
 	public Void visitLock(LockStatement statement) {
159
-		beginSingleLine();
176
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
177
+		beginSingleLine(whitespace);
160
 		result.append("lock ");
178
 		result.append("lock ");
161
 		result.append(statement.object.accept(expressionFormatter).value);
179
 		result.append(statement.object.accept(expressionFormatter).value);
162
 		statement.content.accept(this);
180
 		statement.content.accept(this);
163
-		endSingleLine();
181
+		endSingleLine(whitespace);
164
 		return null;
182
 		return null;
165
 	}
183
 	}
166
 
184
 
167
 	@Override
185
 	@Override
168
 	public Void visitReturn(ReturnStatement statement) {
186
 	public Void visitReturn(ReturnStatement statement) {
169
-		beginSingleLine();
187
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
188
+		beginSingleLine(whitespace);
170
 		result.append("return");
189
 		result.append("return");
171
 		if (statement.value != null) {
190
 		if (statement.value != null) {
172
 			result.append(' ');
191
 			result.append(' ');
173
 			result.append(statement.value.accept(expressionFormatter).value);
192
 			result.append(statement.value.accept(expressionFormatter).value);
174
 		}
193
 		}
175
 		result.append(";");
194
 		result.append(";");
176
-		endSingleLine();
195
+		endSingleLine(whitespace);
177
 		return null;
196
 		return null;
178
 	}
197
 	}
179
 
198
 
180
 	@Override
199
 	@Override
181
 	public Void visitThrow(ThrowStatement statement) {
200
 	public Void visitThrow(ThrowStatement statement) {
182
-		beginSingleLine();
201
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
202
+		beginSingleLine(whitespace);
183
 		result.append("throw ").append(statement.value.accept(expressionFormatter));
203
 		result.append("throw ").append(statement.value.accept(expressionFormatter));
184
-		endSingleLine();
204
+		endSingleLine(whitespace);
185
 		return null;
205
 		return null;
186
 	}
206
 	}
187
 
207
 
188
 	@Override
208
 	@Override
189
 	public Void visitTryCatch(TryCatchStatement statement) {
209
 	public Void visitTryCatch(TryCatchStatement statement) {
190
-		beginSingleLine();
210
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
211
+		beginSingleLine(whitespace);
191
 		result.append("try");
212
 		result.append("try");
192
 		if (statement.resource != null) {
213
 		if (statement.resource != null) {
193
 			result.append(' ').append(statement.resource.name);
214
 			result.append(' ').append(statement.resource.name);
213
 			
234
 			
214
 			format(ParentStatementType.FINALLY, statement.finallyClause);
235
 			format(ParentStatementType.FINALLY, statement.finallyClause);
215
 		}
236
 		}
216
-		endSingleLine();
237
+		endSingleLine(whitespace);
217
 		return null;
238
 		return null;
218
 	}
239
 	}
219
 
240
 
220
 	@Override
241
 	@Override
221
 	public Void visitVar(VarStatement statement) {
242
 	public Void visitVar(VarStatement statement) {
222
-		beginSingleLine();
243
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
244
+		beginSingleLine(whitespace);
223
 		result.append(statement.isFinal ? "val " : "var ");
245
 		result.append(statement.isFinal ? "val " : "var ");
224
 		result.append(statement.name);
246
 		result.append(statement.name);
225
 		
247
 		
232
 			result.append(statement.initializer.accept(expressionFormatter).value);
254
 			result.append(statement.initializer.accept(expressionFormatter).value);
233
 		}
255
 		}
234
 		result.append(";");
256
 		result.append(";");
235
-		endSingleLine();
257
+		endSingleLine(whitespace);
236
 		return null;
258
 		return null;
237
 	}
259
 	}
238
 
260
 
239
 	@Override
261
 	@Override
240
 	public Void visitWhile(WhileStatement statement) {
262
 	public Void visitWhile(WhileStatement statement) {
241
-		beginSingleLine();
263
+		WhitespaceInfo whitespace = statement.getTag(WhitespaceInfo.class);
264
+		beginSingleLine(whitespace);
242
 		result.append("while");
265
 		result.append("while");
243
 		if (statement.label != null) {
266
 		if (statement.label != null) {
244
 			if (settings.spaceBeforeLabelColon)
267
 			if (settings.spaceBeforeLabelColon)
252
 		appendCondition(statement.condition);
275
 		appendCondition(statement.condition);
253
 		
276
 		
254
 		format(ParentStatementType.LOOP, statement.content);
277
 		format(ParentStatementType.LOOP, statement.content);
255
-		endSingleLine();
278
+		endSingleLine(whitespace);
256
 		return null;
279
 		return null;
257
 	}
280
 	}
258
 	
281
 	
271
 			result.append(')');
294
 			result.append(')');
272
 	}
295
 	}
273
 	
296
 	
274
-	private void beginBlock() {
297
+	private void beginBlock(WhitespaceInfo whitespace) {
275
 		result.append(settings.getBlockSeparator(indent, position));
298
 		result.append(settings.getBlockSeparator(indent, position));
299
+		
300
+		if (whitespace != null) {
301
+			if (whitespace.emptyLine) {
302
+				result.append("\n").append(indent);
303
+			}
304
+			writeComments(whitespace.commentsBefore);
305
+		}
276
 	}
306
 	}
277
 	
307
 	
278
-	private void endBlock() {
308
+	private void endBlock(WhitespaceInfo whitespace) {
309
+		if (whitespace != null && !whitespace.commentsAfter.isEmpty())
310
+			result.append(' ').append(whitespace.commentsAfter);
311
+		
279
 		result.append("\n").append(indent).append("}");
312
 		result.append("\n").append(indent).append("}");
280
 		if (position == ParentStatementType.IF_WITH_ELSE) {
313
 		if (position == ParentStatementType.IF_WITH_ELSE) {
281
 			if (settings.elseBracketOnSameLine)
314
 			if (settings.elseBracketOnSameLine)
285
 		}
318
 		}
286
 	}
319
 	}
287
 	
320
 	
288
-	private void beginSingleLine() {
321
+	private void beginSingleLine(WhitespaceInfo whitespace) {
289
 		result.append(settings.getSingleLineSeparator(indent, position));
322
 		result.append(settings.getSingleLineSeparator(indent, position));
323
+		
324
+		if (whitespace != null) {
325
+			if (whitespace.emptyLine) {
326
+				result.append("\n").append(indent);
327
+			}
328
+			writeComments(whitespace.commentsBefore);
329
+		}
290
 	}
330
 	}
291
 	
331
 	
292
-	private void endSingleLine() {
332
+	private void endSingleLine(WhitespaceInfo whitespace) {
333
+		if (whitespace != null && !whitespace.commentsAfter.isEmpty())
334
+			result.append(' ').append(whitespace.commentsAfter);
335
+		
293
 		if (position == ParentStatementType.IF_WITH_ELSE)
336
 		if (position == ParentStatementType.IF_WITH_ELSE)
294
 			result.append("\n").append(indent);
337
 			result.append("\n").append(indent);
295
 	}
338
 	}
339
+	
340
+	private void writeComments(String[] comments) {
341
+		for (String comment : CommentFormatter.format(comments)) {
342
+			result.append(comment).append("\n").append(indent);
343
+		}
344
+	}
345
+	
346
+	private void writePostComments(String[] comments) {
347
+		for (String comment : CommentFormatter.format(comments)) {
348
+			result.append("\n").append(indent).append(comment);
349
+		}
350
+	}
296
 }
351
 }

+ 49
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/WhitespaceInfo.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.codemodel;
7
+
8
+import java.util.ArrayList;
9
+import java.util.List;
10
+import org.openzen.zenscript.shared.StringUtils;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class WhitespaceInfo {
17
+	public static WhitespaceInfo from(String whitespaceBefore, String lineAfter) {
18
+		int numNewLines = 0;
19
+		for (char c : whitespaceBefore.toCharArray())
20
+			if (c == '\n')
21
+				numNewLines++;
22
+		
23
+		List<String> split = StringUtils.split(whitespaceBefore, '\n');
24
+		List<String> commentsBefore = new ArrayList<>();
25
+		for (String splitLine : split) {
26
+			String trimmed = splitLine.trim();
27
+			if (trimmed.isEmpty())
28
+				continue;
29
+			
30
+			commentsBefore.add(trimmed);
31
+		}
32
+		
33
+		boolean emptyLine = numNewLines - commentsBefore.size() > 0;
34
+		return new WhitespaceInfo(
35
+				emptyLine,
36
+				commentsBefore.toArray(new String[commentsBefore.size()]),
37
+				lineAfter.trim());
38
+	}
39
+	
40
+	public boolean emptyLine;
41
+	public String[] commentsBefore;
42
+	public String commentsAfter;
43
+	
44
+	public WhitespaceInfo(boolean emptyLine, String[] commentsBefore, String commentsAfter) {
45
+		this.emptyLine = emptyLine;
46
+		this.commentsBefore = commentsBefore;
47
+		this.commentsAfter = commentsAfter;
48
+	}
49
+}

+ 38
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/WhitespacePostComment.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.codemodel;
7
+
8
+import java.util.ArrayList;
9
+import java.util.List;
10
+import org.openzen.zenscript.shared.StringUtils;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class WhitespacePostComment {
17
+	public static WhitespacePostComment fromWhitespace(String whitespace) {
18
+		List<String> comments = new ArrayList<>();
19
+		for (String line : StringUtils.split(whitespace, '\n')) {
20
+			line = line.trim();
21
+			if (line.isEmpty())
22
+				continue;
23
+			
24
+			comments.add(line);
25
+		}
26
+		
27
+		if (comments.isEmpty())
28
+			return null;
29
+		
30
+		return new WhitespacePostComment(comments.toArray(new String[comments.size()]));
31
+	}
32
+	
33
+	public final String[] comments;
34
+	
35
+	public WhitespacePostComment(String[] comments) {
36
+		this.comments = comments;
37
+	}
38
+}

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/lexer/TokenStream.java View File

294
 					line,
294
 					line,
295
 					lineOffset);
295
 					lineOffset);
296
 			
296
 			
297
-            next = createToken(position, "", "", eof);
297
+            next = createToken(position, whitespace, "", eof);
298
             return;
298
             return;
299
         }
299
         }
300
 		
300
 		

+ 47
- 0
Parser/src/main/java/org/openzen/zenscript/lexer/ZSTokenStream.java View File

9
 import java.io.Reader;
9
 import java.io.Reader;
10
 import java.util.HashMap;
10
 import java.util.HashMap;
11
 import java.util.Map;
11
 import java.util.Map;
12
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
12
 import org.openzen.zenscript.shared.CompileException;
13
 import org.openzen.zenscript.shared.CompileException;
13
 import org.openzen.zenscript.shared.CompileExceptionCode;
14
 import org.openzen.zenscript.shared.CompileExceptionCode;
14
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
15
 import static org.openzen.zenscript.lexer.ZSTokenType.*;
95
 		KEYWORDS.put("new", K_NEW);
96
 		KEYWORDS.put("new", K_NEW);
96
 	}
97
 	}
97
 	
98
 	
99
+	private String whitespaceBuffer = null;
100
+	
98
 	public ZSTokenStream(String filename, Reader reader) {
101
 	public ZSTokenStream(String filename, Reader reader) {
99
 		super(filename, reader, DFA, ZSTokenType.EOF);
102
 		super(filename, reader, DFA, ZSTokenType.EOF);
100
 	}
103
 	}
101
 	
104
 	
105
+	public String loadWhitespace() {
106
+		if (whitespaceBuffer == null)
107
+			whitespaceBuffer = peek().whitespaceBefore;
108
+		
109
+		return whitespaceBuffer;
110
+	}
111
+	
112
+	public void reloadWhitespace() {
113
+		whitespaceBuffer = peek().whitespaceBefore;
114
+	}
115
+	
116
+	public String grabWhitespace() {
117
+		String result = loadWhitespace();
118
+		whitespaceBuffer = null;
119
+		return result;
120
+	}
121
+	
122
+	public String grabWhitespaceLine() {
123
+		String whitespace = loadWhitespace();
124
+		if (whitespace.contains("\n")) {
125
+			int index = whitespace.indexOf('\n');
126
+			whitespaceBuffer = whitespace.substring(index + 1);
127
+			return whitespace.substring(0, index);
128
+		} else {
129
+			whitespaceBuffer = "";
130
+			return whitespace;
131
+		}
132
+	}
133
+	
134
+	public void skipWhitespaceNewline() {
135
+		loadWhitespace();
136
+		int index = whitespaceBuffer.indexOf('\n');
137
+		if (index >= 0)
138
+			whitespaceBuffer = whitespaceBuffer.substring(index + 1);
139
+	}
140
+	
141
+	public WhitespaceInfo collectWhitespaceInfoForBlock(String whitespace) {
142
+		return WhitespaceInfo.from(whitespace, "");
143
+	}
144
+	
145
+	public WhitespaceInfo collectWhitespaceInfo(String whitespace) {
146
+		return WhitespaceInfo.from(whitespace, grabWhitespaceLine());
147
+	}
148
+	
102
 	@Override
149
 	@Override
103
 	protected ZSToken createToken(CodePosition position, String whitespaceBefore, String value, ZSTokenType tokenType) {
150
 	protected ZSToken createToken(CodePosition position, String whitespaceBefore, String value, ZSTokenType tokenType) {
104
 		if (tokenType == T_IDENTIFIER && KEYWORDS.containsKey(value))
151
 		if (tokenType == T_IDENTIFIER && KEYWORDS.containsKey(value))

+ 8
- 2
Parser/src/main/java/org/openzen/zenscript/parser/ParsedFile.java View File

18
 import org.openzen.zenscript.codemodel.Modifiers;
18
 import org.openzen.zenscript.codemodel.Modifiers;
19
 import org.openzen.zenscript.codemodel.PackageDefinitions;
19
 import org.openzen.zenscript.codemodel.PackageDefinitions;
20
 import org.openzen.zenscript.codemodel.ScriptBlock;
20
 import org.openzen.zenscript.codemodel.ScriptBlock;
21
+import org.openzen.zenscript.codemodel.WhitespacePostComment;
21
 import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
22
 import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
22
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
23
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
23
 import org.openzen.zenscript.codemodel.statement.Statement;
24
 import org.openzen.zenscript.codemodel.statement.Statement;
24
 import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
25
 import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
26
+import org.openzen.zenscript.lexer.ZSToken;
25
 import org.openzen.zenscript.shared.CodePosition;
27
 import org.openzen.zenscript.shared.CodePosition;
26
 import org.openzen.zenscript.shared.CompileException;
28
 import org.openzen.zenscript.shared.CompileException;
27
 import org.openzen.zenscript.shared.CompileExceptionCode;
29
 import org.openzen.zenscript.shared.CompileExceptionCode;
58
 		ParsedFile result = new ParsedFile(filename);
60
 		ParsedFile result = new ParsedFile(filename);
59
 		
61
 		
60
 		ZSTokenStream tokens = new ZSTokenStream(filename, reader);
62
 		ZSTokenStream tokens = new ZSTokenStream(filename, reader);
63
+		ZSToken eof = null;
61
 
64
 
62
 		while (true) {
65
 		while (true) {
63
 			CodePosition position = tokens.peek().position;
66
 			CodePosition position = tokens.peek().position;
96
 
99
 
97
 			if (tokens.optional(K_IMPORT) != null) {
100
 			if (tokens.optional(K_IMPORT) != null) {
98
 				result.imports.add(ParsedImport.parse(position, tokens));
101
 				result.imports.add(ParsedImport.parse(position, tokens));
99
-			} else if (tokens.optional(EOF) != null) {
102
+			} else if ((eof = tokens.optional(EOF)) != null) {
100
 				break;
103
 				break;
101
 			} else {
104
 			} else {
102
 				ParsedDefinition definition = ParsedDefinition.parse(pkg, position, modifiers, tokens, null);
105
 				ParsedDefinition definition = ParsedDefinition.parse(pkg, position, modifiers, tokens, null);
110
 			}
113
 			}
111
 		}
114
 		}
112
 		
115
 		
116
+		result.postComment = WhitespacePostComment.fromWhitespace(eof.whitespaceBefore);
113
 		return result;
117
 		return result;
114
 	}
118
 	}
115
 	
119
 	
119
 	private final List<ParsedDefinition> definitions = new ArrayList<>();
123
 	private final List<ParsedDefinition> definitions = new ArrayList<>();
120
 	private final List<ParsedStatement> statements = new ArrayList<>();
124
 	private final List<ParsedStatement> statements = new ArrayList<>();
121
 	private final AccessScope access = new AccessScope();
125
 	private final AccessScope access = new AccessScope();
126
+	private WhitespacePostComment postComment = null;
122
 	
127
 	
123
 	public ParsedFile(String filename) {
128
 	public ParsedFile(String filename) {
124
 		this.filename = filename;
129
 		this.filename = filename;
165
 			definition.compileCode(scope);
170
 			definition.compileCode(scope);
166
 		}
171
 		}
167
 		
172
 		
168
-		if (!statements.isEmpty()) {
173
+		if (!statements.isEmpty() || postComment != null) {
169
 			StatementScope statementScope = new GlobalScriptScope(scope);
174
 			StatementScope statementScope = new GlobalScriptScope(scope);
170
 			List<Statement> statements = new ArrayList<>();
175
 			List<Statement> statements = new ArrayList<>();
171
 			for (ParsedStatement statement : this.statements) {
176
 			for (ParsedStatement statement : this.statements) {
174
 			
179
 			
175
 			ScriptBlock block = new ScriptBlock(statements);
180
 			ScriptBlock block = new ScriptBlock(statements);
176
 			block.setTag(SourceFile.class, new SourceFile(filename));
181
 			block.setTag(SourceFile.class, new SourceFile(filename));
182
+			block.setTag(WhitespacePostComment.class, postComment);
177
 			scripts.add(block);
183
 			scripts.add(block);
178
 		}
184
 		}
179
 	}
185
 	}

+ 61
- 14
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatement.java View File

2
 
2
 
3
 import java.util.ArrayList;
3
 import java.util.ArrayList;
4
 import java.util.List;
4
 import java.util.List;
5
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
6
+import org.openzen.zenscript.codemodel.WhitespacePostComment;
5
 import org.openzen.zenscript.codemodel.statement.Statement;
7
 import org.openzen.zenscript.codemodel.statement.Statement;
6
 import org.openzen.zenscript.lexer.ZSToken;
8
 import org.openzen.zenscript.lexer.ZSToken;
7
 import org.openzen.zenscript.lexer.ZSTokenStream;
9
 import org.openzen.zenscript.lexer.ZSTokenStream;
45
 	}
47
 	}
46
 	
48
 	
47
 	public static ParsedStatement parse(ZSTokenStream parser) {
49
 	public static ParsedStatement parse(ZSTokenStream parser) {
50
+		String ws = parser.grabWhitespace();
48
 		ZSToken next = parser.peek();
51
 		ZSToken next = parser.peek();
49
 		switch (next.getType()) {
52
 		switch (next.getType()) {
50
 			case T_AOPEN: {
53
 			case T_AOPEN: {
51
 				ZSToken t = parser.next();
54
 				ZSToken t = parser.next();
55
+				
56
+				parser.reloadWhitespace();
57
+				parser.skipWhitespaceNewline();
58
+				
52
 				ArrayList<ParsedStatement> statements = new ArrayList<>();
59
 				ArrayList<ParsedStatement> statements = new ArrayList<>();
53
-				while (parser.optional(T_ACLOSE) == null) {
60
+				ZSToken last;
61
+				while ((last = parser.optional(T_ACLOSE)) == null) {
54
 					statements.add(parse(parser));
62
 					statements.add(parse(parser));
55
 				}
63
 				}
56
-				return new ParsedStatementBlock(t.getPosition(), statements);
64
+				
65
+				parser.reloadWhitespace();
66
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfoForBlock(ws);
67
+				WhitespacePostComment postComment = WhitespacePostComment.fromWhitespace(last.whitespaceBefore);
68
+				return new ParsedStatementBlock(t.getPosition(), whitespace, postComment, statements);
57
 			}
69
 			}
58
 			case K_RETURN: {
70
 			case K_RETURN: {
59
 				parser.next();
71
 				parser.next();
62
 					expression = ParsedExpression.parse(parser);
74
 					expression = ParsedExpression.parse(parser);
63
 				}
75
 				}
64
 				parser.required(T_SEMICOLON, "; expected");
76
 				parser.required(T_SEMICOLON, "; expected");
65
-				return new ParsedStatementReturn(next.getPosition(), expression);
77
+				
78
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
79
+				return new ParsedStatementReturn(next.getPosition(), whitespace, expression);
66
 			}
80
 			}
67
 			case K_VAR:
81
 			case K_VAR:
68
 			case K_VAL: {
82
 			case K_VAL: {
78
 					initializer = ParsedExpression.parse(parser);
92
 					initializer = ParsedExpression.parse(parser);
79
 				}
93
 				}
80
 				parser.required(T_SEMICOLON, "; expected");
94
 				parser.required(T_SEMICOLON, "; expected");
81
-				return new ParsedStatementVar(start.getPosition(), name, type, initializer, start.getType() == K_VAL);
95
+				
96
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
97
+				return new ParsedStatementVar(start.getPosition(), whitespace, name, type, initializer, start.getType() == K_VAL);
82
 			}
98
 			}
83
 			case K_IF: {
99
 			case K_IF: {
84
 				ZSToken t = parser.next();
100
 				ZSToken t = parser.next();
85
 				ParsedExpression expression = ParsedExpression.parse(parser);
101
 				ParsedExpression expression = ParsedExpression.parse(parser);
102
+				parser.skipWhitespaceNewline();
86
 				ParsedStatement onIf = parse(parser);
103
 				ParsedStatement onIf = parse(parser);
87
 				ParsedStatement onElse = null;
104
 				ParsedStatement onElse = null;
88
 				if (parser.optional(K_ELSE) != null) {
105
 				if (parser.optional(K_ELSE) != null) {
106
+					parser.reloadWhitespace();
107
+					parser.skipWhitespaceNewline();
89
 					onElse = parse(parser);
108
 					onElse = parse(parser);
90
 				}
109
 				}
91
-				return new ParsedStatementIf(t.getPosition(), expression, onIf, onElse);
110
+				
111
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
112
+				return new ParsedStatementIf(t.getPosition(), whitespace, expression, onIf, onElse);
92
 			}
113
 			}
93
 			case K_FOR: {
114
 			case K_FOR: {
94
 				ZSToken t = parser.next();
115
 				ZSToken t = parser.next();
103
 				parser.required(K_IN, "in expected");
124
 				parser.required(K_IN, "in expected");
104
 				ParsedExpression source = ParsedExpression.parse(parser);
125
 				ParsedExpression source = ParsedExpression.parse(parser);
105
 				ParsedStatement content = parse(parser);
126
 				ParsedStatement content = parse(parser);
127
+				
128
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
106
 				return new ParsedStatementForeach(
129
 				return new ParsedStatementForeach(
107
 						t.getPosition(),
130
 						t.getPosition(),
131
+						whitespace,
108
 						names.toArray(new String[names.size()]),
132
 						names.toArray(new String[names.size()]),
109
 						source,
133
 						source,
110
 						content);
134
 						content);
119
 				parser.required(K_WHILE, "while expected");
143
 				parser.required(K_WHILE, "while expected");
120
 				ParsedExpression condition = ParsedExpression.parse(parser);
144
 				ParsedExpression condition = ParsedExpression.parse(parser);
121
 				parser.required(T_SEMICOLON, "; expected");
145
 				parser.required(T_SEMICOLON, "; expected");
122
-				return new ParsedStatementDoWhile(t.position, label, content, condition);
146
+				
147
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
148
+				return new ParsedStatementDoWhile(t.position, whitespace, label, content, condition);
123
 			}
149
 			}
124
 			case K_WHILE: {
150
 			case K_WHILE: {
125
 				ZSToken t = parser.next();
151
 				ZSToken t = parser.next();
129
 				
155
 				
130
 				ParsedExpression condition = ParsedExpression.parse(parser);
156
 				ParsedExpression condition = ParsedExpression.parse(parser);
131
 				ParsedStatement content = parse(parser);
157
 				ParsedStatement content = parse(parser);
132
-				return new ParsedStatementWhile(t.position, label, condition, content);
158
+				
159
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
160
+				return new ParsedStatementWhile(t.position, whitespace, label, condition, content);
133
 			}
161
 			}
134
 			case K_LOCK: {
162
 			case K_LOCK: {
135
 				ZSToken t = parser.next();
163
 				ZSToken t = parser.next();
136
 				ParsedExpression object = ParsedExpression.parse(parser);
164
 				ParsedExpression object = ParsedExpression.parse(parser);
137
 				ParsedStatement content = parse(parser);
165
 				ParsedStatement content = parse(parser);
138
-				return new ParsedStatementLock(t.position, object, content);
166
+				
167
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
168
+				return new ParsedStatementLock(t.position, whitespace, object, content);
139
 			}
169
 			}
140
 			case K_THROW: {
170
 			case K_THROW: {
141
 				ZSToken t = parser.next();
171
 				ZSToken t = parser.next();
142
 				ParsedExpression value = ParsedExpression.parse(parser);
172
 				ParsedExpression value = ParsedExpression.parse(parser);
143
 				parser.required(T_SEMICOLON, "; expected");
173
 				parser.required(T_SEMICOLON, "; expected");
144
-				return new ParsedStatementThrow(t.position, value);
174
+				
175
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
176
+				return new ParsedStatementThrow(t.position, whitespace, value);
145
 			}
177
 			}
146
 			case K_TRY: {
178
 			case K_TRY: {
147
 				ZSToken t = parser.next();
179
 				ZSToken t = parser.next();
174
 				if (parser.optional(K_FINALLY) != null)
206
 				if (parser.optional(K_FINALLY) != null)
175
 					finallyClause = ParsedStatement.parse(parser);
207
 					finallyClause = ParsedStatement.parse(parser);
176
 				
208
 				
177
-				return new ParsedStatementTryCatch(t.position, name, initializer, content, catchClauses, finallyClause);
209
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
210
+				return new ParsedStatementTryCatch(t.position, whitespace, name, initializer, content, catchClauses, finallyClause);
178
 			}
211
 			}
179
 			case K_CONTINUE: {
212
 			case K_CONTINUE: {
180
 				ZSToken t = parser.next();
213
 				ZSToken t = parser.next();
183
 					name = parser.next().content;
216
 					name = parser.next().content;
184
 				
217
 				
185
 				parser.required(T_SEMICOLON, "; expected");
218
 				parser.required(T_SEMICOLON, "; expected");
186
-				return new ParsedStatementContinue(t.position, name);
219
+				
220
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
221
+				return new ParsedStatementContinue(t.position, whitespace, name);
187
 			}
222
 			}
188
 			case K_BREAK: {
223
 			case K_BREAK: {
189
 				ZSToken t = parser.next();
224
 				ZSToken t = parser.next();
192
 					name = parser.next().content;
227
 					name = parser.next().content;
193
 				
228
 				
194
 				parser.required(T_SEMICOLON, "; expected");
229
 				parser.required(T_SEMICOLON, "; expected");
195
-				return new ParsedStatementBreak(t.position, name);
230
+				
231
+				WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
232
+				return new ParsedStatementBreak(t.position, whitespace, name);
196
 			}
233
 			}
197
 		}
234
 		}
198
 
235
 
199
 		CodePosition position = parser.peek().getPosition();
236
 		CodePosition position = parser.peek().getPosition();
200
-		ParsedStatementExpression result = new ParsedStatementExpression(position, ParsedExpression.parse(parser));
237
+		ParsedExpression expression = ParsedExpression.parse(parser);
201
 		parser.required(T_SEMICOLON, "; expected");
238
 		parser.required(T_SEMICOLON, "; expected");
239
+		WhitespaceInfo whitespace = parser.collectWhitespaceInfo(ws);
240
+		
241
+		ParsedStatementExpression result = new ParsedStatementExpression(position, whitespace, expression);
202
 		return result;
242
 		return result;
203
 	}
243
 	}
204
 	
244
 	
213
 	}
253
 	}
214
 
254
 
215
 	public final CodePosition position;
255
 	public final CodePosition position;
256
+	public final WhitespaceInfo whitespace;
216
 
257
 
217
-	public ParsedStatement(CodePosition position) {
258
+	public ParsedStatement(CodePosition position, WhitespaceInfo whitespace) {
218
 		this.position = position;
259
 		this.position = position;
260
+		this.whitespace = whitespace;
219
 	}
261
 	}
220
 
262
 
221
 	public abstract Statement compile(StatementScope scope);
263
 	public abstract Statement compile(StatementScope scope);
264
+	
265
+	protected Statement result(Statement statement) {
266
+		statement.setTag(WhitespaceInfo.class, whitespace);
267
+		return statement;
268
+	}
222
 }
269
 }

+ 11
- 4
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementBlock.java View File

2
 
2
 
3
 import java.util.ArrayList;
3
 import java.util.ArrayList;
4
 import java.util.List;
4
 import java.util.List;
5
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
6
+import org.openzen.zenscript.codemodel.WhitespacePostComment;
5
 import org.openzen.zenscript.codemodel.statement.BlockStatement;
7
 import org.openzen.zenscript.codemodel.statement.BlockStatement;
6
 import org.openzen.zenscript.codemodel.statement.Statement;
8
 import org.openzen.zenscript.codemodel.statement.Statement;
7
 import org.openzen.zenscript.linker.BlockScope;
9
 import org.openzen.zenscript.linker.BlockScope;
10
 
12
 
11
 public class ParsedStatementBlock extends ParsedStatement {
13
 public class ParsedStatementBlock extends ParsedStatement {
12
 	private final List<ParsedStatement> statements;
14
 	private final List<ParsedStatement> statements;
13
-
14
-	public ParsedStatementBlock(CodePosition position, List<ParsedStatement> statements) {
15
-		super(position);
15
+	private final WhitespacePostComment postComment;
16
+	
17
+	public ParsedStatementBlock(CodePosition position, WhitespaceInfo whitespace, WhitespacePostComment postComment, List<ParsedStatement> statements) {
18
+		super(position, whitespace);
16
 
19
 
17
 		this.statements = statements;
20
 		this.statements = statements;
21
+		this.postComment = postComment;
18
 	}
22
 	}
19
 
23
 
20
 	@Override
24
 	@Override
24
 		for (ParsedStatement statement : statements) {
28
 		for (ParsedStatement statement : statements) {
25
 			compiled.add(statement.compile(blockScope));
29
 			compiled.add(statement.compile(blockScope));
26
 		}
30
 		}
27
-		return new BlockStatement(position, compiled);
31
+		BlockStatement block = new BlockStatement(position, compiled);
32
+		result(block);
33
+		block.setTag(WhitespacePostComment.class, postComment);
34
+		return block;
28
 	}
35
 	}
29
 }
36
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementBreak.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.statement.BreakStatement;
9
 import org.openzen.zenscript.codemodel.statement.BreakStatement;
9
 import org.openzen.zenscript.codemodel.statement.LoopStatement;
10
 import org.openzen.zenscript.codemodel.statement.LoopStatement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
20
 public class ParsedStatementBreak extends ParsedStatement {
21
 public class ParsedStatementBreak extends ParsedStatement {
21
 	public final String name;
22
 	public final String name;
22
 	
23
 	
23
-	public ParsedStatementBreak(CodePosition position, String name) {
24
-		super(position);
24
+	public ParsedStatementBreak(CodePosition position, WhitespaceInfo whitespace, String name) {
25
+		super(position, whitespace);
25
 		
26
 		
26
 		this.name = name;
27
 		this.name = name;
27
 	}
28
 	}
31
 		LoopStatement target = scope.getLoop(name);
32
 		LoopStatement target = scope.getLoop(name);
32
 		if (target == null)
33
 		if (target == null)
33
 			throw new CompileException(position, CompileExceptionCode.BREAK_OUTSIDE_LOOP, name == null ? "Not in a loop" : "No such loop: " + name);
34
 			throw new CompileException(position, CompileExceptionCode.BREAK_OUTSIDE_LOOP, name == null ? "Not in a loop" : "No such loop: " + name);
34
-		return new BreakStatement(position, target);
35
+		return result(new BreakStatement(position, target));
35
 	}
36
 	}
36
 }
37
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementContinue.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.statement.ContinueStatement;
9
 import org.openzen.zenscript.codemodel.statement.ContinueStatement;
9
 import org.openzen.zenscript.codemodel.statement.LoopStatement;
10
 import org.openzen.zenscript.codemodel.statement.LoopStatement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
20
 public class ParsedStatementContinue extends ParsedStatement {
21
 public class ParsedStatementContinue extends ParsedStatement {
21
 	public final String name;
22
 	public final String name;
22
 	
23
 	
23
-	public ParsedStatementContinue(CodePosition position, String name) {
24
-		super(position);
24
+	public ParsedStatementContinue(CodePosition position, WhitespaceInfo whitespace, String name) {
25
+		super(position, whitespace);
25
 		
26
 		
26
 		this.name = name;
27
 		this.name = name;
27
 	}
28
 	}
31
 		LoopStatement target = scope.getLoop(name);
32
 		LoopStatement target = scope.getLoop(name);
32
 		if (target == null)
33
 		if (target == null)
33
 			throw new CompileException(position, CompileExceptionCode.CONTINUE_OUTSIDE_LOOP, name == null ? "Not in a loop" : "No such loop: " + name);
34
 			throw new CompileException(position, CompileExceptionCode.CONTINUE_OUTSIDE_LOOP, name == null ? "Not in a loop" : "No such loop: " + name);
34
-		return new ContinueStatement(position, target);
35
+		return result(new ContinueStatement(position, target));
35
 	}
36
 	}
36
 }
37
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementDoWhile.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.statement.DoWhileStatement;
10
 import org.openzen.zenscript.codemodel.statement.DoWhileStatement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
24
 	public final ParsedStatement content;
25
 	public final ParsedStatement content;
25
 	public final ParsedExpression condition;
26
 	public final ParsedExpression condition;
26
 	
27
 	
27
-	public ParsedStatementDoWhile(CodePosition position, String label, ParsedStatement content, ParsedExpression condition) {
28
-		super(position);
28
+	public ParsedStatementDoWhile(CodePosition position, WhitespaceInfo whitespace, String label, ParsedStatement content, ParsedExpression condition) {
29
+		super(position, whitespace);
29
 		
30
 		
30
 		this.label = label;
31
 		this.label = label;
31
 		this.content = content;
32
 		this.content = content;
43
 		DoWhileStatement result = new DoWhileStatement(position, label, condition);
44
 		DoWhileStatement result = new DoWhileStatement(position, label, condition);
44
 		LoopScope innerScope = new LoopScope(result, scope);
45
 		LoopScope innerScope = new LoopScope(result, scope);
45
 		result.content = this.content.compile(innerScope);
46
 		result.content = this.content.compile(innerScope);
46
-		return result;
47
+		return result(result);
47
 	}
48
 	}
48
 }
49
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementExpression.java View File

1
 package org.openzen.zenscript.parser.statements;
1
 package org.openzen.zenscript.parser.statements;
2
 
2
 
3
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
3
 import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
4
 import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
4
 import org.openzen.zenscript.codemodel.statement.Statement;
5
 import org.openzen.zenscript.codemodel.statement.Statement;
5
 import org.openzen.zenscript.linker.ExpressionScope;
6
 import org.openzen.zenscript.linker.ExpressionScope;
10
 public class ParsedStatementExpression extends ParsedStatement {
11
 public class ParsedStatementExpression extends ParsedStatement {
11
 	private final ParsedExpression expression;
12
 	private final ParsedExpression expression;
12
 
13
 
13
-	public ParsedStatementExpression(CodePosition position, ParsedExpression expression) {
14
-		super(position);
14
+	public ParsedStatementExpression(CodePosition position, WhitespaceInfo whitespace, ParsedExpression expression) {
15
+		super(position, whitespace);
15
 
16
 
16
 		this.expression = expression;
17
 		this.expression = expression;
17
 	}
18
 	}
18
 
19
 
19
 	@Override
20
 	@Override
20
 	public Statement compile(StatementScope scope) {
21
 	public Statement compile(StatementScope scope) {
21
-		return new ExpressionStatement(position, this.expression.compile(new ExpressionScope(scope)).eval());
22
+		return result(new ExpressionStatement(position, this.expression.compile(new ExpressionScope(scope)).eval()));
22
 	}
23
 	}
23
 }
24
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementForeach.java View File

1
 package org.openzen.zenscript.parser.statements;
1
 package org.openzen.zenscript.parser.statements;
2
 
2
 
3
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
3
 import org.openzen.zenscript.codemodel.expression.Expression;
4
 import org.openzen.zenscript.codemodel.expression.Expression;
4
 import org.openzen.zenscript.codemodel.member.IIteratorMember;
5
 import org.openzen.zenscript.codemodel.member.IIteratorMember;
5
 import org.openzen.zenscript.codemodel.statement.ForeachStatement;
6
 import org.openzen.zenscript.codemodel.statement.ForeachStatement;
19
 	private final ParsedExpression list;
20
 	private final ParsedExpression list;
20
 	private final ParsedStatement body;
21
 	private final ParsedStatement body;
21
 
22
 
22
-	public ParsedStatementForeach(CodePosition position, String[] varnames, ParsedExpression list, ParsedStatement body) {
23
-		super(position);
23
+	public ParsedStatementForeach(CodePosition position, WhitespaceInfo whitespace, String[] varnames, ParsedExpression list, ParsedStatement body) {
24
+		super(position, whitespace);
24
 
25
 
25
 		this.varnames = varnames;
26
 		this.varnames = varnames;
26
 		this.list = list;
27
 		this.list = list;
43
 		ForeachStatement statement = new ForeachStatement(position, variables, iterator, list);
44
 		ForeachStatement statement = new ForeachStatement(position, variables, iterator, list);
44
 		ForeachScope innerScope = new ForeachScope(statement, scope);
45
 		ForeachScope innerScope = new ForeachScope(statement, scope);
45
 		statement.content = this.body.compile(innerScope);
46
 		statement.content = this.body.compile(innerScope);
46
-		return statement;
47
+		return result(statement);
47
 	}
48
 	}
48
 }
49
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementIf.java View File

1
 package org.openzen.zenscript.parser.statements;
1
 package org.openzen.zenscript.parser.statements;
2
 
2
 
3
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
3
 import org.openzen.zenscript.codemodel.expression.Expression;
4
 import org.openzen.zenscript.codemodel.expression.Expression;
4
 import org.openzen.zenscript.codemodel.statement.IfStatement;
5
 import org.openzen.zenscript.codemodel.statement.IfStatement;
5
 import org.openzen.zenscript.codemodel.statement.Statement;
6
 import org.openzen.zenscript.codemodel.statement.Statement;
14
 	private final ParsedStatement onThen;
15
 	private final ParsedStatement onThen;
15
 	private final ParsedStatement onElse;
16
 	private final ParsedStatement onElse;
16
 
17
 
17
-	public ParsedStatementIf(CodePosition position, ParsedExpression condition, ParsedStatement onThen, ParsedStatement onElse) {
18
-		super(position);
18
+	public ParsedStatementIf(CodePosition position, WhitespaceInfo whitespace, ParsedExpression condition, ParsedStatement onThen, ParsedStatement onElse) {
19
+		super(position, whitespace);
19
 
20
 
20
 		this.condition = condition;
21
 		this.condition = condition;
21
 		this.onThen = onThen;
22
 		this.onThen = onThen;
27
 		Expression condition = this.condition.compile(new ExpressionScope(scope, BasicTypeID.HINT_BOOL)).eval();
28
 		Expression condition = this.condition.compile(new ExpressionScope(scope, BasicTypeID.HINT_BOOL)).eval();
28
 		Statement onThen = this.onThen.compile(scope);
29
 		Statement onThen = this.onThen.compile(scope);
29
 		Statement onElse = this.onElse == null ? null : this.onElse.compile(scope);
30
 		Statement onElse = this.onElse == null ? null : this.onElse.compile(scope);
30
-		return new IfStatement(position, condition, onThen, onElse);
31
+		return result(new IfStatement(position, condition, onThen, onElse));
31
 	}
32
 	}
32
 }
33
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementLock.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.statement.LockStatement;
10
 import org.openzen.zenscript.codemodel.statement.LockStatement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
21
 	public final ParsedExpression object;
22
 	public final ParsedExpression object;
22
 	public final ParsedStatement content;
23
 	public final ParsedStatement content;
23
 	
24
 	
24
-	public ParsedStatementLock(CodePosition position, ParsedExpression object, ParsedStatement content) {
25
-		super(position);
25
+	public ParsedStatementLock(CodePosition position, WhitespaceInfo whitespace, ParsedExpression object, ParsedStatement content) {
26
+		super(position, whitespace);
26
 		
27
 		
27
 		this.object = object;
28
 		this.object = object;
28
 		this.content = content;
29
 		this.content = content;
32
 	public Statement compile(StatementScope scope) {
33
 	public Statement compile(StatementScope scope) {
33
 		Expression object = this.object.compile(new ExpressionScope(scope)).eval();
34
 		Expression object = this.object.compile(new ExpressionScope(scope)).eval();
34
 		Statement content = this.content.compile(scope);
35
 		Statement content = this.content.compile(scope);
35
-		return new LockStatement(position, object, content);
36
+		return result(new LockStatement(position, object, content));
36
 	}
37
 	}
37
 }
38
 }

+ 4
- 4
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementNull.java View File

6
 
6
 
7
 package org.openzen.zenscript.parser.statements;
7
 package org.openzen.zenscript.parser.statements;
8
 
8
 
9
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
9
 import org.openzen.zenscript.codemodel.statement.EmptyStatement;
10
 import org.openzen.zenscript.codemodel.statement.EmptyStatement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.linker.StatementScope;
12
 import org.openzen.zenscript.linker.StatementScope;
12
-import org.openzen.zenscript.parser.statements.ParsedStatement;
13
 import org.openzen.zenscript.shared.CodePosition;
13
 import org.openzen.zenscript.shared.CodePosition;
14
 
14
 
15
 /**
15
 /**
17
  * @author Stanneke
17
  * @author Stanneke
18
  */
18
  */
19
 public class ParsedStatementNull extends ParsedStatement {
19
 public class ParsedStatementNull extends ParsedStatement {
20
-	public ParsedStatementNull(CodePosition position) {
21
-		super(position);
20
+	public ParsedStatementNull(CodePosition position, WhitespaceInfo whitespace) {
21
+		super(position, whitespace);
22
 	}
22
 	}
23
 
23
 
24
 	@Override
24
 	@Override
25
 	public Statement compile(StatementScope scope) {
25
 	public Statement compile(StatementScope scope) {
26
-		return new EmptyStatement(position);
26
+		return result(new EmptyStatement(position));
27
 	}
27
 	}
28
 }
28
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementReturn.java View File

1
 package org.openzen.zenscript.parser.statements;
1
 package org.openzen.zenscript.parser.statements;
2
 
2
 
3
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
3
 import org.openzen.zenscript.codemodel.expression.Expression;
4
 import org.openzen.zenscript.codemodel.expression.Expression;
4
 import org.openzen.zenscript.codemodel.statement.ReturnStatement;
5
 import org.openzen.zenscript.codemodel.statement.ReturnStatement;
5
 import org.openzen.zenscript.codemodel.statement.Statement;
6
 import org.openzen.zenscript.codemodel.statement.Statement;
14
 public class ParsedStatementReturn extends ParsedStatement {
15
 public class ParsedStatementReturn extends ParsedStatement {
15
 	private final ParsedExpression expression;
16
 	private final ParsedExpression expression;
16
 
17
 
17
-	public ParsedStatementReturn(CodePosition position, ParsedExpression expression) {
18
-		super(position);
18
+	public ParsedStatementReturn(CodePosition position, WhitespaceInfo whitespace, ParsedExpression expression) {
19
+		super(position, whitespace);
19
 		
20
 		
20
 		this.expression = expression;
21
 		this.expression = expression;
21
 	}
22
 	}
38
 					.compile(new ExpressionScope(scope, scope.getFunctionHeader().returnType))
39
 					.compile(new ExpressionScope(scope, scope.getFunctionHeader().returnType))
39
 					.eval()
40
 					.eval()
40
 					.castImplicit(position, scope, scope.getFunctionHeader().returnType);
41
 					.castImplicit(position, scope, scope.getFunctionHeader().returnType);
41
-			return new ReturnStatement(position, value);
42
+			return result(new ReturnStatement(position, value));
42
 		}
43
 		}
43
 	}
44
 	}
44
 }
45
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementThrow.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.statement.Statement;
9
 import org.openzen.zenscript.codemodel.statement.Statement;
9
 import org.openzen.zenscript.codemodel.statement.ThrowStatement;
10
 import org.openzen.zenscript.codemodel.statement.ThrowStatement;
10
 import org.openzen.zenscript.linker.ExpressionScope;
11
 import org.openzen.zenscript.linker.ExpressionScope;
19
 public class ParsedStatementThrow extends ParsedStatement {
20
 public class ParsedStatementThrow extends ParsedStatement {
20
 	private final ParsedExpression expression;
21
 	private final ParsedExpression expression;
21
 	
22
 	
22
-	public ParsedStatementThrow(CodePosition position, ParsedExpression expression) {
23
-		super(position);
23
+	public ParsedStatementThrow(CodePosition position, WhitespaceInfo whitespace, ParsedExpression expression) {
24
+		super(position, whitespace);
24
 		
25
 		
25
 		this.expression = expression;
26
 		this.expression = expression;
26
 	}
27
 	}
27
 
28
 
28
 	@Override
29
 	@Override
29
 	public Statement compile(StatementScope scope) {
30
 	public Statement compile(StatementScope scope) {
30
-		return new ThrowStatement(position, expression.compile(new ExpressionScope(scope)).eval());
31
+		return result(new ThrowStatement(position, expression.compile(new ExpressionScope(scope)).eval()));
31
 	}
32
 	}
32
 }
33
 }

+ 4
- 2
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementTryCatch.java View File

7
 
7
 
8
 import java.util.ArrayList;
8
 import java.util.ArrayList;
9
 import java.util.List;
9
 import java.util.List;
10
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
10
 import org.openzen.zenscript.codemodel.expression.Expression;
11
 import org.openzen.zenscript.codemodel.expression.Expression;
11
 import org.openzen.zenscript.codemodel.statement.CatchClause;
12
 import org.openzen.zenscript.codemodel.statement.CatchClause;
12
 import org.openzen.zenscript.codemodel.statement.Statement;
13
 import org.openzen.zenscript.codemodel.statement.Statement;
30
 	
31
 	
31
 	public ParsedStatementTryCatch(
32
 	public ParsedStatementTryCatch(
32
 			CodePosition position,
33
 			CodePosition position,
34
+			WhitespaceInfo whitespace,
33
 			String resourceName,
35
 			String resourceName,
34
 			ParsedExpression resourceInitializer,
36
 			ParsedExpression resourceInitializer,
35
 			ParsedStatement statement,
37
 			ParsedStatement statement,
36
 			List<ParsedCatchClause> catchClauses,
38
 			List<ParsedCatchClause> catchClauses,
37
 			ParsedStatement finallyClause) {
39
 			ParsedStatement finallyClause) {
38
-		super(position);
40
+		super(position, whitespace);
39
 		
41
 		
40
 		this.resourceName = resourceName;
42
 		this.resourceName = resourceName;
41
 		this.resourceInitializer = resourceInitializer;
43
 		this.resourceInitializer = resourceInitializer;
57
 		if (resourceName != null) {
59
 		if (resourceName != null) {
58
 			resource = new VarStatement(position, resourceName, resourceInitializer.type, resourceInitializer, true);
60
 			resource = new VarStatement(position, resourceName, resourceInitializer.type, resourceInitializer, true);
59
 		}
61
 		}
60
-		return new TryCatchStatement(position, resource, statement, catches, finallyClause);
62
+		return result(new TryCatchStatement(position, resource, statement, catches, finallyClause));
61
 	}
63
 	}
62
 }
64
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementVar.java View File

6
 
6
 
7
 package org.openzen.zenscript.parser.statements;
7
 package org.openzen.zenscript.parser.statements;
8
 
8
 
9
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
9
 import org.openzen.zenscript.codemodel.expression.Expression;
10
 import org.openzen.zenscript.codemodel.expression.Expression;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.statement.VarStatement;
12
 import org.openzen.zenscript.codemodel.statement.VarStatement;
27
 	private final ParsedExpression initializer;
28
 	private final ParsedExpression initializer;
28
 	private final boolean isFinal;
29
 	private final boolean isFinal;
29
 
30
 
30
-	public ParsedStatementVar(CodePosition position, String name, IParsedType type, ParsedExpression initializer, boolean isFinal) {
31
-		super(position);
31
+	public ParsedStatementVar(CodePosition position, WhitespaceInfo whitespace, String name, IParsedType type, ParsedExpression initializer, boolean isFinal) {
32
+		super(position, whitespace);
32
 
33
 
33
 		this.name = name;
34
 		this.name = name;
34
 		this.type = type;
35
 		this.type = type;
49
 		}
50
 		}
50
 		VarStatement result = new VarStatement(position, name, type, initializer, isFinal);
51
 		VarStatement result = new VarStatement(position, name, type, initializer, isFinal);
51
 		scope.defineVariable(result);
52
 		scope.defineVariable(result);
52
-		return result;
53
+		return result(result);
53
 	}
54
 	}
54
 }
55
 }

+ 4
- 3
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementWhile.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.WhitespaceInfo;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.statement.Statement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
10
 import org.openzen.zenscript.codemodel.statement.WhileStatement;
11
 import org.openzen.zenscript.codemodel.statement.WhileStatement;
24
 	public final ParsedStatement content;
25
 	public final ParsedStatement content;
25
 	public final String label;
26
 	public final String label;
26
 	
27
 	
27
-	public ParsedStatementWhile(CodePosition position, String label, ParsedExpression condition, ParsedStatement content) {
28
-		super(position);
28
+	public ParsedStatementWhile(CodePosition position, WhitespaceInfo whitespace, String label, ParsedExpression condition, ParsedStatement content) {
29
+		super(position, whitespace);
29
 		
30
 		
30
 		this.condition = condition;
31
 		this.condition = condition;
31
 		this.content = content;
32
 		this.content = content;
42
 		WhileStatement result = new WhileStatement(position, label, condition);
43
 		WhileStatement result = new WhileStatement(position, label, condition);
43
 		LoopScope innerScope = new LoopScope(result, scope);
44
 		LoopScope innerScope = new LoopScope(result, scope);
44
 		result.content = this.content.compile(innerScope);
45
 		result.content = this.content.compile(innerScope);
45
-		return result;
46
+		return result(result);
46
 	}
47
 	}
47
 }
48
 }

+ 26
- 0
Shared/src/main/java/org/openzen/zenscript/shared/StringUtils.java View File

7
 
7
 
8
 import java.io.IOException;
8
 import java.io.IOException;
9
 import java.io.InputStream;
9
 import java.io.InputStream;
10
+import java.util.ArrayList;
10
 import java.util.Collection;
11
 import java.util.Collection;
11
 import java.util.HashMap;
12
 import java.util.HashMap;
13
+import java.util.List;
12
 import java.util.Map;
14
 import java.util.Map;
13
 import java.util.Properties;
15
 import java.util.Properties;
14
 import java.util.logging.Level;
16
 import java.util.logging.Level;
45
 			NAMED_CHARACTER_ENTITIES.put(entity.stringValue, entity);
47
 			NAMED_CHARACTER_ENTITIES.put(entity.stringValue, entity);
46
 		}
48
 		}
47
 	}
49
 	}
50
+
51
+	/**
52
+	 * Splits a string in parts, given a specified delimiter.
53
+	 *
54
+	 * @param value string to be split
55
+	 * @param delimiter delimiter
56
+	 * @return split string
57
+	 */
58
+	public static List<String> split(String value, char delimiter)
59
+	{
60
+		if (value == null)
61
+			return null;
62
+
63
+		List<String> result = new ArrayList<>();
64
+		int start = 0;
65
+		for (int i = 0; i < value.length(); i++) {
66
+			if (value.charAt(i) == delimiter) {
67
+				result.add(value.substring(start, i));
68
+				start = i + 1;
69
+			}
70
+		}
71
+		result.add(value.substring(start));
72
+		return result;
73
+	}
48
 	
74
 	
49
 	/**
75
 	/**
50
 	 * Left pads (prefixes) a string with characters until it reaches the given string
76
 	 * Left pads (prefixes) a string with characters until it reaches the given string

+ 3
- 0
Shared/src/main/java/org/openzen/zenscript/shared/TagDictionary.java View File

17
     private Map<Class<?>, Object> tags = Collections.EMPTY_MAP;
17
     private Map<Class<?>, Object> tags = Collections.EMPTY_MAP;
18
 
18
 
19
     public <T> void put(Class<T> cls, T tag) {
19
     public <T> void put(Class<T> cls, T tag) {
20
+		if (tag == null)
21
+			return;
22
+		
20
         if (tags == Collections.EMPTY_MAP) {
23
         if (tags == Collections.EMPTY_MAP) {
21
             tags = Collections.singletonMap(cls, tag);
24
             tags = Collections.singletonMap(cls, tag);
22
         } else if (tags.size() == 1) {
25
         } else if (tags.size() == 1) {

Loading…
Cancel
Save