public ArrayTokenStream LexWithFixes(string str) { str = OBScriptFixer.FixScriptErrors(str); ArrayTokenStream tokens = Lex(str); return(tokens); }
public object ParseWithFixLogic(ITokenStream stream) { //WTM: Change: If the script is just a comment, resulting in only an EOF token, parser.ParseWithFixLogic fails. //The below check works around that. IToken[] firstTwoTokens = stream.Take(2).ToArray(); if (firstTwoTokens.Length == 1 && firstTwoTokens[0].Type == EOF_TOKEN_TYPE) { throw new EOFOnlyException(); } try { return(base.Parse(stream)); } catch (UnexpectedTokenException ex) when(ex.Token.Value == "endif") { bool isFixed = false; int nesting = 0; List <IToken> tokens = new List <IToken>(); foreach (var token in stream) { if (token.Type == "BranchStartToken") { ++nesting; tokens.Add(token); } else { if (token.Type == "BranchEndToken") { nesting = nesting - 1; if (nesting > -1) { tokens.Add(token); } else { isFixed = true; nesting = 0; //Clear up the token and nesting will be again 0 } } else { tokens.Add(token); } } } if (!isFixed) { throw; } ArrayTokenStream newTokenStream = new ArrayTokenStream(tokens); object newAST = this.Parse(newTokenStream); return(newAST); } }
public T Parse(string scriptPath) { OBScriptLexer lexer = this.lexerLazy.Value; string sourceText = File.ReadAllText(scriptPath); ArrayTokenStream tokens = lexer.LexWithFixes(sourceText); SyntaxErrorCleanParser parser = this.parserLazy.Value; T result = (T)parser.ParseWithFixLogic(tokens); return(result); }
public ArrayTokenStream LexWithFixes(string str) { //WTM: Change: In tif__0101efc0 and other TGExpelledScripts, PayFine gets misunderstood as a function call instead of a variable. str = str.Replace("TGExpelled.PayFine", "TGExpelled.PayFineTemp"); //WTM: Change: In tgcastout, the below replacement must be made so the variable name can stay in synch. if (str.StartsWith("ScriptName TGCastOut")) { str = str.Replace("Float PayFine", "Float PayFineTemp"); } //WTM: Change: In darkperenniaghostscript, Disable gets misunderstood as a function call instead of a variable. if (str.StartsWith("Scriptname DarkPerenniaGhostScript")) { str = str.Replace("Disable", "DisableTemp"); } //WTM: Change: In blade3script, Look gets misunderstood as a function call instead of a variable. if (str.StartsWith("Scriptname Blade3Script")) { str = str .Replace("short Look", "short LookTemp") .Replace("if Look == ", "if LookTemp == ") .Replace("set Look to ", "set LookTemp to "); } //WTM: Change: In qf_tg03elven_01034ea2_100_0, a variable is apparently accidentally quoted. if (str.Contains("TG03LlathasasBustMarker.PlaceAtMe \"TG03LlathasasBust\"")) { str = str.Replace("TG03LlathasasBustMarker.PlaceAtMe \"TG03LlathasasBust\"", "TG03LlathasasBustMarker.PlaceAtMe TG03LlathasasBust"); } //WTM: Change: In sebruscusdannusitemscript, getstartingpos's arguments are not quoted. if (str.StartsWith("scn SEBruscusDannusItemSCRIPT")) { str = getStartingPosOrAngleUnquotedArguments.Replace(str, "$1 \"$2\""); } ArrayTokenStream tokens = Lex(str); return(tokens); }
public void execute(string buildPath = Build.DEFAULT_BUILD_PATH, bool skipParsing = false, string mode = "strict") { set_time_limit(10800); // 3 hours is the maximum for this command. Need more? You really screwed something, full suite for all Oblivion vanilla data takes 20 minutes. :) float threshold; switch (mode) { case "sloppy": { threshold = 0.5f; break; } case "normal": { threshold = 0.85f; break; } case "strict": default: { threshold = 0.95f; break; } case "perfect": { threshold = 1; break; } } if (!skipParsing) { SyntaxErrorCleanParser parser = new SyntaxErrorCleanParser(new TES4ObscriptCodeGrammar()); //parser = new Parser(new TES4OBScriptGrammar()); TES4ToTES5ASTTIFFragmentConverter converter = TES4ToTES5ASTTIFFragmentConverterFactory.GetConverter(new Build(buildPath)); string inputFolder = "./Fragments/TIF/fragments/"; string outputFolder = "./Fragments/TIF/PapyrusFragments/"; string[] scandir = Directory.GetFiles(inputFolder); int success = 0, total = 0; Dictionary <string, TES5MultipleScriptsScope> ASTTable = new Dictionary <string, TES5MultipleScriptsScope>(); Console.WriteLine("Lexing and parsing.."); int totalNumber = scandir.Length; foreach (var scriptPath in scandir) { if (!scriptPath.EndsWith(".txt")) { continue; } if ((total % 10) == 0) { Console.WriteLine(total + "/" + totalNumber + "..."); } string scriptFileName = scriptPath.Substring(0, scriptPath.Length - 4); string outputScriptPath = scriptFileName + ".psc"; total++; try { Console.WriteLine(scriptFileName + "..."); FragmentLexer lexer = new FragmentLexer(); ArrayTokenStream tokens = lexer.lex(File.ReadAllText(path)); TES4VariableDeclarationList variableList = this.fragmentsReferencesBuilder.buildVariableDeclarationList(inputFolder + scriptFileName + ".references"); TES5MultipleScriptsScope AST = (TES5MultipleScriptsScope)parser.ParseWithFixLogic(tokens); ASTTable[scriptPath] = AST; TES5Target TES5AST = converter.convert(scriptFileName, variableList, AST); string outputScript = TES5AST.output(); File.WriteAllText(outputFolder + outputScriptPath, outputScript); Process.Start("lua", "\"Utilities/beautifier.lua\" \"" + outputFolder + outputScriptPath + "\""); success++; } catch (Exception e) { Console.WriteLine(scriptPath + "\r\n" + e.GetType().FullName + ": " + e.Message + "\r\n"); continue; } } float successRate = (float)success / total; if (successRate < threshold) { float percent = (float)Math.Round(successRate * 100); Console.WriteLine("ERROR: Build failed on parsing step in " + mode + " mode. The rate is " + success + "/" + total + " (" + percent + " %)"); return; } Console.WriteLine("Parsing in " + mode + " mode succedeed (rate " + success + "/" + total + "). Copying Skyrim scripts and parsed papyrus fragments to build folder..."); } Console.WriteLine("Build in " + mode + " mode succeeded!"); }