static int Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Error: First argument of program must be the script to be parsed"); Console.WriteLine("\nI suggest using this script for testing: https://github.com/07th-mod/umineko-question/raw/master/InDevelopment/ManualUpdates/0.utf"); Console.WriteLine("\nVisual Studio users can follow these instructions to set program arguments: https://stackoverflow.com/questions/298708/debugging-with-command-line-parameters-in-visual-studio"); Console.ReadKey(); return(-1); } // Read input script string inputFilePath = args[0]; Console.WriteLine($"Processing input file [{inputFilePath}]"); string[] lines = File.ReadAllLines(inputFilePath); // First pass of script is to build the function database SubroutineDatabase database = UserFunctionScanner.buildInitialUserList(lines, new SubroutineDatabase()); // Add predefined functions. If a function already exists, it will be added with an '_' prefix PredefinedFunctionInfoLoader.load("function_list.txt", database); // Add some extra pre-defined functions database["langen"] = new SubroutineInformation(false); database["langjp"] = new SubroutineInformation(false); database["showlangen"] = new SubroutineInformation(false); database["showlangjp"] = new SubroutineInformation(false); database["langall"] = new SubroutineInformation(false); //TODO: not sure if this is a real function or a typo. Only occurs once in umineko question script. database["endroll"] = new SubroutineInformation(true); database["steamsetachieve"] = new SubroutineInformation(true); database["getreadlang"] = new SubroutineInformation(true); database["say"] = new SubroutineInformation(true); database["tachistate"] = new SubroutineInformation(true); foreach (KeyValuePair <string, SubroutineInformation> kvp in database.GetRawDict()) { Console.WriteLine($"{kvp.Key}: {kvp.Value.hasArguments}"); } bool dumpNodes = true; bool error = true; if (dumpNodes) { string savePath = @"ponscripter_script_nodes.txt"; error = DumpTopLevelNodes(lines, database, savePath); } else { error = CompileScript(lines, database); } return(error ? -2 : 0); }
public bool TryAdd(string sAnyCase, SubroutineInformation value) { string s = NormalizeKey(sAnyCase); if (subroutineInfoDict.ContainsKey(s)) { //Console.WriteLine($"WARNING: duplicate defsub found for {s}"); duplicateDefsubs.Add(s); return(false); } else { subroutineInfoDict.Add(s, value); return(true); } }
public bool TryGetValue(string sAnyCase, out SubroutineInformation output) { if (InnerTryGetValue(sAnyCase, out SubroutineInformation subroutineInformation)) { output = subroutineInformation; return(true); } else if (sAnyCase.StartsWith("_") && InnerTryGetValue(sAnyCase.Substring(1), out SubroutineInformation underscoreSubroutineInformation)) { output = underscoreSubroutineInformation; Console.WriteLine($"WARNING: it appears the function {sAnyCase} is called with an underscore, even though it is not overriden"); return(true); } output = null; return(false); }
/// <summary> /// Scan the entire script for subroutine declarations and definitions /// </summary> /// <param name="allLines"></param> public static SubroutineDatabase buildInitialUserList(string[] allLines, SubroutineDatabase database) { List <LabelInfo> labels = new List <LabelInfo>(); //scan for subroutines definitions and labels for (int i = 0; i < allLines.Length; i++) { string s = allLines[i]; Match defsubMatch = defsubRegex.Match(s); Match labelMatch = labelRegex.Match(s); if (defsubMatch.Success) { //search the script for "defsub ut_mld2" type calls. store each in a hashmap string subName = defsubMatch.Groups[1].Value; Console.WriteLine($"Got sub definition {subName}"); if (!database.TryAdd(subName, null)) { Console.WriteLine($"WARNING: duplicate defsub found for {subName}"); } } else if (labelMatch.Success) { string labelName = labelMatch.Groups[1].Value; Console.WriteLine($"Got label definition {labelName}"); labels.Add(new LabelInfo(labelName, i)); } } //iterate starting at the label definition until (worst case) the end of file //when a getparam or return is found, the number of parameters is recorded SubroutineInformation GetSubroutineInformation(string[] linesToSearch, LabelInfo label) { for (int i = label.labelLineIndex; i < linesToSearch.Length; i++) { string s = linesToSearch[i]; Match getParamMatch = getParamRegex.Match(s); Match returnMatch = returnRegex.Match(s); if (getParamMatch.Success) { Console.WriteLine($"{label.labelName} arguments are {getParamMatch.Groups[0].Value} [{s}]"); return(new SubroutineInformation(getParamMatch.Groups[0].Value)); } else if (returnMatch.Success) { Console.WriteLine($"{label.labelName} takes no arguments"); return(new SubroutineInformation(hasArguments: false)); } } //somehow reached end of the document return(null); } //For reach subroutine, determine what arguments (if any) it uses //May not work for all cases, but usually getparam is the first call //after the label def so use this method for now. foreach (LabelInfo label in labels) { //Only process subroutine definitions, not ordinary labels if (!database.InnerTryGetValue(label.labelName, out _)) { continue; } Console.WriteLine($"{label.labelName} is a subroutine"); SubroutineInformation subInfo = GetSubroutineInformation(allLines, label); if (subInfo == null) { Console.WriteLine($"ERROR: no return or getparam for subroutine {label.labelName}"); } else { database[label.labelName] = subInfo; } } return(database); }
//TODO: tidy this up later... public bool InnerTryGetValue(string sAnyCase, out SubroutineInformation output) { return(subroutineInfoDict.TryGetValue(NormalizeKey(sAnyCase), out output)); }