Beispiel #1
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            var             variableNameToken = tokenMarker.Token as VariableNameToken;
            ValueTokenArray indicies          = null;

            if (variableNameToken == null)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (tokenMarker.PeekNext() is OpenParenToken)
            {
                indicies = interpreter.ExpressionEvaluator.EvaluateVariableArrayAssignment(tokenMarker);
            }
            else
            {
                tokenMarker.MoveNext();
            }

            var equalsToken = tokenMarker.Token;

            if (!(equalsToken is Operators.EqualToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (tokenMarker.GetNextToken() == null)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            var result = interpreter.ExpressionEvaluator.Evaluate(tokenMarker);

            interpreter.VariablesEnvironment.SetVariableValue(variableNameToken, indicies, result);
        }
Beispiel #2
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            while (tokenMarker.Token != null)
            {
                if (!(tokenMarker.Token is VariableNameToken variableNameToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                if (!(tokenMarker.PeekNext() is OpenParenToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                var indicies = interpreter.ExpressionEvaluator.EvaluateVariableArrayAssignment(tokenMarker);
                interpreter.VariablesEnvironment.DimensionArrayVariable(variableNameToken, indicies);

                if (!(tokenMarker.Token is CommaToken))
                {
                    break;
                }

                tokenMarker.MoveNext();
            }
        }
Beispiel #3
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            if (tokenMarker.Token == null)
            {
                interpreter.Run();
                return;
            }

            if (!(tokenMarker.Token is NumericValueToken numericValueToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (tokenMarker.PeekNext() != null)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            interpreter.Run(numericValueToken.IntValue);
        }
Beispiel #4
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            while (tokenMarker.Token != null)
            {
                ValueTokenArray indicies = null;

                if (!(tokenMarker.Token is VariableNameToken variableNameToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                if (tokenMarker.PeekNext() is OpenParenToken)
                {
                    indicies = interpreter.ExpressionEvaluator.EvaluateVariableArrayAssignment(tokenMarker);
                }
                else
                {
                    tokenMarker.MoveNext();
                }

                var valueToken = interpreter.ReadNextDataValue();
                if (valueToken == null)
                {
                    throw new Exceptions.OutOfDataException();
                }

                switch (variableNameToken.VariableType)
                {
                case VariableValueType.String:
                    break;

                case VariableValueType.RealNumber:
                    float realValue = 0;
                    var   success   = float.TryParse(((StringValueToken)valueToken).Value, out realValue);
                    if (success == false)
                    {
                        throw new Exceptions.TypeMismatchException();
                    }
                    valueToken = interpreter.TokensProvider.CreateRealValueToken(realValue);
                    break;

                case VariableValueType.IntegerNumber:
                    success = float.TryParse(((StringValueToken)valueToken).Value, out realValue);
                    if (success == false)
                    {
                        throw new Exceptions.TypeMismatchException();
                    }
                    // In Commodore BASIC, a READ of a number with a decimal into an integer number produces a zero.
                    int intValue = (int)Math.Abs(realValue);
                    if (realValue != intValue)
                    {
                        intValue = 0;
                    }

                    if (intValue < Int16.MinValue || intValue > Int16.MaxValue)
                    {
                        throw new Exceptions.OverflowException();
                    }

                    valueToken = interpreter.TokensProvider.CreateIntegerValueToken((Int16)intValue);
                    break;
                }

                interpreter.VariablesEnvironment.SetVariableValue(variableNameToken, indicies, valueToken);

                if (tokenMarker.Token == null)
                {
                    break;
                }

                if (!(tokenMarker.Token is CommaToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                tokenMarker.MoveNext();
                // The next token should now be a variable name token
            }
        }
Beispiel #5
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            if (interpreter.InterpreterMode == InterpreterMode.Immmediate)
            {
                throw new Exceptions.IllegalDirectModeException();
            }

            var variableNameTokens = new List <(VariableNameToken, ValueTokenArray)>();

            while (tokenMarker.Token != null)
            {
                ValueTokenArray indicies = null;
                if (!(tokenMarker.Token is VariableNameToken variableNameToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                if (tokenMarker.PeekNext() is OpenParenToken)
                {
                    indicies = interpreter.ExpressionEvaluator.EvaluateVariableArrayAssignment(tokenMarker);
                }
                else
                {
                    tokenMarker.MoveNext();
                }

                if (tokenMarker.Token != null && !(tokenMarker.Token is CommaToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                variableNameTokens.Add((variableNameToken, indicies));
            }

            foreach (var(nameToken, indicies) in variableNameTokens)
            {
                var input = interpreter.Console.ReadChar();
                switch (nameToken.VariableType)
                {
                case VariableValueType.String:
                    string inputString = (input != null) ? input.ToString() : string.Empty;
                    interpreter.VariablesEnvironment.SetVariableValue(nameToken, indicies,
                                                                      interpreter.TokensProvider.CreateStringValueToken(inputString));
                    break;

                case VariableValueType.RealNumber:
                    float realValue;
                    if (input == null)
                    {
                        realValue = 0;
                    }
                    else
                    {
                        if (input >= '0' && input <= '9')
                        {
                            realValue = (float)(input - '0');
                        }
                        else
                        {
                            throw new Exceptions.SyntaxErrorException();
                        }
                    }
                    interpreter.VariablesEnvironment.SetVariableValue(nameToken, indicies,
                                                                      interpreter.TokensProvider.CreateRealValueToken(realValue));

                    break;

                case VariableValueType.IntegerNumber:
                    Int16 intValue;
                    if (input == null)
                    {
                        intValue = 0;
                    }
                    else
                    {
                        if (input >= '0' && input <= '9')
                        {
                            intValue = (Int16)(input - '0');
                        }
                        else
                        {
                            throw new Exceptions.SyntaxErrorException();
                        }
                    }
                    interpreter.VariablesEnvironment.SetVariableValue(nameToken, indicies,
                                                                      interpreter.TokensProvider.CreateIntegerValueToken(intValue));

                    break;
                }

                if (input == null)
                {
                    Thread.Sleep(100);
                }
            }
        }
Beispiel #6
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            var firstToken = tokenMarker.Token;

            if (firstToken == null)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            // Is there an input prompt?
            if (firstToken is StringValueToken stringValueToken)
            {
                interpreter.Console.OutputTextWriter.Write(stringValueToken.Value);
                interpreter.Console.OutputTextWriter.Write("? ");

                tokenMarker.MoveNext();

                // Ensure a semicolon follows the input prompt.
                if ((tokenMarker.Token == null) || !(tokenMarker.Token is SemicolonToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                tokenMarker.MoveNext();
            }
            else
            {
                interpreter.Console.OutputTextWriter.Write("? ");
            }

            // Now make a list of the variable names the input will be parsed into.
            var variableNameTokens = new List <(VariableNameToken, ValueTokenArray)>();

            while (tokenMarker.Token != null)
            {
                if (!(tokenMarker.Token is VariableNameToken variableNameToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }
                ValueTokenArray indicies = null;
                // For an array variable, get the array indicies.
                if (tokenMarker.PeekNext() is OpenParenToken)
                {
                    indicies = interpreter.ExpressionEvaluator.EvaluateVariableArrayAssignment(tokenMarker);
                }
                else
                {
                    tokenMarker.MoveNext();
                }

                variableNameTokens.Add((variableNameToken, indicies));

                if (tokenMarker.Token == null)
                {
                    break;
                }

                // Make sure a comma is the next token
                if (!(tokenMarker.Token is CommaToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                tokenMarker.MoveNext();
            }

            if (variableNameTokens.Count == 0)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            // Add default value for inputs
            var tokenResults = new List <ValueToken>();

            foreach (var(variableNameToken, indicies) in variableNameTokens)
            {
                switch (variableNameToken.VariableType)
                {
                case VariableValueType.String:
                    tokenResults.Add(interpreter.TokensProvider.CreateStringValueToken(string.Empty));
                    break;

                case VariableValueType.RealNumber:
                    tokenResults.Add(interpreter.TokensProvider.CreateRealValueToken(0));
                    break;

                case VariableValueType.IntegerNumber:
                    tokenResults.Add(interpreter.TokensProvider.CreateIntegerValueToken(0));
                    break;
                }
            }

            int tokenResultsIndex = 0;

            // Get input. Support the quirks of Microsoft's 6502 BASIC I could discover.
            bool getMoreInput = true;

            while (getMoreInput)
            {
                string inputLine = interpreter.Console.ReadLine()?.ToUpper();
                if (inputLine == null)
                {
                    // Probably received a Ctrl-C.
                    interpreter.BreakDetected();
                    return;
                }

                /* A quirk of Microsoft BASIC's INPUT implementation is that pressing return without entering anything
                 * uses the default or what has been previously input. */
                if (inputLine.Length == 0)
                {
                    getMoreInput = false;
                    break;
                }

                int  index        = 0;
                bool parseSuccess = true;

                while (index < inputLine.Length && parseSuccess && tokenResultsIndex < tokenResults.Count)
                {
                    parseSuccess = ParseNextInput(inputLine, index, out index, out string parsedInput, out ParseFailureReason parseFailureReason);
                    // Still assign the input to a variable even if the parse failed. Another Microsoft BASIC quirk.
                    bool assignmentSuccess = AssignInputToVariable(interpreter,
                                                                   variableNameTokens[tokenResultsIndex].Item1,
                                                                   variableNameTokens[tokenResultsIndex].Item2,
                                                                   parsedInput);

                    if (!parseSuccess)
                    {
                        switch (parseFailureReason)
                        {
                        // Because characters followed a closing quote but shouldn't, write out a redo from start message and start over.
                        case ParseFailureReason.CharactersAfterQuote:
                            // Set to -1 since one will be added below to bring the index back to zero
                            tokenResultsIndex = -1;
                            interpreter.Console.OutputTextWriter.WriteLine($"{ErrorMessages.errorStart} {ErrorMessages.redoFromStart}");
                            break;

                        // No error output for a colon, except when it involves the last result.
                        case ParseFailureReason.Colon:
                            if (tokenResultsIndex + 1 == tokenResults.Count)
                            {
                                interpreter.Console.OutputTextWriter.WriteLine($"{ErrorMessages.errorStart} {ErrorMessages.extraIgnored}");
                            }
                            break;
                        }
                    }
                    tokenResultsIndex += 1;
                }

                if (tokenResultsIndex < tokenResults.Count)
                {
                    // Still need more input and no more input is on this line. Ask for more.
                    if (index >= inputLine.Length)
                    {
                        interpreter.Console.OutputTextWriter.Write("?? ");
                        continue;
                    }
                }
                else
                {
                    // For too much input, write out an extra ignored message.
                    if (index < inputLine.Length)
                    {
                        interpreter.Console.OutputTextWriter.WriteLine($"{ErrorMessages.errorStart} {ErrorMessages.extraIgnored}");
                    }
                    getMoreInput = false;
                }
            }
        }