/* * User: Ryan * Date: 8/17/2017 * Time: 11:54 AM */ using System; using System.Data; using System.Diagnostics; using System.IO; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Reflection; using System.Threading; using System.Windows.Input; using FancyPrintCS; using NAudio.Wave; using parseManagerCS; namespace parseManagerCS { /// The parseManager is an Advance Config Script (It goes beyond what it was initially desgined for though!) /// It allows the user to run code while also defining variables /// This also has very flexible flow control meaning you can use it for chat logic and such public class parseManager { public string _VERSION = "1.4.0"; standardDefine _invoke = new standardDefine(); string _filepath; bool _active = true; int _pauseRate = 100; string _define = "NO_DEFINE"; string _entry = "START"; bool _isInternal; Type _defineType; bool isThread; standardDefine def = new standardDefine(); MethodInfo _defineMethod; object _defineClassObject; chunk _currentChunk; chunk _lastChunk = null; ENV _mainENV = new ENV(); bool _paused; public ENV _defualtENV; Stack _fStack = new Stack(); Dictionary _flags = new Dictionary(); Dictionary _chunks = new Dictionary(); Dictionary _methods = new Dictionary(); void INITENV() { _mainENV.SetSen(GetFlag("casesensitive")); _mainENV["Color_Black"] = ConsoleColor.Black; _mainENV["Color_Blue"] = ConsoleColor.Blue; _mainENV["Color_Cyan"] = ConsoleColor.Cyan; _mainENV["Color_DarkBlue"] = ConsoleColor.DarkBlue; _mainENV["Color_DarkCyan"] = ConsoleColor.DarkCyan; _mainENV["Color_DarkGray"] = ConsoleColor.DarkGray; _mainENV["Color_DarkGreen"] = ConsoleColor.DarkGreen; _mainENV["Color_DarkMagenta"] = ConsoleColor.DarkMagenta; _mainENV["Color_DarkRed"] = ConsoleColor.DarkRed; _mainENV["Color_DarkYellow"] = ConsoleColor.DarkYellow; _mainENV["Color_Gray"] = ConsoleColor.Gray; _mainENV["Color_Green"] = ConsoleColor.Green; _mainENV["Color_Magenta"] = ConsoleColor.Magenta; _mainENV["Color_Red"] = ConsoleColor.Red; _mainENV["Color_White"] = ConsoleColor.White; _mainENV["Color_Yellow"] = ConsoleColor.Yellow; _mainENV["VERSION"] = _VERSION; } public void _SetDENV(ENV env) { _mainENV = env; } public void Pause() { _paused = true; } public void Resume() { _paused = false; } public void makeThread() { isThread = true; } public bool isAThread() { return isThread; } public parseManager(string filepath) { InitFlags(); _filepath = filepath; _defineType = Type.GetType("standardDefine"); ConstructorInfo defineConstructor = _defineType.GetConstructor(Type.EmptyTypes); _defineClassObject = defineConstructor.Invoke(new object[]{ }); _defualtENV = _mainENV; INITENV(); Parse(); } public parseManager(string filepath, string define) { InitFlags(); _define = define; _filepath = filepath; _defineType = Type.GetType(define); ConstructorInfo defineConstructor = _defineType.GetConstructor(Type.EmptyTypes); _defineClassObject = defineConstructor.Invoke(new object[]{ }); _defualtENV = _mainENV; INITENV(); Parse(); } public parseManager(string code, string define, bool c) { InitFlags(); _define = define; _filepath = code; _isInternal = true; _defineType = Type.GetType(define); ConstructorInfo defineConstructor = _defineType.GetConstructor(Type.EmptyTypes); _defineClassObject = defineConstructor.Invoke(new object[]{ }); _defualtENV = _mainENV; INITENV(); Parse(code, c); } public parseManager(string code, bool c) { _isInternal = true; InitFlags(); _filepath = code; _defineType = Type.GetType("standardDefine"); ConstructorInfo defineConstructor = _defineType.GetConstructor(Type.EmptyTypes); _defineClassObject = defineConstructor.Invoke(new object[]{ }); _defualtENV = _mainENV; INITENV(); Parse(code, c); } public bool IsInternal() { return _isInternal; } public string GetFilepath() { return _filepath; } public string GetDefine() { return _define; } void InitFlags() { _flags.Add("leaking", false); _flags.Add("forseelabels", true); _flags.Add("debugging", false); _flags.Add("topdown", true); _flags.Add("casesensitive", true); _flags.Add("strictsyntax", false); } public ENV Pop() { return _fStack.Pop(); } public bool GetFlag(string flag) { bool f; if (_flags.TryGetValue(flag, out f)) { return f; } return false; } public void debug(object msg) { if (_flags["debugging"]) Console.WriteLine("DEBUGGING: " + msg); } public void SetPauseRate(int r) { _pauseRate = r; } void _Parse(string data, string hFile) { foreach (Match m in Regex.Matches(data, @"LOAD ([a-zA-Z0-9_\./]+)")) { Parse(m.Groups[1].ToString()); } foreach (Match m in Regex.Matches(data, @"ENABLE ([a-zA-Z0-9_\./]+)")) { _flags[m.Groups[1].ToString().ToLower()] = true; } foreach (Match m in Regex.Matches(data, @"DISABLE ([a-zA-Z0-9_\./]+)")) { _flags[m.Groups[1].ToString().ToLower()] = false; } foreach (Match m in Regex.Matches(data, @"ENTRY ([a-zA-Z0-9_\./]+)")) { _entry = m.Groups[1].ToString(); } foreach (Match m in Regex.Matches(data, @"VERSION ([a-zA-Z0-9_\./]+)")) { if (Version.Parse(m.Groups[1].ToString()) > Version.Parse(_VERSION)) { PushError("Attempt to run a code created for a greater version of the interperter/compiler! Script's Version: " + Version.Parse(m.Groups[1].ToString()) + " Interperter's Version: " + Version.Parse(_VERSION)); } } foreach (Match m in Regex.Matches(data, @"THREAD ([a-zA-Z0-9_\./]+)")) { def._newThread(this, m.Groups[1].ToString()); } data = data + "\n"; var match = Regex.Matches(data, "\\[(.+)\\][\r\n]*?\\{([^\0]+?)\\}\r?\n"); var count = 0; foreach (Match m in match) { string Blck = m.Groups[1].ToString(); string Cont = m.Groups[2].ToString(); int loc = Blck.IndexOf(":", StringComparison.Ordinal); if (loc != -1) { _chunks[Blck.Substring(0, loc)] = new chunk(Blck.Substring(0, loc), Cont, Blck.Substring(loc + 1)); Blck = Blck.Substring(0, loc); } else { _chunks[Blck] = new chunk(Blck, Cont); } count++; _chunks[Blck].SetHostFile(hFile); if (_lastChunk != null) _lastChunk.SetNextChunk(_chunks[Blck]); _lastChunk = _chunks[Blck]; } } void Parse() { try { StreamReader sr = File.OpenText(_filepath); _Parse(sr.ReadToEnd(), _filepath); sr.Close(); } catch (FileNotFoundException) { PushError("File '" + _filepath + "' does not exist!"); } } void Parse(string code, bool c) { _Parse(code, "Internally Parsed Code!"); } void Parse(string filename) { try { StreamReader sr = File.OpenText(filename); _Parse(sr.ReadToEnd(), filename); sr.Close(); } catch (FileNotFoundException) { PushError("Could not load '" + _filepath + "' it does not exist!"); } } public void ParseCode(string code) { _Parse(code, "Internally Parsed Code!"); } public chunk[] GetChunks() { var chunks = _chunks.Values; var temp = new chunk[_chunks.Count]; var i = 0; foreach (var item in _chunks) { temp[i] = item.Value; i++; } return temp; } public chunk GetCurrentChunk() { return _currentChunk; } public void Deactivate() { _active = false; } public bool GetLogic(parseManager PM, string log) { var test2 = PM.Logic(log); var te = evaluater.Evaluate(PM, test2); if (te > 0) { return true; } else { return false; } } public bool isRegisteredFunction(string method, out chunk o) { if (_chunks.TryGetValue(method, out o)) { if (o.isFunction()) { return true; } return false; } return false; } public object InvokeI(string method, object[] argsV, chunk c, bool rets) { var ccP = _currentChunk.GetPos(); var ccN = _currentChunk.GetName(); var argsN = c.GetArgs(); var fEnv = new ENV(); fEnv.SetSen(GetFlag("casesensitive")); fEnv.SetParent(_defualtENV); if (!(argsN.Length == 1 && argsN[0] == "")) { for (int i = 0; i < argsN.Length; i++) { fEnv[argsN[i]] = argsV[i]; } } var tempEnv = new ENV(); tempEnv[0] = ccN; tempEnv[1] = ccP; tempEnv[2] = _defualtENV; _fStack.Push(tempEnv); if (_fStack.Count > 1024) { PushError("Stack Overflow!"); } _defualtENV = fEnv; def.JUMP(this, method); if (rets) { return fEnv; // TODO Handle returns } else { return null; } } public object Invoke(string method, object[] args) { chunk c; if (isRegisteredFunction(method, out c)) { return InvokeI(method, args, c, true); } PushError("Attempt to invoke a non existing method!"); return null; } public object InvokeR(string method, object[] args) { chunk c; if (isRegisteredFunction(method, out c)) { return InvokeI(method, args, c, true); } try { _defineMethod = _defineType.GetMethod(method); return _defineMethod.Invoke(_defineClassObject, tackBArgs(this, args)); } catch (Exception e) { var tests = e.ToString(); if (tests.Contains("Null")) { PushError("Invalid method: " + method + " (Method does not exist! Check your spelling!)"); } else if (tests.Contains("ArgumentException")) { PushError("Invalid method: " + method + " (Check your arguments! Ensure the types are correct!)"); } PushError("Invalid method: " + method + " (Unknown Error! It just doesn't work!)\n\n" + e); return null; } } public int InvokeNR(string method, object[] args) { chunk c; if (isRegisteredFunction(method, out c)) { InvokeI(method, args, c, false); return 0; } try { _defineMethod = _defineType.GetMethod(method); _defineMethod.Invoke(_defineClassObject, tackBArgs(this, args)); return 0; } catch (Exception e) { var tests = e.ToString(); if (tests.Contains("Null")) { PushError("Invalid method: " + method + " (Method does not exist! Check your spelling!)"); } else if (tests.Contains("ArgumentException")) { PushError("Invalid method: " + method + " (Check your arguments! Ensure the types are correct!)"); } PushError("Invalid method: " + method + " (Unknown Error! It just doesn't work!)\n\n" + e); return -1; } } public object[] tackBArgs(object o, object[] args) { var len = args.Length; var newargs = new object[len + 1]; for (int i = 0; i < len; i++) { newargs[i + 1] = args[i]; } newargs[0] = o; return newargs; } public void SetBlock(string BLOCK) { chunk cchunk; if (_chunks.TryGetValue(BLOCK, out cchunk)) { _currentChunk = cchunk; _currentChunk.ResetPos(); } else { PushError("Attempt to JUMP to a non existing block: \"" + BLOCK + "\""); } } public ENV GetENV() { if (_defualtENV == null) { return _mainENV; } return _defualtENV; } public ENV GetDENV() { return _mainENV; } public void SetENV() { _defualtENV = _mainENV; } public void SetENV(ENV o) { _defualtENV = o; } public void SetBlock(chunk BLOCK) { _currentChunk = BLOCK; } public void SetBlock() { chunk cchunk; if (_chunks.TryGetValue(_entry, out cchunk)) { _currentChunk = cchunk; _currentChunk.ResetPos(); } else { PushError("Entrypoint is Invalid!"); } } public void PushError(string err) { if (_currentChunk == null) { Console.WriteLine(err + "\nPress Enter"); Console.ReadLine(); Environment.Exit(0); } var line = _currentChunk.GetCurrentLine(); var file = _currentChunk.GetHostFile(); var sr = File.OpenText(file); var code = sr.ReadToEnd(); var haschunk = false; var chunk = _currentChunk.GetName(); code = Regex.Replace(code, @"^\t+", "", RegexOptions.Multiline); var lines = code.Split(new [] { "\r\n", "\n" }, StringSplitOptions.None); var pos = 0; for (int i = 0; i < lines.Length; i++) { if (!haschunk && lines[i].StartsWith("[" + chunk)) { haschunk = true; } if (lines[i].StartsWith(line) && haschunk) { pos = i + 1; break; } } Console.WriteLine(string.Format("Error in File: {0} on Line: {1}\nLIQ: {2}\n\nERROR: {3}\nPress Enter!", file, pos, line, err)); Console.ReadLine(); Environment.Exit(0); } public nextType Next(string BLOCK) { if (_currentChunk == null) { SetBlock(BLOCK); } return Next(); } public nextType Next() { var tempReturn = new nextType(); if (_paused) { if (_pauseRate != 0) { Thread.Sleep(_pauseRate); } return tempReturn; } if (_currentChunk == null) { SetBlock(); } var cCMD = _currentChunk.GetCLine(); object[] stuff; if (cCMD == null) { if (_flags["leaking"] && _active) { var test = _currentChunk.GetNextChunk(); if (test != null) { SetBlock(_currentChunk.GetNextChunk()); return Next(); } } tempReturn.SetCMDType("EOF"); tempReturn.SetText("Reached the end of the file!"); return tempReturn; } if (!_active) { tempReturn.SetCMDType("EOF"); tempReturn.SetText("Reached the end of the file!"); return tempReturn; } var type = cCMD.GetCMDType(); stuff = cCMD.GetArgs(); if (type == "LOGIC") {//{conds,andors,_funcif,_resultif,_funcelse,_resultelse} var conds = (string)stuff[0]; var funcif = (string)stuff[1]; var argsif = (string[])stuff[2]; var funcelse = (string)stuff[3]; var argselse = (string[])stuff[4]; var truth = GetLogic(this, conds); if (truth) { InvokeNR(funcif, ResolveVar(argsif)); } else { InvokeNR(funcelse, ResolveVar(argselse)); } tempReturn.SetCMDType("conditional"); tempReturn.SetText("test turned out to be: " + truth); return tempReturn; } else if (type == "LABEL") { tempReturn.SetCMDType("label"); tempReturn.SetText("Jumped to a label!"); return tempReturn; } if (type == "FUNC") { var func = (string)stuff[0]; var args = (string[])stuff[1]; if (args.Length == 1 && args[0] == "") { // assume no args inserted! InvokeNR(func, new object[]{ }); } else { InvokeNR(func, ResolveVar(args)); } tempReturn.SetCMDType("method"); tempReturn.SetText("INVOKED METHOD: " + func); return tempReturn; } else if (type == "LINE") { tempReturn.SetCMDType("line"); var test = parseHeader((string)stuff[0]); tempReturn.SetText(test.Substring(1, test.Length - 2)); return tempReturn; } else if (type == "FUNC_R") { var retargs = (string[])stuff[0]; var func = (string)stuff[1]; var args = (string[])stuff[2]; object data; var env = GetENV(); if (args.Length == 1 && args[0] == "") { // assume no args inserted! data = InvokeR(func, new object[]{ }); } else { data = InvokeR(func, ResolveVar(args)); } env[retargs[0]] = data; GLOBALS.Add_Var(retargs[0]); tempReturn.SetCMDType("method"); tempReturn.SetText("INVOKED METHOD: " + func); return tempReturn; } else if (type == "ASSIGN") { // TODO add lists/dictonaries support var vars = (string[])stuff[0]; var vals = (string[])stuff[1]; var env = GetENV(); var types = ResolveVar(vals); AssignmentHandler(vars, types); tempReturn.SetCMDType("assignment"); tempReturn.SetText(_currentChunk.GetLine()); return tempReturn; } else { var b = GetFlag("strictsyntax"); if (b) { PushError("INVALID SYNTAX!"); } } return tempReturn; } public void AssignmentHandler(string[] vars, object[] types) { var env = GetENV(); for (int i = 0; i < types.Length; i++) { var test = vars[i]; if (test.EndsWith("]")) { var dict = Regex.Match(test, @"(.*)\[(.+)\]"); var _var = dict.Groups[1].Value; var _val = dict.Groups[2].Value; var val = ResolveVar(new []{ _val }); var _e = env[_var]; if (!_e.GetType().ToString().Contains("ENV")) { PushError("Attempted to index a object that isn't a table!"); } else { var e = (ENV)_e; if (val[0].GetType().ToString().Contains("Double")) { e[int.Parse(val[0].ToString())] = types[i]; } else if (val[0].GetType().ToString().Contains("String")) { e[(string)val[0]] = types[i]; } else { PushError("Invalid index type: " + val[0]); } } } else { env[vars[i]] = types[i]; GLOBALS.Add_Var(vars[i]); } } } public string parseHeader(string header) { var results = Regex.Matches(header, @"\$([\S\*]+?)\$"); int len = results.Count; string str; object temp; object temp2; int testnum; for (int i = 0; i < len; i++) { str = results[i].Groups[1].Value; if (str.Contains("*")) { var test = Regex.Match(str, @"(.+?)\*(.+)"); var spart = test.Groups[1].Value; var ipart = test.Groups[2].Value; if (!isVar(spart, out temp)) { } if (int.TryParse(ipart, out testnum)) { str = def.repeat(this, temp.ToString(), (double)testnum); header = header.Replace(results[i].ToString(), str); } else if (isVar(ipart, out temp2)) { str = def.repeat(this, temp.ToString(), (double)temp2); header = header.Replace(results[i].ToString(), str); } else { PushError("When using the $varname*num$ expression num must be a number or a variable that is set to a number!"); } } if (isVar(str, out temp)) { header = header.Replace(results[i].ToString(), temp.ToString()); } else { header = header.Replace(results[i].ToString(), "null"); } } return header; } public object[] ResolveVar(string[] v) { //_defualtENV var len = v.Length; var args = new object[len]; object val; double num; bool boo; double ex; for (int i = 0; i < len; i++) { if (v[i] == "true") { args[i] = true; continue; } if (v[i] == "false") { args[i] = false; continue; } if (!v[i].StartsWith("[") && !v[i].StartsWith("\"")) ex = evaluater.Evaluate(this, v[i]); else ex = double.NaN; if (v[i].Length == 0 && len == 1) { return new object[]{ }; } if (v[i] == "[]") { args[i] = new ENV(); continue; } if (v[i].StartsWith("[")) { var result = GLOBALS.Split(v[i].Substring(1, v[i].Length - 2)); // TODO make ENV var res = ResolveVar(result); var env = new ENV(); for (int g = 0; g < res.Length; g++) { env[g] = res[g]; } args[i] = env; debug("TABLE: " + env); } else if (v[i].EndsWith("]")) { var dict = Regex.Match(v[i], @"(.*)\[(.+)\]"); var _var = dict.Groups[1].Value; var _val = dict.Groups[2].Value; var val2 = ResolveVar(new []{ _val }); var env = GetENV(); var _e = env[_var]; if (!_e.GetType().ToString().Contains("ENV")) { PushError("Attempted to index a object that isn't a table!"); } else { var e = (ENV)_e; if (val2[0].GetType().ToString().Contains("Double")) { args[i] = e[int.Parse(val2[0].ToString())]; } else if (val2[0].GetType().ToString().Contains("String")) { args[i] = e[(string)val2[0]]; } else { PushError("Invalid index type: " + val2[0]); } } } else if (isVar(v[i], out val)) { args[i] = val; debug("RETREVING SAVED VAL"); } else if (double.TryParse(v[i], out num)) { args[i] = num; debug("NUMBER: " + num); } else if (v[i][0] == '"' && v[i][v[i].Length - 1] == '"') { args[i] = parseHeader(v[i].Replace("\"", "")); debug("STRING: " + args[i]); } else if (bool.TryParse(v[i], out boo)) { args[i] = boo; debug("BOOL: " + boo); } else if (!double.IsNaN(ex)) { args[i] = ex; } else { args[i] = null; } } return args; } public int resolveLogic(bool b) { if (b) { return 1; } else { return 0; } } public bool resolveLogic(int b) { if (b == 1) { return true; } else { return true; } } public string Logic(string log) { log = Regex.Replace(log, "and", "*"); log = Regex.Replace(log, "or", "+"); foreach (Match m in Regex.Matches(log,@"\(?\s*(\S+?)\s*([=!><]+)\s*(\S+)\s*\)?")) { var a = m.Groups[1].Value; var b = m.Groups[2].Value; var c = m.Groups[3].Value; a = Regex.Replace(a, @"\(", ""); c = Regex.Replace(c, @"\)", ""); if (b == "==") { debug("=="); log = Regex.Replace(log, a + "\\s*" + b + "\\s*" + c, resolveLogic(ResolveVar(new []{ a })[0].ToString() == ResolveVar(new []{ c })[0].ToString()).ToString()); } else if (b == ">=") { debug(">="); log = Regex.Replace(log, a + "\\s*" + b + "\\s*" + c, resolveLogic(double.Parse(ResolveVar(new []{ a })[0].ToString()) >= double.Parse(ResolveVar(new []{ c })[0].ToString())).ToString()); } else if (b == "<=") { debug("<="); log = Regex.Replace(log, a + "\\s*" + b + "\\s*" + c, resolveLogic(double.Parse(ResolveVar(new []{ a })[0].ToString()) <= double.Parse(ResolveVar(new []{ c })[0].ToString())).ToString()); } else if (b == ">") { debug(">"); log = Regex.Replace(log, a + "\\s*" + b + "\\s*" + c, resolveLogic(double.Parse(ResolveVar(new []{ a })[0].ToString()) > double.Parse(ResolveVar(new []{ c })[0].ToString())).ToString()); } else if (b == "<") { debug("<"); log = Regex.Replace(log, a + "\\s*" + b + "\\s*" + c, resolveLogic(double.Parse(ResolveVar(new []{ a })[0].ToString()) < double.Parse(ResolveVar(new []{ c })[0].ToString())).ToString()); } else if (b == "!=") { debug("!="); log = Regex.Replace(log, a + "\\s*" + b + "\\s*" + c, resolveLogic(ResolveVar(new []{ a })[0].ToString() != ResolveVar(new []{ c })[0].ToString()).ToString()); } } return log; } public bool isVar(string val, out object v) { debug("TESTING: " + val); if (_defualtENV == null) { _defualtENV = _mainENV; } debug("GETTING VAL FROM ENV: " + _defualtENV[val]); if (_defualtENV[val] != null) { v = _defualtENV[val]; return true; } if (val.EndsWith("]")) { var dict = Regex.Match(val, @"(.*)\[(.+)\]"); var _var = dict.Groups[1].Value; var _val = dict.Groups[2].Value; var val2 = ResolveVar(new []{ _val }); var env = GetENV(); var _e = env[_var]; if (!_e.GetType().ToString().Contains("ENV")) { PushError("Attempted to index a object that isn't a table!"); } else { var e = (ENV)_e; if (val2[0].GetType().ToString().Contains("Double")) { v = e[int.Parse(val2[0].ToString())]; return true; } else if (val2[0].GetType().ToString().Contains("String")) { v = e[(string)val2[0]]; return true; } else { PushError("Invalid index type: " + val2[0]); } } } v = null; return false; } } /* * Helper Classes */ public class chunk { string _BLOCK; string _type; string _pureType; string[] _lines; string[] args; bool isFunc; string _hostfile; Dictionary _labels = new Dictionary(); List _compiledlines = new List(); int _pos = 0; chunk _next = null; public string[] GetArgs() { return args; } public chunk(string name, string cont, string type) { _BLOCK = name; _type = type; _clean(cont); } public bool isFunction() { return isFunc; } public chunk(string name, string cont) { _BLOCK = name; _type = "CODEBLOCK"; _clean(cont); } public void SetHostFile(string file) { _hostfile = file; } public string GetHostFile() { return _hostfile; } void _clean(string cont) { var m = Regex.Match(_type, @"([a-zA-Z0-9_]+)"); _pureType = m.Groups[1].ToString(); var tCont = Regex.Replace(cont, @"\-\-\[\[[\S\s]+\]\]", "", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"^\t+", "", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"\-\-.+\r\n", "\r\n", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"\-\-.+\n", "\n", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"\n\n", "", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"\r\n\r\n", "", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"\-\-\[\[[\S\s]+\]\]", "", RegexOptions.Multiline); tCont = Regex.Replace(tCont, @"^\s+$[\r\n]*", "", RegexOptions.Multiline); _lines = tCont.Split(new [] { "\r\n", "\n" }, StringSplitOptions.None); compile(); } void compile() { string temp; for (int i = 0; i < _lines.Length - 1; i++) { temp = _lines[i]; var pureLine = Regex.Match(temp, "^\"(.+)\""); var FuncTest = Regex.Match(temp, @"([a-zA-Z0-9_]+)\s?\((.*)\)"); var assignment = Regex.Match(temp, "^([a-zA-Z0-9_,\\[\\]\"]+)\\s*=\\s*(.+)"); var FuncWReturn = Regex.Match(temp, "([\\[\\]\"a-zA-Z0-9_,]+)\\s?=\\s?([a-zA-Z0-9_]+)\\s?\\((.*)\\)"); var FuncWOReturn = Regex.Match(temp, @"^([a-zA-Z0-9_]+)\s?\((.*)\)"); var label = Regex.Match(temp, "::(.*)::"); var logic = Regex.Match(temp, @"if\s*(.+)\s*then\s*(.+?\))\s*\|\s*(.+?\))"); if (logic.ToString() != "") { var condition = logic.Groups[1].ToString(); var tempif = logic.Groups[2].ToString(); var tempelse = logic.Groups[3].ToString(); var argsif = Regex.Match(tempif, @"^([a-zA-Z0-9_]+)\s?\((.*)\)"); var argselse = Regex.Match(tempelse, @"^([a-zA-Z0-9_]+)\s?\((.*)\)"); string _funcif = (argsif.Groups[1]).ToString(); var _argsif = (argsif.Groups[2]).ToString(); string[] _resultif = GLOBALS.Split(_argsif); string _funcelse = (argselse.Groups[1]).ToString(); var _argselse = (argselse.Groups[2]).ToString(); string[] _resultelse = GLOBALS.Split(_argselse); var mm = Regex.Matches(condition, "(.+?)([and ]+?[or ]+)"); var conds = new string[(mm.Count + 1) * 3]; var andors = new string[mm.Count]; var count = 0; var p = 0; var p2 = 0; foreach (Match m in mm) { var s1 = m.Groups[1].ToString(); var s1p = Regex.Match(s1, "(.+?)([~!><=]+)+(.+)"); var s1a = s1p.Groups[1].ToString(); var s1b = s1p.Groups[2].ToString(); var s1c = s1p.Groups[3].ToString(); var s2 = m.Groups[2].ToString(); conds[p++] = s1a; conds[p++] = s1b; conds[p++] = s1c; andors[p2++] = s2.Substring(1, 1); count += s1.Length + s2.Length; } var s1p2 = Regex.Match(condition.Substring(count, condition.Length - count - 1), "(.+?)([~!><=]+)+(.+)"); var s1a2 = s1p2.Groups[1].ToString(); var s1b2 = s1p2.Groups[2].ToString(); var s1c2 = s1p2.Groups[3].ToString(); conds[p++] = s1a2; conds[p++] = s1b2; conds[p++] = s1c2; _compiledlines.Add(new CMD("LOGIC", new object[] { condition, _funcif, _resultif, _funcelse, _resultelse })); } else if (label.ToString() != "") { _labels[label.Groups[1].ToString()] = i; _compiledlines.Add(new CMD("LABEL", new object[]{ })); } else if (FuncWReturn.ToString() != "") { var var1 = (FuncWReturn.Groups[1]).ToString(); var func = (FuncWReturn.Groups[2]).ToString(); var args2 = (FuncWReturn.Groups[3]).ToString(); var retargs = GLOBALS.Split(var1); var result = GLOBALS.Split(args2); _compiledlines.Add(new CMD("FUNC_R", new object[] { retargs, func, result })); } else if (FuncWOReturn.ToString() != "") { var func = (FuncWOReturn.Groups[1]).ToString(); var args2 = (FuncWOReturn.Groups[2]).ToString(); var result = GLOBALS.Split(args2); _compiledlines.Add(new CMD("FUNC", new object[]{ func, result })); } else if (pureLine.ToString() != "") { _compiledlines.Add(new CMD("LINE", new object[]{ pureLine.ToString() })); } else if (assignment.ToString() != "") { var vars = GLOBALS.Split(assignment.Groups[1].ToString()); var tabTest = assignment.Groups[2].ToString(); string[] vals = GLOBALS.Split(tabTest); //string[] vals = Regex.Split(assignment.Groups[2].ToString(), ",(?=(?:[^\"'\\[\\]]*[\"'\\[\\]][^\"'\\[\\]]*[\"'\\[\\]])*[^\"'\\[\\]]*$)"); _compiledlines.Add(new CMD("ASSIGN", new object[]{ vars, vals })); } else { _compiledlines.Add(new CMD("UNKNOWN", new object[]{ })); } } if (_type.Contains("function")) { isFunc = true; var func = Regex.Match(_type, @"\((.+)\)"); args = GLOBALS.Split(func.Groups[1].Value); _compiledlines.Add(new CMD("FUNC", new object[] { "TRACEBACK", new string[]{ } })); // Append the traceback method to the chunk } } public string GetName() { return _BLOCK; } public int GetLabel(string lab) { return _labels[lab]; } public bool TryGetLabel(string lab, out int pos) { int p; if (_labels.TryGetValue(lab, out p)) { pos = p; return true; } pos = -1; return false; } public void RemoveNextChunk() { _next = null; } public void SetNextChunk(chunk next) { _next = next; } public chunk GetNextChunk() { return _next; } public chunk SetNextChunk() { return _next; } public string[] GetLines() { return _lines; } public string GetLine() { string temp = _lines[_pos]; if (_pos == _lines.Length) { return null; } return temp; } public string GetCurrentLine() { string temp = ""; if (_pos == 0) { temp = _lines[_pos + 2]; } else { temp = _lines[_pos - 1]; } if (_pos - 1 == _lines.Length) { return null; } return temp; } public CMD GetCLine() { if (_pos < _compiledlines.Count) { return _compiledlines[_pos++]; } return null; } public int GetPos() { return _pos; } public void SetPos(int n) { _pos = n; } public void ResetPos() { _pos = 0; } public string GetChunkPType() { return _pureType; } public string GetChunkType() { return _type; } } public static class evaluater { public static double Evaluate(parseManager PM, string str) { string oldstr = str; object temp; double temp2; foreach (Match m in Regex.Matches(str, "([a-zA-Z0-9_]+)")) { if (!double.TryParse(m.Groups[0].Value, out temp2)) { temp2 = double.NaN; } if (PM.isVar(m.Groups[0].Value, out temp)) { if (temp.GetType().ToString().Contains("Double")) { str = str.Replace(m.Groups[0].Value, ((double)temp).ToString()); } else { return double.NaN; } } else if (!double.IsNaN(temp2)) { str = str.Replace(m.Groups[0].Value, temp2.ToString()); } else { return double.NaN;//PM.PushError("Variable \"" + m.Groups[0].Value + "\" does not exist"); } } double result; try { result = Convert.ToDouble(new DataTable().Compute(str, null)); } catch { result = double.NaN; } return result; } } [Serializable] public class ENV { bool _sen; ENV _Parent; bool _busyI; bool _busyS; Dictionary _vars = new Dictionary(); Dictionary _varsI = new Dictionary(); public void SetParent(ENV other) { _Parent = other; } public object[] GetList() { var temp = new object[_varsI.Count]; var count = 0; foreach (KeyValuePair entry in _varsI) { temp[count] = entry.Value; count++; } return temp; } public override string ToString() { string str = "("; foreach (KeyValuePair entry in _vars) { var val = entry.Value; if (val.GetType().ToString().Contains("ENV")) { val = "ENV"; } str += "[\"" + entry.Key + "\"] = " + val + ", "; } foreach (KeyValuePair entry in _varsI) { str += "[" + entry.Key + "] = " + entry.Value + ", "; } return str + ")"; } public bool TryGetValue(string ind, out object obj) { if (this[ind] != null) { obj = this[ind]; return true; } obj = null; return false; } public void SetSen(bool s) { _sen = s; } public bool TryGetValue(int ind, out object obj) { if (this[ind] != null) { obj = this[ind]; return true; } obj = null; return false; } public object this[string ind] { get { object obj; if (!_sen) { ind = ind.ToLower(); } if (_vars.TryGetValue(ind, out obj)) { return obj; } if (_Parent != null) { return _Parent[ind]; } return null; } set { while(_busyS){ // wait } _busyS=true; if (!_sen) { ind = ind.ToLower(); } _vars[ind] = value; _busyS=false; } } public object this[int ind] { get { object obj; if (_varsI.TryGetValue(ind, out obj)) { return obj; } if (_Parent != null) { return _Parent[ind]; } return null; } set { while(_busyI){ // wait } _busyI=true; _varsI[ind] = value; _busyI=false; } } } public class nextType { string _type; string _text; Dictionary _other = new Dictionary(); public nextType() { _type = "UNSET"; } public nextType(string type) { _type = type; } public string GetCMDType() { return _type; } public void SetText(string text) { _text = text; } public void SetCMDType(string type) { _type = type; } public string GetText() { return _text; } public object GetData(string name) { return _other[name]; } public void AddData(string varname, object data) { _other[varname] = data; } } public class CMD { string _type; object[] _args; public CMD(string type, object[] args) { _type = type; _args = args; } public string GetCMDType() { return _type; } public object[] GetArgs() { return _args; } } /* * The Standard Methods! */ static class GLOBALS { static standardDefine _define = new standardDefine(); static parseManager _main; static readonly ENV _env = new ENV(); static List _numvars = new List(); static List _Threads = new List(); public static parseManager[] GetThreads() { return _Threads.ToArray(); } public static void AddThread(parseManager PM) { _Threads.Add(PM); } public static void FixThreads(parseManager PM) { var PMS = _Threads.ToArray(); var env = PM.GetDENV(); for (int i = 0; i < PMS.Length; i++) { PMS[i]._SetDENV(env); PMS[i].SetENV(env); } } public static void WriteToBinaryFile(string filePath, ENV objectToWrite, bool append = false) { using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create)) { var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); binaryFormatter.Serialize(stream, objectToWrite); } } public static ENV ReadFromBinaryFile(string filePath) { using (Stream stream = File.Open(filePath, FileMode.Open)) { var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); return (ENV)binaryFormatter.Deserialize(stream); } } public static object GetData(string ind) { return _env[ind]; } public static standardDefine GetDefine() { return _define; } public static void AddData(string ind, object data) { _env[ind] = data; } public static void SetMainPM(parseManager o) { _main = o; } public static parseManager GetMainPM() { return _main; } public static void Add_Var(string var) { if (!_numvars.Contains(var)) { _numvars.Add(var); } } public static void Remove_Var(string var) { _numvars.Remove(var); } public static string[] GetVars() { return _numvars.ToArray(); } public static string[] Split(string split) { var res = new List(); var state = 0; var c = "."; var elem = ""; for (int gg = 0; gg < split.Length; gg++) { c = split.Substring(gg, 1); if (state == 3 || state == 0) { if (state == 3 && c == " ") { state = 0; } else { state = 0; if (c == "\"" || c == "'") { state = 1; elem += "\""; } else if (c == "[") { state = 1; elem += "["; } else if (c == ",") { res.Add(elem); elem = ""; state = 3; } else { elem += c; } } } else if (state == 1) { if (c == "\"" || c == "'") { state = 0; elem += "\""; } else if (c == "]") { state = 0; elem += "]"; } else if (c == "\\") { state = 2; } else { elem += c; } } else if (state == 2) { elem += c; state = 1; } } res.Add(elem); return res.ToArray(); } } } public class standardDefine { List devices = new List(); int count = -1; Random rnd = new Random(); int origRow = Console.CursorTop; int origCol = Console.CursorLeft; public void newThread(parseManager PM, string Block) { var thread = new Thread(() => _THREAD(Block, PM)); thread.Start(); } public void _THREAD(string block, parseManager _PM) { var define = _PM.GetDefine(); var path = _PM.GetFilepath(); parseManager PM; if (_PM.IsInternal()) { if (define == "NO_DEFINE") { PM = new parseManager(path, true); } else { PM = new parseManager(path, define, true); } } else { if (define == "NO_DEFINE") { PM = new parseManager(path); } else { PM = new parseManager(path, define); } } GLOBALS.AddThread(PM); PM.makeThread(); PM._SetDENV(_PM.GetDENV()); PM.SetENV(_PM.GetENV()); nextType next = PM.Next(block); string type; while (next.GetCMDType() != "EOF") { type = next.GetCMDType(); next = PM.Next(); } } public void _newThread(parseManager PM, string filename) { var thread = new Thread(() => _THREAD(PM, filename)); thread.Start(); } public void _THREAD(parseManager _PM, string filename) { parseManager PM = new parseManager(filename); GLOBALS.AddThread(PM); PM.makeThread(); PM._SetDENV(_PM.GetDENV()); PM.SetENV(_PM.GetENV()); nextType next = PM.Next(); string type; while (next.GetCMDType() != "EOF") { type = next.GetCMDType(); next = PM.Next(); } } public void SAVE(parseManager PM, string name) { if (PM.isAThread()) { GLOBALS.GetMainPM().PushError("Cannot Call SAVE() in a thread!"); } var env = PM.GetDENV(); var c = PM.GetCurrentChunk(); env["__CurrentChunkName"] = c.GetName(); env["__CurrentChunkPos"] = c.GetPos(); env["__DefualtENV"] = PM.GetENV(); GLOBALS.WriteToBinaryFile(name, env); } public bool LOAD(parseManager PM, string _name) { if (PM.isAThread()) { GLOBALS.GetMainPM().PushError("Cannot Call LOAD() in a thread!"); } try { ENV env = GLOBALS.ReadFromBinaryFile(_name); var name = (string)env["__CurrentChunkName"]; var pos = (int)env["__CurrentChunkPos"]; var denv = (ENV)env["__DefualtENV"]; PM._SetDENV(env); PM.SetENV(denv); PM.SetBlock(name); PM.GetCurrentChunk().SetPos(pos); GLOBALS.FixThreads(PM); return true; } catch { return false; } } public void TRACEBACK(parseManager PM) { ENV env = PM.Pop(); PM.SetBlock((string)env[0]); var c = PM.GetCurrentChunk(); c.SetPos((int)env[1]); setENV(PM, (ENV)env[3]); } public void EXIT(parseManager PM) { cleanUpAudio(); PM.Deactivate(); } public void QUIT(parseManager PM) { cleanUpAudio(); Environment.Exit(0); } public void setENV(parseManager PM, ENV env) { PM.SetENV(env); } public ENV getENV(parseManager PM) { return PM.GetENV(); } public ENV getDefualtENV(parseManager PM) { return PM.GetDENV(); } public ENV createENV(parseManager PM) { var temp = new ENV(); temp.SetParent(PM.GetENV()); return temp; } public string repeat(parseManager PM, string str, double n) { return string.Concat(Enumerable.Repeat(str, (int)n)); } public string getInput(parseManager PM) { return Console.ReadLine(); } public void setCC(parseManager PM) { Console.SetCursorPosition(0, Console.CursorTop - 1); } public void whiteOut(parseManager PM) { for (int i = 0; i < Console.BufferWidth; i++) { Console.Write(" "); } } public void setBG(parseManager PM, ConsoleColor BG) { Console.BackgroundColor = BG; } public void setFG(parseManager PM, ConsoleColor FG) { Console.ForegroundColor = FG; } public void resetColor(parseManager PM) { Console.ResetColor(); } public int GOTO(parseManager PM, string label) { var c = PM.GetCurrentChunk(); int pos; if (c.TryGetLabel(label, out pos)) { c.SetPos(pos); return 0; } else if (PM.GetFlag("forseelabels")) { var chunks = PM.GetChunks(); for (int i = 0; i < chunks.Length; i++) { if (chunks[i].TryGetLabel(label, out pos)) { PM.SetBlock(chunks[i].GetName()); chunks[i].SetPos(pos); return 0; } } } PM.PushError("Unable to GOTO a non existing label: \"" + label + "\""); return 0; } public double len(parseManager PM, object o) { string type = o.GetType().ToString(); if (type.Contains("String")) { return (double)((string)o).Length; } if (type.Contains("ENV")) { return (double)((ENV)o).GetList().Length; } return 0; } public void JUMP(parseManager PM, string block) { var c = PM.GetCurrentChunk(); c.ResetPos(); PM.SetBlock(block); } public void SKIP(parseManager PM, double n) { var c = PM.GetCurrentChunk(); var pos = c.GetPos(); c.SetPos(pos + (int)n); } public double tonumber(parseManager PM, string strn) { double d; if (double.TryParse(strn, out d)) { return d; } PM.debug("Cannot convert to a number!"); return double.NaN; } public void sleep(parseManager PM, double n) { Thread.Sleep((int)n); } public void setVar(parseManager PM, string var, object value) { var env = PM.GetDENV(); env[var] = value; } public double ADD(parseManager PM, double a, double b) { return a + b; } public double SUB(parseManager PM, double a, double b) { return a - b; } public double MUL(parseManager PM, double a, double b) { return a * b; } public double DIV(parseManager PM, double a, double b) { return a / b; } public double MOD(parseManager PM, double a, double b) { return a % b; } public double CALC(parseManager PM, string ex) { return evaluater.Evaluate(PM, ex); } public void pause(parseManager PM) { if (!PM.isAThread()) { PM.Pause(); } else { PM.debug("WARNING: Calling pause with the main thread is not allowed!"); } } public void resume(parseManager PM) { PM.Resume(); } public void print(parseManager PM, object o) { Console.WriteLine(o); } public double random(parseManager PM, double s, double e) { return (double)rnd.Next((int)s, (int)e); } public double rand(parseManager PM) { return rnd.NextDouble(); } public void randomseed(parseManager PM,double seed){ rnd = new Random((int)seed); } public double round(parseManager PM, double num, double n) { return Math.Round(num, (int)n); } public void clear(parseManager PM) { Console.Clear(); } public void write(parseManager PM, object o) { Console.Write(o); } public void backspace(parseManager PM) { Console.Write("\b"); } public void beep(parseManager PM) { Console.Beep(); } public void fancy(parseManager PM, string msg) { Fancy.Print(msg); } public void setFancyForm(parseManager PM, string form) { Fancy.SetForm(form); } public void setFancyType(parseManager PM, double f) { Fancy.SetFVar((int)f); } public void stopSong(parseManager PM, double id) { devices[(int)id].Stop(); } public void playSong(parseManager PM, double id) { devices[(int)id].Play(); } public void resumeSong(parseManager PM, double id) { devices[(int)id].Play(); } public void setSongVolume(parseManager PM, double id, double vol) { devices[(int)id].Volume = (float)vol; } public void pauseSong(parseManager PM, double id) { devices[(int)id].Pause(); } public void replaySong(parseManager PM, double id) { devices[(int)id].Stop(); devices[(int)id].Play(); } public double loadSong(parseManager PM, string filepath) { count++; devices.Add(new WaveOut()); var temp = new AudioFileReader(filepath); devices[count].Init(temp); return count; } void cleanUpAudio() { for (int i = 0; i < devices.Count; i++) { devices[i].Stop(); devices[i].Dispose(); } } public void setPosition(parseManager PM, double x, double y) { Console.SetCursorPosition((int)x, (int)y); } public void writeAt(parseManager PM, string s, double x, double y) { try { Console.SetCursorPosition(origCol + (int)x, origRow + (int)y); Console.Write(s); } catch (ArgumentOutOfRangeException e) { Console.Clear(); PM.PushError(e.Message); } } public void setWindowSize(parseManager PM, double x, double y) { Console.SetWindowSize((int)x, (int)y); } public double getConsoleWidth(parseManager PM) { return Console.WindowWidth; } public double getConsoleHeight(parseManager PM) { return Console.WindowHeight; } public bool isDown(parseManager PM, string key) { if (!ApplicationIsActivated()) { return false; } Key kk = Key.Zoom; var k = key.ToUpper(); if (k == "A") { kk = Key.A; } else if (k == "B") { kk = Key.B; } else if (k == "C") { kk = Key.C; } else if (k == "D") { kk = Key.D; } else if (k == "E") { kk = Key.E; } else if (k == "F") { kk = Key.F; } else if (k == "G") { kk = Key.G; } else if (k == "H") { kk = Key.H; } else if (k == "I") { kk = Key.I; } else if (k == "J") { kk = Key.J; } else if (k == "K") { kk = Key.K; } else if (k == "L") { kk = Key.L; } else if (k == "M") { kk = Key.M; } else if (k == "N") { kk = Key.N; } else if (k == "O") { kk = Key.O; } else if (k == "P") { kk = Key.P; } else if (k == "Q") { kk = Key.Q; } else if (k == "R") { kk = Key.R; } else if (k == "S") { kk = Key.S; } else if (k == "T") { kk = Key.T; } else if (k == "U") { kk = Key.U; } else if (k == "V") { kk = Key.V; } else if (k == "W") { kk = Key.W; } else if (k == "X") { kk = Key.X; } else if (k == "Y") { kk = Key.Y; } else if (k == "Z") { kk = Key.Z; } else if (k == "{UP}") { kk = Key.Up; } else if (k == "{DOWN}") { kk = Key.Down; } else if (k == "{LEFT}") { kk = Key.Left; } else if (k == "{RIGHT}") { kk = Key.Right; } else if (k == "{ENTER}") { kk = Key.Enter; } else if (k == "{LSHIFT}") { kk = Key.LeftShift; } else if (k == "{RSHIFT}") { kk = Key.RightShift; } else if (k == "0") { kk = Key.D0; } else if (k == "1") { kk = Key.D1; } else if (k == "2") { kk = Key.D2; } else if (k == "3") { kk = Key.D3; } else if (k == "4") { kk = Key.D4; } else if (k == "5") { kk = Key.D5; } else if (k == "6") { kk = Key.D6; } else if (k == "7") { kk = Key.D7; } else if (k == "8") { kk = Key.D8; } else if (k == "9") { kk = Key.D9; } else if (k == "{SPACE}") { kk = Key.Space; } return Keyboard.IsKeyDown(kk); } public void error(parseManager PM, string msg) { PM.PushError(msg); } public string isPressing(parseManager PM) { return Console.ReadKey(true).Key.ToString(); } public static bool ApplicationIsActivated() { var activatedHandle = GetForegroundWindow(); if (activatedHandle == IntPtr.Zero) { return false; // No window is currently activated } else { var procId = Process.GetCurrentProcess().Id; int activeProcId; GetWindowThreadProcessId(activatedHandle, out activeProcId); return activeProcId == procId; } } [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern int GetWindowThreadProcessId(IntPtr handle, out int processId); }