/// <summary> /// Ejecuta una instrucción for /// </summary> private void Execute(InstructionFor instruction) { Variable variableIndex = ExpressionComputer.Search(instruction.IndexVariable, out string error); if (!error.IsEmpty()) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener la variable índice: {error}"); } else { ValueBase valueStart = ExpressionComputer.Evaluate(instruction.StartValueRPN); if (valueStart.HasError) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener el valor de inicio del bucle for {valueStart.Error}"); } else if (!(valueStart is ValueNumeric)) { Compiler.LocalErrors.Add(instruction.Token, "El valor de inicio del bucle for no es un valor numérico"); } else { ValueBase valueEnd = ExpressionComputer.Evaluate(instruction.EndValueRPN); if (valueEnd.HasError) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener el valor de fin del bucle for {valueEnd.Error}"); } else if (!(valueEnd is ValueNumeric)) { Compiler.LocalErrors.Add(instruction.Token, "El valor de fin del bucle for no es un valor numérico"); } else { ValueBase valueStep; // Obtiene el valor del paso if (instruction.StepValueRPN == null || instruction.StepValueRPN.Count == 0) { valueStep = ValueBase.GetInstance("1"); } else { valueStep = ExpressionComputer.Evaluate(instruction.StepValueRPN); } // Comprueba los errores antes de entrar en el bucle if (valueStep.HasError) { Compiler.LocalErrors.Add(instruction.Token, $"Error al obtener el valor de paso del bucle for {valueEnd.Error}"); } else if (!(valueEnd is ValueNumeric)) { Compiler.LocalErrors.Add(instruction.Token, "El valor de paso del bucle for no es un valor numérico"); } else { int indexLoop = 0; int start = (int)(valueStart as ValueNumeric).Value; int end = (int)(valueEnd as ValueNumeric).Value; int intStep = (int)(valueStep as ValueNumeric).Value; int index = start; // Cambia el valor de la variable de índice variableIndex.Value = ValueBase.GetInstance(index.ToString()); // Ejecuta las instrucciones del bucle while (index <= end && indexLoop < Compiler.MaximumRepetitionsLoop) { // Ejecuta las instrucciones del bucle Execute(instruction.Instructions); // Incrementa la variable índice y cambia el valor de la variable index += intStep; variableIndex.Value = ValueBase.GetInstance(index.ToString()); // Incrementa el número de iteraciones indexLoop++; } // Comprueba el número de iteraciones if (indexLoop >= Compiler.MaximumRepetitionsLoop) { Compiler.LocalErrors.Add(instruction.Token, "Se ha sobrepasado el número máximo de iteraciones del bucle for"); } } } } } }
/// <summary> /// Lee una sentencia for /// </summary> private InstructionBase ReadCommandFor(Token token) { InstructionFor instruction = new InstructionFor(token); Token nextToken = GetToken(true); // Lee la variable if (nextToken.Type == Token.TokenType.Variable) { // Asigna la variable instruction.IndexVariable = ReadVariableIdentifier(GetToken(), out string error); // Comprueba si hay algún error antes de continuar if (!string.IsNullOrWhiteSpace(error)) { instruction.Error = error; } else { // Signo igual nextToken = GetToken(true); if (nextToken.Type != Token.TokenType.Equal) { instruction.Error = "Falta el signo igual en el bucle for"; } else { // Quita el igual GetToken(); // Lee el valor inicial instruction.StartValue = ReadExpression(ExpressionReaderMode.Normal, out error); instruction.StartValueRPN = _expressionEvaluator.ConvertToRPN(instruction.StartValue); if (!string.IsNullOrEmpty(error)) { instruction.Error = error; } else { // Sentencia to nextToken = GetToken(true); if (nextToken.Type != Token.TokenType.Sentence || !nextToken.Content.Equals("to", StringComparison.CurrentCultureIgnoreCase)) { instruction.Error = "Falta la sentencia to en el bucle for"; } else { // Quita el to nextToken = GetToken(); // Lee el valor final instruction.EndValue = ReadExpression(ExpressionReaderMode.Normal, out error); instruction.EndValueRPN = _expressionEvaluator.ConvertToRPN(instruction.EndValue); if (!string.IsNullOrEmpty(error)) { instruction.Error = error; } else { // Sentencia step nextToken = GetToken(true); // Obtiene el valor del incremento (si es necesario) if (nextToken.Type == Token.TokenType.Sentence && nextToken.Content.Equals("step", StringComparison.CurrentCultureIgnoreCase)) { // Quita el step GetToken(); // Lee el valor del step instruction.StepValue = ReadExpression(ExpressionReaderMode.Normal, out error); instruction.StepValueRPN = _expressionEvaluator.ConvertToRPN(instruction.StepValue); // Comprueba el error y lee las instrucciones if (!string.IsNullOrEmpty(error)) { instruction.Error = error; } } // Lee las instrucciones del for if (!instruction.IsError) { token = ReadInstructions(instruction.Instructions); } } } } } } } else { instruction.Error = "Debe existir una variable después del for"; } // Devuelve la instrucción return(instruction); }