public void InterpretLine(string line) { //Debug.Log("Parsing: " + line + " line number " + currentLineNumber + " Block type = " + currentType + " Block States " + BlockStates.Count + " Escape LVL " + escapeLevel); if(line.Equals("end", System.StringComparison.OrdinalIgnoreCase)) { if(currentType == BlockType.function) { functions.Add(currentFunction.name, currentFunction); Debug.Log("Added function " + currentFunction.name + " to repertoire."); currentFunction = null; PopBlockState(); } else if(currentType == BlockType.loop) { //go back to the WHILE line currentLineNumber = loopState.startLine - 1; Debug.Log("Looping to " + currentLineNumber); PopBlockState(); } else if (currentType == BlockType.skip) { /*if (--escapeLevel == 0) PopBlockState(); if (escapeLevel < 0) throw new InterpreterException("There is an end statement without an accompanying block start statement.", currentLineNumber);*/ if (escapeLevel > 0) { escapeLevel--; } else { PopBlockState(); } } else if (currentType == BlockType.conditional) { PopBlockState(); } return; } if(currentType != BlockType.none) { //still processing block if(currentType == BlockType.function) { currentFunction.AddLine(line); return; } else if (currentType == BlockType.block) { currentBlock.AddLine(line); return; } else if (currentType == BlockType.loop) { //do nothing and continue Debug.Log("Continuing loop line " + currentLineNumber); } else if (currentType == BlockType.conditional) { //do nothing and continue Debug.Log("Continuing conditional line " + currentLineNumber); } else if (currentType == BlockType.skip) { //skip do nothing string[] tokens = line.Split(' '); if (IsBlockStart(tokens[0])) escapeLevel++; return; } else { //nothing } /*string[] tokens = line.Split(' '); if (IsBlockStart(tokens[0])) escapeLevel++;*/ Debug.Log("Processed line in block [" + line + "]"); } string[] pieces = line.Split(' '); double delayTime = 0; if(pieces[0].Equals("delay", System.StringComparison.OrdinalIgnoreCase)) { //if the first word is delay //start coroutine with that delay if (numbers.ContainsKey(pieces[1])) { numbers.TryGetValue(pieces[1], out delayTime); } else { if (!double.TryParse(pieces[1], out delayTime)) throw (new InterpreterException("Cannot parse the delay time. [" + pieces[1] + "]", currentLineNumber)); } string[] npieces = new string[pieces.Length - 2]; for(int i = 0; i < pieces.Length - 2; i++) { npieces[i] = pieces[i + 2]; } pieces = npieces; } if (pieces[0].Equals("return", System.StringComparison.OrdinalIgnoreCase)) { if (delayTime > 0) throw (new InterpreterException("A return statement cannot succeed a delay statement", currentLineNumber)); returnStatement = true; if(pieces.Length > 2) throw (new InterpreterException("The return statement can only be followed by a single token", currentLineNumber)); TokenType type = GetType(pieces[1]); string value = ""; //Unknown = 0, //XBObject = 1, //SceneObject = 2, //Number = 3, //NumberValue = 4, //Text = 5, //Function = 6 //Debug.Log("Returning raw [" + pieces[1] + "]"); switch(type) { case (TokenType.XBObject): case (TokenType.SceneObject): case (TokenType.NumberValue): case (TokenType.Text): returnValue = pieces[1]; break; case (TokenType.Number): if(numbers.ContainsKey(pieces[1])) { double n = 0; numbers.TryGetValue(pieces[1], out n); returnValue = "" + n; } else { throw (new InterpreterException("Cannot return value, the number variable has not been initialized.", currentLineNumber)); } break; case (TokenType.Function): throw (new InterpreterException("Returning a function is not supported.", currentLineNumber)); break; case (TokenType.Unknown): throw (new InterpreterException("Cannot return a value of unknown type.", currentLineNumber)); break; } //Debug.Log("Returning value [" + returnValue + "]"); return; } if (pieces[0].Equals("print", System.StringComparison.OrdinalIgnoreCase)) { pieces = ReplaceToValues(pieces, 1); Debug.Log("PRINT [" + GetString(pieces) + "]"); PrintToDebugUI ("PRINT [" + GetString(pieces) + "]"); return; } if(variables.ContainsKey(pieces[0])) { XBGameObject obj; variables.TryGetValue(pieces[0], out obj); InterpreterDesc desc; objectDescs.TryGetValue(obj.datatype, out desc); printDebug(pieces[0] + " is a variable of type " + obj.datatype, currentLineNumber); InterpreterInterface script = null; if (InfixPrefix.equal(obj.datatype, "rocket")) { RocketBoosterScript rbscript = obj.gameObject.GetComponent<RocketBoosterScript>(); script = (InterpreterInterface)rbscript; } else if (InfixPrefix.equal(obj.datatype, "missile")) { MissileGeneratorScript mgscript = obj.gameObject.transform.GetChild(0).GetComponent<MissileGeneratorScript>(); script = (InterpreterInterface)mgscript; } else { throw (new InterpreterException("The block type " + pieces[0] + " does not have a programmable interface. ", currentLineNumber)); } if(Contains(desc.methods, pieces[1])) { //invoke the method //RKT START printDebug(pieces[1] + " is a method of " + obj.datatype, currentLineNumber); script.command((float)delayTime, pieces[1], null); } else if (Contains(desc.variables, pieces[1])) { //set variable //RKT FORCE 100 printDebug(pieces[1] + " is a variable of " + obj.datatype, currentLineNumber); if (numbers.ContainsKey(pieces[2])) numbers.TryGetValue(pieces[2], out delayTime); script.set((float)delayTime, pieces[1], pieces[2]); } else { throw (new InterpreterException("The block named " + pieces[0] + " of the " + obj.datatype + " type does not have a function or variable named " + pieces[1], currentLineNumber)); } } else if(objectDescs.ContainsKey(pieces[0])) { //check if it's a datatype //which means object initialization //get object of type //EG syntax: ROCKET RKT <- GETOBJECT rocketbooster if (variables.ContainsKey(pieces[1])) throw (new InterpreterException("Cannot initialize a variable that already exists", currentLineNumber)); if(objects.ContainsKey(pieces[4])) { GameObject obj; objects.TryGetValue(pieces[4], out obj); XBGameObject xbobj; xbobj.gameObject = obj; xbobj.datatype = pieces[0]; variables.Add(pieces[1], xbobj); if(pieces[0].Equals("radar", System.StringComparison.OrdinalIgnoreCase)) { sensors.Add(pieces[1]); UpdateSensorData(); } } else { //there is no gameObject in the scene with this name throw (new NoBlockWithNameFoundError("There was no block with the name " + pieces[4], currentLineNumber)); } } else if (numbers.ContainsKey(pieces[0])) { //Arithmetic evaluations on existing number if(pieces.Length < 3) { throw (new InterpreterException("There are not enough arguments for this Arithmetic operation.", currentLineNumber)); } double value = arithmetic.EvaluateArithExpression(pieces, 2); numbers[pieces[0]] = value; //throw (new InterpreterException("Evaluated number " + pieces[0] + " to " + value, currentLineNumber)); } else if (pieces[0].Equals("number", System.StringComparison.OrdinalIgnoreCase)) { //Arithmetic evaluations on Initialization of number if (pieces.Length < 4) { throw (new InterpreterException("There are not enough arguments for this Arithmetic initialization.", currentLineNumber)); } double value = arithmetic.EvaluateArithExpression(pieces, 3); numbers.Add(pieces[1], value); //throw (new InterpreterException("Evaluated number " + pieces[1] + " to " + value, currentLineNumber)); } else if (pieces[0].Equals("struct", System.StringComparison.OrdinalIgnoreCase)) { /* create a new struct * Format: STRUCT NAME KEY=VALUE KEY=VALUE KEY=VALUE... * NAME SET KEY=VALUE * NAME[KEY] */ string[] kvs = new string[pieces.Length - 2]; for (int i = 2; i < pieces.Length; i++) kvs[i - 2] = pieces[i]; CreateStructure(pieces[1], kvs); } else if (structures.ContainsKey(pieces[0])) { switch(pieces[1].ToLowerInvariant()) { case("set"): if(pieces.Length < 4) throw (new InterpreterException("There are not enough arguments for this set operation.", currentLineNumber)); XBStructure XBS; structures.TryGetValue(pieces[0], out XBS); string[] pair = pieces[2].Split('='); if (pair.Length != 2) throw new InterpreterException("Incoherent key value, must be in format (key=value) [" + pieces[2] + "]", currentLineNumber); XBS.Set(pair[0], pair[1]); break; default: break; } } else if (functions.ContainsKey(pieces[0])) { CallFunction(pieces); } else if (IsBlockStart(pieces[0])) { if (pieces[0].Equals("function", System.StringComparison.OrdinalIgnoreCase)) { if(currentType == BlockType.function) { throw (new InterpreterException("You cannot define a function within a function.", currentLineNumber)); } //function definition blockInstruction = line; //create the block for this //XBFunction(string name, string[] args, int lineNumber) List<string> args = new List<string>(); if(pieces.Length > 2) { if(pieces.Length % 2 != 0) { throw (new InterpreterException("The function declaration has improper arguments.", currentLineNumber)); } for(int i = 2; i < pieces.Length; i = i + 2) { args.Add(pieces[i] + " " + pieces[i+1]); } } if(functions.ContainsKey(pieces[1])) { throw (new InterpreterException("The function " + pieces[1] + " has already been declared.", currentLineNumber)); return; } currentFunction = new XBFunction(this, pieces[1], args.ToArray(), currentLineNumber); PushBlockState(BlockType.function); } else if (pieces[0].Equals("if", System.StringComparison.OrdinalIgnoreCase)) { pieces = ReplaceNumberValue(pieces, 0); Debug.Log (String.Join(",", pieces)); pieces = ReplaceStructValue(pieces, 0); Debug.Log (String.Join(",", pieces)); pieces = ReplacePrimitiveFunctionValue(pieces, 0); Debug.Log (String.Join(",", pieces)); //conditional string if(pieces.Length < 4 && !functions.ContainsKey(pieces[1])) { throw (new InterpreterException("[Basic Check] Invalid conditional statement.", currentLineNumber)); } //get the results of each function called in the conditional statement bool eval = logic.EvaluateLogic(pieces, 1); if (!eval) PushBlockState(BlockType.skip); else PushBlockState(BlockType.conditional); } else { //WHILE LOOP //check if already inside a loop if so push the current LoopState into stack if(currentType == BlockType.loop) { loopStates.Push(loopState); } loopState.startLine = currentLineNumber; //check the conditional bool eval = logic.EvaluateLogic(pieces, 1); if (!eval) { PushBlockState(BlockType.skip); Debug.Log("Setting type to SKIP"); } else { PushBlockState(BlockType.loop); Debug.Log("Setting type to LOOP"); } } } /* These cases cover reserved commands such as * TARGET - Look at a target * TURN - turn to angle position */ else if (pieces[0].Equals("target", System.StringComparison.OrdinalIgnoreCase)) { Debug.Log ("Target: " + pieces[1]); pieces = ReplaceToValues(pieces, 0); Debug.Log ("Target: " + pieces[1]); GameObject target; if (pieces[1].Equals("none", System.StringComparison.OrdinalIgnoreCase)) { Root.LookAtTransform = null; } else if(objects.TryGetValue(pieces[1], out target)) { Root.LookAtTransform = target.transform; } else { throw (new InterpreterException("Target object not recognized.", currentLineNumber)); } } else if(pieces[0].Equals("turn", System.StringComparison.OrdinalIgnoreCase)) { // Root.gameObject.transform.Rotate(Vector3.Forward,) } else { //Something else throw (new InterpreterException("[" + line + "] Syntax not recognized.", currentLineNumber)); } }
public void PopInterpreterState() { XBInterpreterState xbis = StateStack.Pop(); currentLineNumber = xbis.currentLineNumber; blockInstruction = xbis.blockInstruction; currentBlock = xbis.currentBlock; currentFunction = xbis.currentFunction; currentType = xbis.currentType; numbers = xbis.numbers; variables = xbis.variables; }