Skip to content

Commit 0a3771f

Browse files
committed
Add negative and decimal literal support
1 parent 9661fdf commit 0a3771f

File tree

1 file changed

+108
-44
lines changed

1 file changed

+108
-44
lines changed

GDWeave/Script/ScriptTokenizer.cs

Lines changed: 108 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ public static class ScriptTokenizer {
3030
{"setget", TokenType.PrSetget},
3131
{"static", TokenType.PrStatic},
3232

33-
{"void", TokenType.PrVoid},
34-
{"enum", TokenType.PrEnum},
35-
33+
{"void", TokenType.PrVoid}, {"enum", TokenType.PrEnum},
3634
{"preload", TokenType.PrPreload},
3735
{"assert", TokenType.PrAssert},
3836

@@ -182,83 +180,149 @@ public static class ScriptTokenizer {
182180

183181
private static readonly List<string> BuiltinFunctions = Enum.GetNames<BuiltinFunction>().ToList();
184182

183+
private static void InsertNewLine(IEnumerator<string> enumerator, uint baseIndent, List<Token> toFlush) {
184+
if (!enumerator.MoveNext()) {
185+
return;
186+
}
187+
188+
var tabCount = uint.Parse(enumerator.Current);
189+
toFlush.Add(new Token(TokenType.Newline, tabCount + baseIndent));
190+
}
191+
192+
private static void BuildIdentifierName(IEnumerator<string> enumerator, List<Token> toFlush, out string? found) {
193+
found = string.Empty;
194+
if (!enumerator.MoveNext()) {
195+
return;
196+
}
197+
198+
if (enumerator.Current == ":") {
199+
toFlush.Add(new Token(TokenType.Wildcard));
200+
toFlush.Add(new Token(TokenType.Semicolon));
201+
return;
202+
}
203+
204+
found = "_" + enumerator.Current;
205+
}
206+
207+
private static void BuildNumber(IEnumerator<string> enumerator, List<Token> toFlush) {
208+
int sign = 1;
209+
210+
if (enumerator.Current == "-") {
211+
sign = -1;
212+
if (!enumerator.MoveNext()) return;
213+
}
214+
215+
if (!long.TryParse(enumerator.Current, out long upper)) {
216+
toFlush.Add(new Token(TokenType.OpSub));
217+
return;
218+
}
219+
220+
if (!enumerator.MoveNext()) return;
221+
222+
if (enumerator.Current != ".") {
223+
toFlush.Add(new ConstantToken(new IntVariant(upper * sign)));
224+
return;
225+
}
226+
227+
if (!enumerator.MoveNext()) return;
228+
229+
if (!long.TryParse(enumerator.Current, out long lower)) {
230+
// I dont think there is really a proper return for here.
231+
// You'd have a number that looks like this "1000."
232+
// No following decimal
233+
// Comment if you had ideas
234+
return;
235+
}
236+
237+
var result = upper + (lower / Math.Pow(10, lower.ToString().Length));
238+
toFlush.Add(new ConstantToken(new RealVariant(result * sign)));
239+
}
240+
185241
public static IEnumerable<Token> Tokenize(string gdScript, uint baseIndent = 0) {
242+
var finalTokens = new List<Token>();
186243
var tokens = SanitizeInput(TokenizeString(gdScript + " "));
187244

188245
var previous = string.Empty;
189246
var idName = string.Empty;
190247

191-
List<Token> toFlush = new(2);
192-
yield return new Token(TokenType.Newline, baseIndent);
193-
foreach (var current in tokens) {
248+
var toFlush = new List<Token>(2);
249+
finalTokens.Add(new Token(TokenType.Newline, baseIndent));
250+
var enumerator = tokens.GetEnumerator();
251+
while (enumerator.MoveNext()) {
252+
var current = enumerator.Current;
194253
if (current == "\n") {
195-
goto endAndFlushId;
196-
}
197-
198-
if (previous == "\n") {
199-
var tabCount = uint.Parse(current);
200-
toFlush.Add(new Token(TokenType.Newline, tabCount + baseIndent));
201-
goto end;
254+
InsertNewLine(enumerator, baseIndent, toFlush);
255+
endAndFlushId();
256+
continue;
202257
}
203258

204259
if (current == "_") {
205-
goto end;
260+
BuildIdentifierName(enumerator, toFlush, out string? found);
261+
if (found == string.Empty) {
262+
endAndFlushId();
263+
continue;
264+
}
265+
266+
idName += found;
267+
268+
end();
269+
continue;
206270
}
207271

208-
if (previous == "_" && current == ":") {
209-
toFlush.Add(new Token(TokenType.Wildcard));
210-
toFlush.Add(new Token(TokenType.Semicolon));
211-
goto endAndFlushId;
212-
} else if (previous == "_") {
213-
idName += "_" + current;
214-
goto end;
272+
if (current == "-" || char.IsDigit(current[0])) {
273+
BuildNumber(enumerator, toFlush);
274+
endAndFlushId();
275+
continue;
215276
}
216277

217278
if (BuiltinFunctions.Contains(current)) {
218279
toFlush.Add(new Token(TokenType.BuiltInFunc, (uint?) BuiltinFunctions.IndexOf(current)));
219-
goto endAndFlushId;
280+
endAndFlushId();
281+
continue;
220282
}
221283

222284
if (Tokens.TryGetValue(current, out var type)) {
223285
toFlush.Add(new Token(type));
224-
goto endAndFlushId;
286+
endAndFlushId();
287+
continue;
225288
}
226289

227-
if (current[0] == '"') {
290+
if (current.StartsWith('"')) {
228291
toFlush.Add(new ConstantToken(new StringVariant(current.Substring(1, current.Length - 2))));
229-
goto endAndFlushId;
292+
endAndFlushId();
293+
continue;
230294
}
231295

232296
if (bool.TryParse(current, out var resultB)) {
233297
toFlush.Add(new ConstantToken(new BoolVariant(resultB)));
234-
goto endAndFlushId;
298+
endAndFlushId();
299+
continue;
235300
}
236301

237-
if (long.TryParse(current, out var resultL)) {
238-
toFlush.Add(new ConstantToken(new IntVariant(resultL)));
239-
goto endAndFlushId;
240-
}
302+
idName += current;
241303

242-
if (double.TryParse(current, out var result)) {
243-
toFlush.Add(new ConstantToken(new RealVariant(result)));
244-
goto endAndFlushId;
304+
end();
305+
306+
void end() {
307+
previous = enumerator.Current;
308+
finalTokens.AddRange(toFlush);
309+
toFlush.Clear();
245310
}
246311

247-
idName += current;
312+
void endAndFlushId() {
313+
if (idName != string.Empty) {
314+
finalTokens.Add(new IdentifierToken(idName));
315+
idName = string.Empty;
316+
}
248317

249-
goto end;
250-
endAndFlushId:
251-
if (idName != string.Empty) {
252-
yield return new IdentifierToken(idName);
253-
idName = string.Empty;
318+
end();
254319
}
255-
end:
256-
previous = current;
257-
foreach (var token in toFlush) yield return token;
258-
toFlush.Clear();
259320
}
260321

261-
yield return new(TokenType.Newline, baseIndent);
322+
finalTokens.Add(new(TokenType.Newline, baseIndent));
323+
324+
foreach (var t in finalTokens) yield return t;
325+
262326
}
263327

264328
private static IEnumerable<string> SanitizeInput(IEnumerable<string> tokens) {

0 commit comments

Comments
 (0)