Пример #1
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            // For an empty PRINT command, just output a writeline and return.
            if (tokenMarker.Token == null)
            {
                interpreter.Console.OutputTextWriter.WriteLine();
                return;
            }

            Token lastToken = null;

            while (tokenMarker.Token != null)
            {
                lastToken = tokenMarker.Token;
                switch (tokenMarker.Token)
                {
                case StringValueToken stringValueToken:
                case RealValueToken realValueToken:
                case IntegerValueToken integerValueToken:
                case UnaryMinusToken unaryMinusToken:
                case MinusToken minusToken:
                case PlusToken plusToken:
                case VariableNameToken variableToken:
                case FunctionToken functionToken:
                case FnToken userDefinedFunctionToken:
                case OpenParenToken openParenToken:
                    var result = interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
                    WriteValue(interpreter, result);
                    break;

                case SemicolonToken semiColonToken:
                    tokenMarker.MoveNext();
                    break;

                case CommaToken commaToken:
                    MoveToNextTabMargin(interpreter);
                    tokenMarker.MoveNext();
                    break;

                case TabToken tabToken:
                    tokenMarker.MoveNext();
                    tabToken.Execute(interpreter, tokenMarker);
                    break;

                case SpcToken spcToken:
                    tokenMarker.MoveNext();
                    spcToken.Execute(interpreter, tokenMarker);
                    break;

                default:
                    throw new Exceptions.SyntaxErrorException();
                }
//                lastToken = tokenMarker.Token;
//                tokenMarker.MoveNext();
            }
            if (!((lastToken is SemicolonToken) || (lastToken is CommaToken)))
            {
                interpreter.Console.OutputTextWriter.WriteLine();
            }
        }
Пример #2
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);
        }
Пример #3
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();
            }
        }
Пример #4
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            var variableNameTokens = new List <VariableNameToken>();

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

                if (!((variableNameToken.VariableType == VariableValueType.IntegerNumber) ||
                      (variableNameToken.VariableType == VariableValueType.RealNumber)))
                {
                    throw new Exceptions.TypeMismatchException();
                }

                variableNameTokens.Add(variableNameToken);

                // Maybe add more variable names to the list
                if (tokenMarker.GetNextToken() is CommaToken)
                {
                    tokenMarker.MoveNext();
                    continue;
                }
            }

            if (interpreter.ForNextLoops.Count == 0)
            {
                throw new Exceptions.NextWithoutForException();
            }

            if (variableNameTokens.Count == 0)
            {
                ProcessForNextState(interpreter, interpreter.ForNextLoops.Peek());
                return;
            }

            int variableNameIndex = 0;

            while (variableNameIndex < variableNameTokens.Count)
            {
                if (interpreter.ForNextLoops.TryPeek(out ForNextLoopState forNextState) == false)
                {
                    throw new Exceptions.NextWithoutForException();
                }

                bool forNextLoopDone = ProcessForNextState(interpreter, forNextState, variableNameTokens[variableNameIndex]);
                if (!forNextLoopDone)
                {
                    return;
                }

                variableNameIndex += 1;
            }
        }
Пример #5
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
            }
        }
Пример #6
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);
                }
            }
        }
Пример #7
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;
                }
            }
        }
