Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text.RegularExpressions;
- using System.IO;
- namespace TinkerWorX.JassToTypeScript
- {
- internal class TypeDefinition
- {
- public string Name { get; set; }
- public string Parent { get; set; }
- }
- internal class ArgumentDefinition
- {
- public string Type { get; set; }
- public string Name { get; set; }
- }
- internal class NativeDefinition
- {
- public string Name { get; set; }
- public List<ArgumentDefinition> Arguments { get; set; }
- public string ReturnType { get; set; }
- }
- internal class GlobalDefinition
- {
- public bool IsConstant { get; set; }
- public string Type { get; set; }
- public bool IsArray { get; set; }
- public string Name { get; set; }
- public string Value { get; set; }
- }
- internal class FunctionDefinition
- {
- public string Name { get; set; }
- public List<ArgumentDefinition> Arguments { get; set; }
- public string ReturnType { get; set; }
- }
- internal class LibraryDefinition
- {
- public List<TypeDefinition> Types { get; } = new List<TypeDefinition>();
- public List<NativeDefinition> Natives { get; } = new List<NativeDefinition>();
- public List<GlobalDefinition> Globals { get; } = new List<GlobalDefinition>();
- public List<FunctionDefinition> Functions { get; } = new List<FunctionDefinition>();
- }
- internal class Program
- {
- private const string TYPE_DEFINITION = @"type\s+(?<name>\w+)\s+extends\s+(?<parent>\w+)";
- private const string NATIVE_DEFINITION = @"native\s+(?<name>\w+)\s+takes\s+(?<prototype>.+)";
- private const string GLOBAL_DEFINITION = @"(?<constant>constant)?\s*(?<type>\w+)(\s+(?<array>array))?\s+(?<name>\w+)(\s+=\s(?<value>.+))?";
- private const string FUNCTION_DEFINITION = @"function\s+(?<name>\w+)\s+takes\s+(?<prototype>.+)";
- private static string Clean(string input)
- {
- input = input.Trim();
- while (input.IndexOf(" ") >= 0)
- input = input.Replace(" ", " ");
- if (input.IndexOf("//") >= 0)
- input = input.Substring(0, input.IndexOf("//"));
- while (input.IndexOf(" ") >= 0)
- input = input.Replace(" ", " ");
- return input;
- }
- private static void ParseLines(string[] lines, LibraryDefinition library)
- {
- bool inGlobals = false;
- foreach (var rawLine in lines)
- {
- var line = Clean(rawLine);
- if (line.StartsWith("//"))
- continue;
- if (inGlobals)
- {
- inGlobals = !line.Contains("endglobals");
- if (!inGlobals)
- continue;
- var globalDefinition = Regex.Match(line, GLOBAL_DEFINITION);
- if (globalDefinition.Success)
- {
- var type = globalDefinition.Groups["type"].Value;
- var value = globalDefinition.Groups["value"].Value;
- //if (value.Length == 6 && value[0] == '\'' && value[5] == '\'')
- // type = "string";
- library.Globals.Add(new GlobalDefinition
- {
- IsConstant = !String.IsNullOrWhiteSpace(globalDefinition.Groups["constant"].Value),
- Type = type,
- IsArray = !String.IsNullOrWhiteSpace(globalDefinition.Groups["array"].Value),
- Name = globalDefinition.Groups["name"].Value,
- Value = value,
- });
- continue;
- }
- }
- else
- {
- inGlobals = line.Contains("globals");
- if (inGlobals)
- continue;
- var typeDefinition = Regex.Match(line, TYPE_DEFINITION);
- if (typeDefinition.Success)
- {
- library.Types.Add(new TypeDefinition
- {
- Name = typeDefinition.Groups["name"].Value,
- Parent = typeDefinition.Groups["parent"].Value
- });
- continue;
- }
- var nativeDefinition = Regex.Match(line, NATIVE_DEFINITION);
- if (nativeDefinition.Success)
- {
- var name = nativeDefinition.Groups["name"].Value;
- var prototype = nativeDefinition.Groups["prototype"].Value;
- var takes = Clean(prototype.Split(new string[] { "returns" }, StringSplitOptions.None)[0]);
- var returns = Clean(prototype.Split(new string[] { "returns" }, StringSplitOptions.None)[1]);
- library.Natives.Add(new NativeDefinition
- {
- Name = name,
- Arguments = takes.Equals("nothing") ? new List<ArgumentDefinition>() : takes.Split(',').Select(s => s.Trim()).Select(s => new ArgumentDefinition
- {
- Type = s.Split(' ')[0],
- Name = s.Split(' ')[1],
- }).ToList(),
- ReturnType = returns,
- });
- continue;
- }
- var functionDefinition = Regex.Match(line, FUNCTION_DEFINITION);
- if (functionDefinition.Success)
- {
- var name = functionDefinition.Groups["name"].Value;
- var prototype = functionDefinition.Groups["prototype"].Value;
- var takes = Clean(prototype.Split(new string[] { "returns" }, StringSplitOptions.None)[0]);
- var returns = Clean(prototype.Split(new string[] { "returns" }, StringSplitOptions.None)[1]);
- library.Functions.Add(new FunctionDefinition
- {
- Name = name,
- Arguments = takes.Equals("nothing") ? new List<ArgumentDefinition>() : takes.Split(',').Select(s => s.Trim()).Select(s => new ArgumentDefinition
- {
- Type = s.Split(' ')[0],
- Name = s.Split(' ')[1],
- }).ToList(),
- ReturnType = returns,
- });
- continue;
- }
- }
- }
- }
- private static void ParseFile(string path, LibraryDefinition library)
- {
- ParseLines(File.ReadAllLines(path), library);
- }
- private static string FixType(string type)
- {
- switch (type)
- {
- case "real":
- case "integer":
- type = "number";
- break;
- case "nothing":
- type = "void";
- break;
- case "code":
- type = "() => void";
- break;
- //case "boolexpr":
- //case "conditionfunc":
- //case "filterfunc":
- //type = "() => boolean";
- //break;
- }
- return type;
- }
- private static void Magic(NativeDefinition native)
- {
- switch (native.Name)
- {
- case "Condition":
- case "Filter":
- native.Arguments[0].Type = "() => boolean";
- break;
- }
- }
- private static int Main(string[] args)
- {
- if (args.Length < 2)
- {
- Console.WriteLine("Usage: TinkerWorX.JassToTypeScript.exe input1.j [input2.j...] output.d.ts");
- return 1;
- }
- var inputFiles = args.Reverse().Skip(1).Reverse();
- var outputFile = args.Reverse().First();
- var library = new LibraryDefinition();
- foreach (var inputFile in inputFiles)
- {
- Console.WriteLine($"Parsing: {inputFile}");
- ParseFile(inputFile, library);
- }
- Console.WriteLine($"Writing: {outputFile}");
- using (var stream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.Write))
- using (var writer = new StreamWriter(stream))
- {
- writer.WriteLine("/** @noSelfInFile **/");
- writer.WriteLine();
- foreach (var type in library.Types)
- {
- writer.WriteLine($"declare abstract class {type.Name} extends {type.Parent} {{ __{type.Name}: never; }}");
- }
- writer.WriteLine();
- foreach (var native in library.Natives)
- {
- Magic(native);
- writer.Write($"declare function {native.Name}(");
- if (native.Arguments.Any())
- writer.Write($"{native.Arguments.Select(arg => $"{arg.Name}: {FixType(arg.Type)}").Aggregate((a, b) => a + ", " + b)}");
- writer.WriteLine($"): {FixType(native.ReturnType)}");
- }
- writer.WriteLine();
- foreach (var global in library.Globals)
- {
- writer.Write("declare");
- if (global.IsConstant)
- writer.Write(" const");
- else
- writer.Write(" var");
- writer.Write($" {global.Name}");
- writer.WriteLine($": {FixType(global.Type)}");
- }
- writer.WriteLine();
- foreach (var function in library.Functions)
- {
- writer.Write($"declare function {function.Name}(");
- if (function.Arguments.Any())
- writer.Write($"{function.Arguments.Select(arg => $"{arg.Name}: {FixType(arg.Type)}").Aggregate((a, b) => a + ", " + b)}");
- writer.WriteLine($"): {FixType(function.ReturnType)}");
- }
- }
- return 0;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement