private void ParseFunctionArguments(ScriptVar funcVar) { _currentLexer.Match((ScriptLex.LexTypes) '('); while (_currentLexer.TokenType != (ScriptLex.LexTypes) ')') { funcVar.AddChildNoDup(_currentLexer.TokenString, null); _currentLexer.Match(ScriptLex.LexTypes.Id); if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')') { _currentLexer.Match((ScriptLex.LexTypes) ','); } } _currentLexer.Match((ScriptLex.LexTypes) ')'); }
public void AddMethod(String funcName, String[] args, ScriptCallbackCB callback, Object userdata) { ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native); funcVar.SetCallback(callback, userdata); //do we have any arguments to create? if (args != null) { foreach (string arg in args) { funcVar.AddChildNoDup(arg, null); } } Root.AddChild(funcName, funcVar); }
public void AddMethod(String[] ns, String funcName, String[] args, ScriptCallbackCB callback, Object userdata) { String fName = funcName; ScriptVar baseVar = Root; if (ns != null) { int x = 0; for (; x < ns.Length; x++) { ScriptVarLink link = baseVar.FindChild(ns[x]); if (link == null) { link = baseVar.AddChild(ns[x], new ScriptVar(null, ScriptVar.Flags.Object)); } baseVar = link.Var; } } ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native); funcVar.SetCallback(callback, userdata); //do we have any arguments to create? if (args != null) { foreach (string arg in args) { funcVar.AddChildNoDup(arg, null); } } baseVar.AddChild(fName, 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); } }
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); }