Пример #8
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            if (!(tokenMarker.Token is VariableNameToken variableNameToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (variableNameToken.VariableType != VariableValueType.RealNumber)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            if (!(tokenMarker.GetNextToken() is EqualToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            tokenMarker.MoveNext();

            NumericValueToken startValue;

            try
            {
                startValue = (NumericValueToken)interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
            }
            catch (InvalidCastException)
            {
                throw new Exceptions.TypeMismatchException();
            }

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

            tokenMarker.MoveNext();

            NumericValueToken endValue;

            try
            {
                endValue = (NumericValueToken)interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
            }
            catch (InvalidCastException)
            {
                throw new Exceptions.TypeMismatchException();
            }

            NumericValueToken stepValueToken = null;

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

                tokenMarker.MoveNext();
                var result = interpreter.ExpressionEvaluator.Evaluate(tokenMarker);
                if (!(result is NumericValueToken))
                {
                    throw new Exceptions.TypeMismatchException();
                }
                stepValueToken = (NumericValueToken)result;
            }
            else
            {
                // Default step is 1 or -1
//                if (startValue.RealValue <= endValue.RealValue)
                stepValueToken = interpreter.TokensProvider.CreateRealValueToken(1);
//                else
//                    stepValueToken = interpreter.TokensProvider.CreateRealValueToken(-1);
            }

            ForNextLoopState forNextLoopState;

            if (interpreter.InterpreterMode == InterpreterMode.Running)
            {
                var forNextMarker = interpreter.CopyCurrentStatementMarker();

                // In immediate mode, FOR may not neccessarily be followed by a statement.
                if (forNextMarker.Valid)
                {
                    forNextMarker.MoveToNextStatement();
                }

                forNextLoopState = new ForNextLoopState(forNextMarker, variableNameToken, startValue, endValue, stepValueToken);
            }
            else
            {
                var index = interpreter.CurrentImmediateModeStatementMarker.StatementIndex;
                forNextLoopState = new ForNextLoopState(index, variableNameToken, startValue, endValue, stepValueToken);
            }

            interpreter.ForNextLoops.Push(forNextLoopState);
            interpreter.VariablesEnvironment.SetVariableValue(variableNameToken, startValue);
        }
Пример #9
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            var conditionToken = interpreter.ExpressionEvaluator.Evaluate(tokenMarker);

            if (!(conditionToken is NumericValueToken resultToken))
            {
                throw new Exceptions.TypeMismatchException();
            }

            // Condition evaluated to false. Skip to the next line.
            if (resultToken.IntValue == 0)
            {
                var nextLineMarker = interpreter.CopyCurrentStatementMarker();
                nextLineMarker.MoveToNextLine();
                interpreter.NextStatementMarker = nextLineMarker;
                return;
            }

            // Condition evaluated to true. Continue on...
            if (!((tokenMarker.Token is ThenToken) || tokenMarker.Token is GotoToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            tokenMarker.MoveNext();

            if (tokenMarker.Token is NumericValueToken gotoLineValueToken)
            {
                var gotoLineMarker = interpreter.CreateStatementMarker();
                gotoLineMarker.MoveToLine(gotoLineValueToken.IntValue);
                interpreter.NextStatementMarker = gotoLineMarker;
                return;
            }

            var  commandToken      = tokenMarker.Token as CommandToken;
            var  variableNameToken = tokenMarker.Token as VariableNameToken;
            bool performMoveNext   = true;

            if (commandToken == null && variableNameToken != null)
            {
                commandToken    = (CommandToken)interpreter.TokensProvider.GetBuiltinToken("LET");
                performMoveNext = false;
            }

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

            // GOTO <linenumber> is fine, GOTO <command> is not!
            if (commandToken is GotoToken)
            {
                throw new Exceptions.SyntaxErrorException();
            }

            // Execute the command following the THEN
            if (performMoveNext)
            {
                tokenMarker.MoveNext();
            }

            commandToken.Execute(interpreter, tokenMarker);
        }
Пример #10
0
        public override void Execute(Interpreter interpreter, TokenMarker tokenMarker)
        {
            var indexToken = interpreter.ExpressionEvaluator.Evaluate(tokenMarker);

            if (!(indexToken is NumericValueToken indexValueToken))
            {
                throw new Exceptions.TypeMismatchException();
            }

            var commandToken = tokenMarker.Token;

            if (!(commandToken is GosubToken || commandToken is GotoToken))
            {
                throw new Exceptions.SyntaxErrorException();
            }

            tokenMarker.MoveNext();

            var index = indexValueToken.IntValue;

            if (index < 0 || index > 255)
            {
                throw new Exceptions.IllegalQuantityException();
            }

            if (index == 0)
            {
                return;
            }

            index -= 1;
            while (index > 0 && tokenMarker.Token != null)
            {
                var token = tokenMarker.Token;
                if (!(token is NumericValueToken))
                {
                    throw new Exceptions.SyntaxErrorException();
                }

                tokenMarker.MoveNext();

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

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

                tokenMarker.MoveNext();
                index -= 1;
            }

            // Index was out of range. Continue on to the next statement.
            if (tokenMarker.Token == null)
            {
                return;
            }

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

            var lineNumber = lineNumberToken.IntValue;

            if (commandToken is GosubToken)
            {
                // Setup the return stack.
                var currentMarker = interpreter.CopyCurrentStatementMarker();
                currentMarker.MoveToNextStatement();
                interpreter.GosubMarkers.Push(currentMarker);
            }

            var gotoMarker = interpreter.CreateStatementMarker();

            if (gotoMarker.MoveToLine(lineNumber) == false)
            {
                throw new Exceptions.UndefinedStatementException();
            }

            interpreter.NextStatementMarker = gotoMarker;
        }