public void AddNativeProperty(string propertyDesc, ScriptCallbackCB callbackCB, object userData) { var oldLex = currentLexer; currentLexer = new ScriptLex(propertyDesc); var baseVar = Root; var propName = currentLexer.TokenString; currentLexer.Match(ScriptLex.LexTypes.Id); while (currentLexer.TokenType == (ScriptLex.LexTypes) '.') { currentLexer.Match((ScriptLex.LexTypes) '.'); var link = baseVar.FindChild(propName); if (link == null) { link = baseVar.AddChild(propName, new ScriptVar(null, ScriptVar.Flags.Object)); } baseVar = link.Var; propName = currentLexer.TokenString; currentLexer.Match(ScriptLex.LexTypes.Id); } var propVar = new ScriptVar(); callbackCB.Invoke(propVar, null); currentLexer = oldLex; baseVar.AddChild(propName, propVar); }
public ScriptLex(ScriptLex owner, int start, int end) { data = owner.data; dataOwned = false; dataStart = start; dataEnd = end; Reset(); }
public ScriptLex(ScriptLex owner, Int32 start, Int32 end) { _data = owner._data; _dataOwned = false; _dataStart = start; _dataEnd = end; Reset(); }
public ScriptVarLink EvalComplex(String code) { ScriptLex oldLex = _currentLexer; Stack <ScriptVar> oldScopes = _scopes; _currentLexer = new ScriptLex(code); _callStack.Clear(); _scopes.Clear(); _scopes.Push(Root); ScriptVarLink v = null; try { bool execute = true; do { v = Base(ref execute); if (_currentLexer.TokenType != ScriptLex.LexTypes.Eof) { _currentLexer.Match((ScriptLex.LexTypes) ';'); } } while (_currentLexer.TokenType != ScriptLex.LexTypes.Eof); } catch (ScriptException ex) { String errorMessage = ex.Message; int i = 0; foreach (ScriptVar scriptVar in _scopes) { errorMessage += "\n" + i++ + ": " + scriptVar; } #if WINDOWS_UWP Debug.WriteLine(errorMessage); #else Console.Write(errorMessage); #endif } _currentLexer = oldLex; _scopes = oldScopes; if (v != null) { return(v); } return(new ScriptVarLink(new ScriptVar(null), null)); }
public ScriptVarLink EvalComplex(string code) { var oldLex = currentLexer; var oldScopes = scopes; currentLexer = new ScriptLex(code); scopes = new List <ScriptVar>(); //callStack.Clear(); scopes.Clear(); scopes.PushBack(Root); ScriptVarLink v = null; try { var execute = true; do { v = Base(ref execute); if (currentLexer.TokenType != ScriptLex.LexTypes.Eof) { currentLexer.Match((ScriptLex.LexTypes) ';'); } } while (currentLexer.TokenType != ScriptLex.LexTypes.Eof); } catch (ScriptException ex) { var errorMessage = new StringBuilder(string.Format("ERROR on line {0} column {1} [{2}]", currentLexer.LineNumber, currentLexer.ColumnNumber, ex.Message)); int i = 0; foreach (ScriptVar scriptVar in scopes) { errorMessage.AppendLine(); errorMessage.Append(i++ + ": " + scriptVar); } Console.Error.WriteLine(errorMessage.ToString()); } currentLexer = oldLex; scopes = oldScopes; if (v != null) { return(v); } return(new ScriptVarLink(new ScriptVar(null), null)); }
public void Execute(string code) { var oldLex = currentLexer; var oldScopes = scopes; scopes = new List <ScriptVar>(); scopes.Clear(); scopes.PushBack(Root); var rootLink = new ScriptVarLink(Root, "root"); callStack.Push(rootLink); using (currentLexer = new ScriptLex(code)) { var execute = true; while (currentLexer.TokenType != 0) { try { Statement(ref execute); } catch (Exception ex) { if (ex is ScriptException || ex is JITException) { var errorMessage = new StringBuilder(string.Format("ERROR on line {0} column {1} [{2}]", currentLexer.LineNumber, currentLexer.ColumnNumber, ex.Message)); Console.Error.WriteLine(errorMessage.ToString()); return; } else { throw; } } } } callStack.Pop(); currentLexer = oldLex; scopes = oldScopes; }
public ScriptEngine() { currentLexer = null; scopes = new List <ScriptVar>(); callStack = new Stack <ScriptVarLink>(); Root = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); objectClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); stringClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); arrayClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); Root.AddChild("Object", objectClass); Root.AddChild("String", stringClass); Root.AddChild("Array", arrayClass); }
public ScriptEngine(bool loadProviders = true) { _currentLexer = null; _scopes = new Stack <ScriptVar>(); _callStack = new Stack <string>(); Root = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); _stringClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); _objectClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); _arrayClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref(); Root.AddChild("String", _stringClass); Root.AddChild("Object", _objectClass); Root.AddChild("Array", _arrayClass); if (loadProviders) { LoadAllFunctionProviders(); } }
public void AddMethod(String funcProto, ScriptCallbackCB callback, Object userdata) { ScriptLex oldLex = _currentLexer; using (_currentLexer = new ScriptLex(funcProto)) { ScriptVar baseVar = Root; _currentLexer.Match(ScriptLex.LexTypes.RFunction); String funcName = _currentLexer.TokenString; _currentLexer.Match(ScriptLex.LexTypes.Id); while (_currentLexer.TokenType == (ScriptLex.LexTypes) '.') { _currentLexer.Match((ScriptLex.LexTypes) '.'); ScriptVarLink link = baseVar.FindChild(funcName); if (link == null) { link = baseVar.AddChild(funcName, new ScriptVar(null, ScriptVar.Flags.Object)); } baseVar = link.Var; funcName = _currentLexer.TokenString; _currentLexer.Match(ScriptLex.LexTypes.Id); } ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native); funcVar.SetCallback(callback, userdata); ParseFunctionArguments(funcVar); baseVar.AddChild(funcName, funcVar); } _currentLexer = oldLex; }
public void Execute(String code) { ScriptLex oldLex = _currentLexer; Stack <ScriptVar> oldScopes = _scopes; using (_currentLexer = new ScriptLex(code)) { _scopes.Clear(); _scopes.Push(Root); _callStack.Clear(); try { while (_currentLexer.TokenType != 0) { bool execute = true; Statement(ref execute); } } catch (ScriptException ex) { String errorMessage = String.Format("ERROR on line {0} column {1} [{2}]", _currentLexer.LineNumber, _currentLexer.ColumnNumber, ex.Message); int i = 0; foreach (ScriptVar scriptVar in _scopes) { errorMessage += "\n" + i++ + ": " + scriptVar; } Console.Write(errorMessage); } } _currentLexer = oldLex; _scopes = oldScopes; }
public void AddNative(string funcDesc, ScriptCallbackCB callbackCB, object userData) { var oldLex = currentLexer; currentLexer = new ScriptLex(funcDesc); var baseVar = Root; currentLexer.Match(ScriptLex.LexTypes.RFunction); var funcName = currentLexer.TokenString; currentLexer.Match(ScriptLex.LexTypes.Id); while (currentLexer.TokenType == (ScriptLex.LexTypes) '.') { currentLexer.Match((ScriptLex.LexTypes) '.'); var link = baseVar.FindChild(funcName); if (link == null) { link = baseVar.AddChild(funcName, new ScriptVar(null, ScriptVar.Flags.Object)); } baseVar = link.Var; funcName = currentLexer.TokenString; currentLexer.Match(ScriptLex.LexTypes.Id); } var funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native); funcVar.SetCallback(callbackCB, userData); ParseFunctionArguments(funcVar); currentLexer = oldLex; baseVar.AddChild(funcName, funcVar); }
private ScriptVarLink FunctionCall(ref bool execute, ScriptVarLink function, ScriptVar parent) { if (execute) { if (!function.Var.IsFunction) { throw new ScriptException(String.Format("{0} is not a function", function.Name)); } currentLexer.Match((ScriptLex.LexTypes) '('); var functionRoot = new ScriptVar(null, ScriptVar.Flags.Function); if (parent != null) { functionRoot.AddChildNoDup("this", parent); } var v = function.Var.FirstChild; while (v != null) { var value = Base(ref execute); if (execute) { if (value.Var.IsBasic) { //pass by val functionRoot.AddChild(v.Name, value.Var.DeepCopy()); } else { //pass by ref functionRoot.AddChild(v.Name, value.Var); } } if (currentLexer.TokenType != (ScriptLex.LexTypes) ')') { currentLexer.Match((ScriptLex.LexTypes) ','); } v = v.Next; } currentLexer.Match((ScriptLex.LexTypes) ')'); var returnVarLink = functionRoot.AddChild(ScriptVar.ReturnVarName, null); scopes.PushBack(functionRoot); //callStack.PushBack(string.Format("{0} from line {1}", function.Name, currentLexer.LineNumber)); callStack.Push(function); if (function.Var.IsNative) { var func = function.Var.GetCallback(); func?.Invoke(functionRoot, function.Var.GetCallbackUserData()); } else { var oldLex = currentLexer; var newLex = new ScriptLex(function.Var.String); currentLexer = newLex; try { Block(ref execute); execute = true; } catch { throw; } finally { currentLexer = oldLex; } } callStack.Pop(); scopes.PopBack(); var returnVar = new ScriptVarLink(returnVarLink.Var, null); functionRoot.RemoveLink(returnVarLink); return(returnVar); } else { //not executing the function, just parsing it out currentLexer.Match((ScriptLex.LexTypes) '('); while (currentLexer.TokenType != (ScriptLex.LexTypes) ')') { Base(ref execute); if (currentLexer.TokenType != (ScriptLex.LexTypes) ')') { currentLexer.Match((ScriptLex.LexTypes) ','); } } currentLexer.Match((ScriptLex.LexTypes) ')'); if (currentLexer.TokenType == (ScriptLex.LexTypes) '{') //WTF? { Block(ref execute); } return(function); } }
public void Execute(String code) { ScriptLex oldLex = _currentLexer; Stack <ScriptVar> oldScopes = _scopes; // Preprocess script and expand any libraries if needed IncludedLibraries.Clear(); foreach (KimonoProperty property in ObiScriptPortfolio.Portfolio.Properties) { // Is this a script library? if (property is KimonoPropertyLibrary) { // Yes, see if it has been included in the current script var token = $"using {property.Name};"; // Included? if (code.Contains(token)) { // Yes, is the library already included? if (LibraryIncluded(property.Name)) { // Yes, just remove this call code = code.Replace(token, ""); } else { // No, expand the library into this script and // mark library as included code = code.Replace(token, property.ObiScript); IncludedLibraries.Add(property.Name); } } } } using (_currentLexer = new ScriptLex(code)) { _scopes.Clear(); _scopes.Push(Root); _callStack.Clear(); // Clear results ObiScriptEngine.EvaluationResult.Successful = true; ObiScriptEngine.EvaluationResult.ErrorMessage = ""; ObiScriptEngine.EvaluationResult.Value = this; try { while (_currentLexer.TokenType != 0) { bool execute = true; Statement(ref execute); } } catch (ScriptException ex) { // Record error ObiScriptEngine.EvaluationResult.Successful = false; ObiScriptEngine.EvaluationResult.ErrorMessage = String.Format("ERROR on line {0} column {1} [{2}]", _currentLexer.LineNumber, _currentLexer.ColumnNumber, ex.Message); int i = 0; foreach (ScriptVar scriptVar in _scopes) { ObiScriptEngine.EvaluationResult.ErrorMessage += "\n" + i++ + ": " + scriptVar; } // Clear result ObiScriptEngine.EvaluationResult.Value = null; } } _currentLexer = oldLex; _scopes = oldScopes; }
private void Statement(ref bool execute) { if (_currentLexer.TokenType == ScriptLex.LexTypes.Id || _currentLexer.TokenType == ScriptLex.LexTypes.Int || _currentLexer.TokenType == ScriptLex.LexTypes.Float || _currentLexer.TokenType == ScriptLex.LexTypes.Str || _currentLexer.TokenType == (ScriptLex.LexTypes) '-') { //execite a basic statement Base(ref execute); _currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (_currentLexer.TokenType == (ScriptLex.LexTypes) '{') { //code block Block(ref execute); } else if (_currentLexer.TokenType == (ScriptLex.LexTypes) ';') { //allow for multiple semi colon such as ;;; _currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (_currentLexer.TokenType == ScriptLex.LexTypes.RVar) { //creating variables //TODO: make this less shit _currentLexer.Match(ScriptLex.LexTypes.RVar); while (_currentLexer.TokenType != (ScriptLex.LexTypes) ';') { ScriptVarLink a = null; if (execute) { a = _scopes.Peek().FindChildOrCreate(_currentLexer.TokenString); } _currentLexer.Match(ScriptLex.LexTypes.Id); //get through the dots while (_currentLexer.TokenType == (ScriptLex.LexTypes) '.') { _currentLexer.Match((ScriptLex.LexTypes) '.'); if (execute) { ScriptVarLink aLast = a; if (aLast != null) { a = aLast.Var.FindChildOrCreate(_currentLexer.TokenString); } } _currentLexer.Match(ScriptLex.LexTypes.Id); } //initialiser if (_currentLexer.TokenType == (ScriptLex.LexTypes) '=') { _currentLexer.Match((ScriptLex.LexTypes) '='); ScriptVarLink varLink = Base(ref execute); if (execute) { if (a != null) { a.ReplaceWith(varLink); } } } if (_currentLexer.TokenType != (ScriptLex.LexTypes) ';') { _currentLexer.Match((ScriptLex.LexTypes) ','); } } _currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (_currentLexer.TokenType == ScriptLex.LexTypes.RIf) { //if condition _currentLexer.Match(ScriptLex.LexTypes.RIf); _currentLexer.Match((ScriptLex.LexTypes) '('); ScriptVarLink varLink = Base(ref execute); _currentLexer.Match((ScriptLex.LexTypes) ')'); bool condition = execute && varLink.Var.GetBool(); bool noExecute = false; if (condition) { Statement(ref execute); } else { Statement(ref noExecute); } if (_currentLexer.TokenType == ScriptLex.LexTypes.RElse) { //else part of an if _currentLexer.Match(ScriptLex.LexTypes.RElse); if (condition) { Statement(ref noExecute); } else { Statement(ref execute); } } } else if (_currentLexer.TokenType == ScriptLex.LexTypes.RWhile) { //while loop _currentLexer.Match(ScriptLex.LexTypes.RWhile); _currentLexer.Match((ScriptLex.LexTypes) '('); Int32 whileConditionStart = _currentLexer.TokenStart; ScriptVarLink condition = Base(ref execute); bool loopCondition = execute && condition.Var.GetBool(); ScriptLex whileCond = _currentLexer.GetSubLex(whileConditionStart); _currentLexer.Match((ScriptLex.LexTypes) ')'); Int32 whileBodyStart = _currentLexer.TokenStart; Statement(ref loopCondition); ScriptLex whileBody = _currentLexer.GetSubLex(whileBodyStart); ScriptLex oldLex = _currentLexer; //TODO: possible maximum itteration limit? while (loopCondition) { whileCond.Reset(); _currentLexer = whileCond; condition = Base(ref execute); loopCondition = condition.Var.GetBool(); if (loopCondition) { whileBody.Reset(); _currentLexer = whileBody; Statement(ref execute); } } _currentLexer = oldLex; } else if (_currentLexer.TokenType == ScriptLex.LexTypes.RFor) { //for loop _currentLexer.Match(ScriptLex.LexTypes.RFor); _currentLexer.Match((ScriptLex.LexTypes) '('); Statement(ref execute); //init int forConditionStart = _currentLexer.TokenStart; ScriptVarLink condition = Base(ref execute); bool noExecute = false; bool loopCondition = execute && condition.Var.GetBool(); ScriptLex forCondition = _currentLexer.GetSubLex(forConditionStart); _currentLexer.Match((ScriptLex.LexTypes) ';'); int forIterStart = _currentLexer.TokenStart; Base(ref noExecute); ScriptLex forIter = _currentLexer.GetSubLex(forIterStart); _currentLexer.Match((ScriptLex.LexTypes) ')'); int forBodyStart = _currentLexer.TokenStart; if (loopCondition) { Statement(ref execute); } else { Statement(ref noExecute); } ScriptLex forBody = _currentLexer.GetSubLex(forBodyStart); ScriptLex oldLex = _currentLexer; if (loopCondition) { forIter.Reset(); _currentLexer = forIter; Base(ref execute); } //TODO: limit number of iterations? while (execute && loopCondition) { forCondition.Reset(); _currentLexer = forCondition; condition = Base(ref execute); loopCondition = condition.Var.GetBool(); if (execute && loopCondition) { forBody.Reset(); _currentLexer = forBody; Statement(ref execute); } if (execute && loopCondition) { forIter.Reset(); _currentLexer = forIter; Base(ref execute); } } _currentLexer = oldLex; } else if (_currentLexer.TokenType == ScriptLex.LexTypes.RReturn) { _currentLexer.Match(ScriptLex.LexTypes.RReturn); ScriptVarLink res = null; if (_currentLexer.TokenType != (ScriptLex.LexTypes) ';') { res = Base(ref execute); } if (execute) { ScriptVarLink resultVar = _scopes.Peek().FindChild(ScriptVar.ReturnVarName); if (resultVar != null) { resultVar.ReplaceWith(res); } else { //return statement outside of function??? System.Diagnostics.Trace.TraceWarning("Return statement outside of a function, what is going on?"); } } execute = false; _currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (_currentLexer.TokenType == ScriptLex.LexTypes.RFunction) { //function ScriptVarLink funcVar = ParseFunctionDefinition(); if (execute) { if (funcVar.Name == String.Empty) { //functions must have a name at statement level } else { ScriptVar v = _scopes.Peek(); v.AddChildNoDup(funcVar.Name, funcVar.Var); } } } else { _currentLexer.Match(ScriptLex.LexTypes.Eof); } }
private ScriptVarLink FunctionCall(ref bool execute, ScriptVarLink function, ScriptVar parent) { if (execute) { if (!function.Var.IsFunction) { throw new ScriptException(String.Format("{0} is not a function", function.Name)); } _currentLexer.Match((ScriptLex.LexTypes) '('); ScriptVar functionRoot = new ScriptVar(null, ScriptVar.Flags.Function); if (parent != null) { functionRoot.AddChildNoDup("this", parent); } ScriptVarLink v = function.Var.FirstChild; while (v != null) { ScriptVarLink value = Base(ref execute); if (value.Var.IsBasic) { //pass by val functionRoot.AddChild(v.Name, value.Var.DeepCopy()); } else { //pass by ref functionRoot.AddChild(v.Name, value.Var); } if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')') { _currentLexer.Match((ScriptLex.LexTypes) ','); } v = v.Next; } _currentLexer.Match((ScriptLex.LexTypes) ')'); ScriptVarLink returnVarLink = functionRoot.AddChild(ScriptVar.ReturnVarName, null); _scopes.Push(functionRoot); _callStack.Push(String.Format("{0} from line {1}", function.Name, _currentLexer.LineNumber)); if (function.Var.IsNative) { ScriptCallbackCB func = function.Var.GetCallback(); if (func != null) { func(functionRoot, function.Var.GetCallbackUserData(), parent); } } else { ScriptException ex = null; ScriptLex oldLex = _currentLexer; ScriptLex newLex = new ScriptLex(function.Var.GetString()); _currentLexer = newLex; try { Block(ref execute); execute = true; } catch (ScriptException e) { ex = e; } _currentLexer = oldLex; if (ex != null) { throw ex; } } _callStack.Pop(); _scopes.Pop(); ScriptVarLink returnVar = new ScriptVarLink(returnVarLink.Var, null); functionRoot.RemoveLink(returnVarLink); return(returnVar); } //not executing the function, just parsing it out _currentLexer.Match((ScriptLex.LexTypes) '('); while (_currentLexer.TokenType != (ScriptLex.LexTypes) ')') { Base(ref execute); if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')') { _currentLexer.Match((ScriptLex.LexTypes) ','); } } _currentLexer.Match((ScriptLex.LexTypes) ')'); if (_currentLexer.TokenType == (ScriptLex.LexTypes) '{') //WTF? { Block(ref execute); } return(function); }
private void Statement(ref bool execute) { if (currentLexer.TokenType == (ScriptLex.LexTypes) '{') { //code block Block(ref execute); } else if (currentLexer.TokenType == (ScriptLex.LexTypes) ';') { //allow for multiple semi colon such as ;;; currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (currentLexer.TokenType == ScriptLex.LexTypes.RVar || currentLexer.TokenType == ScriptLex.LexTypes.RConst) { //creating variables //TODO: make this less shit var readOnly = currentLexer.TokenType == ScriptLex.LexTypes.RConst; currentLexer.Match(currentLexer.TokenType); while (currentLexer.TokenType != (ScriptLex.LexTypes) ';') { ScriptVarLink a = null; if (execute) { a = scopes.Back().FindChildOrCreate(currentLexer.TokenString, ScriptVar.Flags.Undefined, readOnly); } currentLexer.Match(ScriptLex.LexTypes.Id); //get through the dots while (currentLexer.TokenType == (ScriptLex.LexTypes) '.') { currentLexer.Match((ScriptLex.LexTypes) '.'); if (execute) { var aLast = a; if (aLast != null) { a = aLast.Var.FindChildOrCreate(currentLexer.TokenString); } } currentLexer.Match(ScriptLex.LexTypes.Id); } //initialiser if (currentLexer.TokenType == (ScriptLex.LexTypes) '=') { currentLexer.Match((ScriptLex.LexTypes) '='); var varLink = Base(ref execute); if (execute) { if (a != null) { a.ReplaceWith(varLink); } } } if (currentLexer.TokenType != (ScriptLex.LexTypes) ';') { currentLexer.Match((ScriptLex.LexTypes) ','); } } currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (currentLexer.TokenType == ScriptLex.LexTypes.RIf) { //if condition currentLexer.Match(ScriptLex.LexTypes.RIf); currentLexer.Match((ScriptLex.LexTypes) '('); var varLink = Base(ref execute); currentLexer.Match((ScriptLex.LexTypes) ')'); bool condition = execute && varLink.Var.Bool; bool noExecute = false; if (condition) { Statement(ref execute); } else { Statement(ref noExecute); } if (currentLexer.TokenType == ScriptLex.LexTypes.RElse) { //else part of an if currentLexer.Match(ScriptLex.LexTypes.RElse); if (condition) { Statement(ref noExecute); } else { Statement(ref execute); } } } else if (currentLexer.TokenType == ScriptLex.LexTypes.RWhile) { //while loop currentLexer.Match(ScriptLex.LexTypes.RWhile); currentLexer.Match((ScriptLex.LexTypes) '('); var whileConditionStart = currentLexer.TokenStart; var noExecute = false; var condition = Base(ref execute); var loopCondition = execute && condition.Var.Bool; var whileCond = currentLexer.GetSubLex(whileConditionStart); currentLexer.Match((ScriptLex.LexTypes) ')'); var whileBodyStart = currentLexer.TokenStart; if (loopCondition) { Statement(ref execute); } else { Statement(ref noExecute); } var whileBody = currentLexer.GetSubLex(whileBodyStart); var oldLex = currentLexer; //TODO: possible maximum itteration limit? while (loopCondition) { whileCond.Reset(); currentLexer = whileCond; condition = Base(ref execute); loopCondition = execute && condition.Var.Bool; if (loopCondition) { whileBody.Reset(); currentLexer = whileBody; Statement(ref execute); } } currentLexer = oldLex; } else if (currentLexer.TokenType == ScriptLex.LexTypes.RFor) { //for loop currentLexer.Match(ScriptLex.LexTypes.RFor); currentLexer.Match((ScriptLex.LexTypes) '('); Statement(ref execute); //init var forConditionStart = currentLexer.TokenStart; var condition = Base(ref execute); var noExecute = false; var loopCondition = execute && condition.Var.Bool; var forCondition = currentLexer.GetSubLex(forConditionStart); currentLexer.Match((ScriptLex.LexTypes) ';'); var forIterStart = currentLexer.TokenStart; Base(ref noExecute); var forIter = currentLexer.GetSubLex(forIterStart); currentLexer.Match((ScriptLex.LexTypes) ')'); var forBodyStart = currentLexer.TokenStart; if (loopCondition) { Statement(ref execute); } else { Statement(ref noExecute); } var forBody = currentLexer.GetSubLex(forBodyStart); var oldLex = currentLexer; if (loopCondition) { forIter.Reset(); currentLexer = forIter; Base(ref execute); } //TODO: limit number of iterations? while (execute && loopCondition) { forCondition.Reset(); currentLexer = forCondition; condition = Base(ref execute); loopCondition = condition.Var.Bool; if (execute && loopCondition) { forBody.Reset(); currentLexer = forBody; Statement(ref execute); } if (execute && loopCondition) { forIter.Reset(); currentLexer = forIter; Base(ref execute); } } currentLexer = oldLex; } else if (currentLexer.TokenType == ScriptLex.LexTypes.RReturn) { currentLexer.Match(ScriptLex.LexTypes.RReturn); ScriptVarLink res = null; if (currentLexer.TokenType != (ScriptLex.LexTypes) ';') { res = Base(ref execute); } if (execute) { var resultVar = scopes.Back().FindChild(ScriptVar.ReturnVarName); if (resultVar != null) { resultVar.ReplaceWith(res); } else { //return statement outside of function??? System.Diagnostics.Trace.TraceWarning("Return statement outside of a function, what is going on?"); } execute = false; } currentLexer.Match((ScriptLex.LexTypes) ';'); } else if (currentLexer.TokenType == ScriptLex.LexTypes.RFunction) { //function var funcVar = ParseFunctionDefinition(); if (execute) { if (funcVar.Name == string.Empty) { //functions must have a name at statement level } else { var v = scopes.Back(); v.AddChildNoDup(funcVar.Name, funcVar.Var); } } } else if (currentLexer.TokenType == ScriptLex.LexTypes.RTry) { var tryBlock = ParseDefinition(ScriptLex.LexTypes.RTry); ScriptVarLink catchBlock = null, finallyBlock = null; var originalLexer = currentLexer; if (currentLexer.TokenType == ScriptLex.LexTypes.RCatch) { catchBlock = ParseDefinition(ScriptLex.LexTypes.RCatch); } if (currentLexer.TokenType == ScriptLex.LexTypes.RFinally) { finallyBlock = ParseDefinition(ScriptLex.LexTypes.RFinally); } try { var oldLex = currentLexer; var newLex = new ScriptLex(tryBlock.Var.String); currentLexer = newLex; Block(ref execute); execute = true; currentLexer = oldLex; } catch (JITException ex) { if (catchBlock != null) { var catchScope = new ScriptVar(null, ScriptVar.Flags.Object); var v = catchBlock?.Var?.FirstChild; if (v != null) { catchScope.AddChild(v.Name, ex.VarObj); } var oldLex = currentLexer; var newLex = new ScriptLex(catchBlock.Var.String); currentLexer = newLex; scopes.PushBack(catchScope); Block(ref execute); scopes.PopBack(); execute = true; currentLexer = oldLex; } else { throw new ScriptException(ex.Message, ex); } } finally { if (finallyBlock != null) { var oldLex = currentLexer; var newLex = new ScriptLex(finallyBlock.Var.String); currentLexer = newLex; Block(ref execute); execute = true; currentLexer = oldLex; } } currentLexer = originalLexer; } else if (currentLexer.TokenType == ScriptLex.LexTypes.RThrow) { currentLexer.Match(ScriptLex.LexTypes.RThrow); ScriptVar message = new ScriptVar(); if (currentLexer.TokenType == (ScriptLex.LexTypes) ';') { currentLexer.Match((ScriptLex.LexTypes) ';'); } else { var res = Base(ref execute); message = res.Var; } throw new JITException(message); } else { //execute a basic statement Base(ref execute); currentLexer.Match((ScriptLex.LexTypes) ';'); } }