Exemple #1
0
        protected override void IfZero()
        {
            var op = new InterpreterOperator
            {
                Operator = NumOperator.IF_NOT_ZERO,
            };

            this.controlStack.Push(op);
            AddToken(op);
        }
Exemple #2
0
        protected override void WhileNotZero()
        {
            var op = new InterpreterOperator
            {
                Operator = NumOperator.WHILE_NOT_ZERO,
            };

            // EndWhileで使用するために自分の位置を設定しておく
            op.JumpPosition = this.tokens.Count;

            this.controlStack.Push(op);
            AddToken(op);
        }
Exemple #3
0
 private void AddToken(InterpreterOperator iop)
 {
     this.tokens.Add(iop);
 }
Exemple #4
0
        protected override void Postprocess()
        {
            int length = tokens.Count;

            this.controlStack.Clear();

            for (int i = 0; i < length; i++)
            {
                InterpreterOperator op = this.tokens[i];

                switch (op.Operator)
                {
                case NumOperator.COUNT:
                    this.stack.Push((uint)this.stack.Count);
                    break;

                case NumOperator.POP:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"empty stack: {op.Operator}");
                    }
                    else
                    {
                        this.stack.Pop();
                    }
                    break;

                case NumOperator.COPY:
                    if (this.stack.TryPeek(out uint result))
                    {
                        this.stack.Push(result);
                    }
                    else
                    {
                        throw new ApplicationException($"empty stack: {op.Operator}");
                    }
                    break;

                case NumOperator.SWAP:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(top);
                        this.stack.Push(next);
                    }
                    break;

                case NumOperator.OVER:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Peek();

                        this.stack.Push(top);
                        this.stack.Push(next);
                    }
                    break;

                case NumOperator.INCREMENT:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        this.stack.Push(top + 1);
                    }
                    break;

                case NumOperator.DECREMENT:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        this.stack.Push(top - 1);
                    }
                    break;

                case NumOperator.NOT:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        this.stack.Push(~top);
                    }
                    break;

                case NumOperator.ROTATE_DOWN:
                    if (this.stack.Count < 3)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top    = this.stack.Pop();
                        uint next   = this.stack.Pop();
                        uint bottom = this.stack.Pop();

                        this.stack.Push(next);
                        this.stack.Push(top);
                        this.stack.Push(bottom);
                    }
                    break;

                case NumOperator.ROTATE_UP:
                    if (this.stack.Count < 3)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top    = this.stack.Pop();
                        uint next   = this.stack.Pop();
                        uint bottom = this.stack.Pop();

                        this.stack.Push(top);
                        this.stack.Push(bottom);
                        this.stack.Push(next);
                    }
                    break;

                case NumOperator.AND:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next & top);
                    }
                    break;

                case NumOperator.OR:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next | top);
                    }
                    break;

                case NumOperator.XOR:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next ^ top);
                    }
                    break;

                case NumOperator.SHIFT_RIGHT:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next >> (int)top);
                    }
                    break;

                case NumOperator.SHIFT_LEFT:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next << (int)top);
                    }
                    break;

                case NumOperator.ADD:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next + top);
                    }
                    break;

                case NumOperator.SUBTRACT:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next - top);
                    }
                    break;

                case NumOperator.MULTIPLY:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next * top);
                    }
                    break;

                case NumOperator.DIVIDE:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next / top);
                    }
                    break;

                case NumOperator.REMAINDER:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next % top);
                    }
                    break;

                case NumOperator.GREATER_THAN:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next > top ? 1U : 0U);
                    }
                    break;

                case NumOperator.LESS_THAN:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next < top ? 1U : 0U);
                    }
                    break;

                case NumOperator.EQUAL:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next == top ? 1U : 0U);
                    }
                    break;

                case NumOperator.NOT_EQUAL:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next != top ? 1U : 0U);
                    }
                    break;

                case NumOperator.TEST:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Peek();

                        this.stack.Push(top);
                        this.stack.Push(next == top ? 1U : 0U);
                    }
                    break;

                case NumOperator.GREATER_THAN_OR_EQUAL:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next >= top ? 1U : 0U);
                    }
                    break;

                case NumOperator.LESS_THAN_OR_EQUAL:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Pop();

                        this.stack.Push(next <= top ? 1U : 0U);
                    }
                    break;

                case NumOperator.EQUAL_ZERO:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        this.stack.Push(top == 0 ? 1U : 0U);
                    }
                    break;

                case NumOperator.NOT_EQUAL_ZERO:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        this.stack.Push(top != 0 ? 1U : 0U);
                    }
                    break;

                case NumOperator.TEST_NOT:
                    if (this.stack.Count < 2)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top  = this.stack.Pop();
                        uint next = this.stack.Peek();

                        this.stack.Push(top);
                        this.stack.Push(next != top ? 1U : 0U);
                    }
                    break;

                case NumOperator.IF_NOT_ZERO:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Peek();

                        if (top == 0)
                        {
                            i = op.JumpPosition;
                        }
                        else
                        {
                            this.controlStack.Push(op);
                        }
                    }
                    break;

                case NumOperator.IF_ZERO:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Peek();

                        if (top != 0)
                        {
                            i = op.JumpPosition;
                        }
                        else
                        {
                            this.controlStack.Push(op);
                        }
                    }
                    break;

                case NumOperator.END_IF:
                    if (this.controlStack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in control stack: {op.Operator}");
                    }
                    else
                    {
                        InterpreterOperator control = this.controlStack.Pop();

                        if (control.Operator != NumOperator.IF_NOT_ZERO && control.Operator != NumOperator.IF_ZERO)
                        {
                            throw new ApplicationException($"invalid control: {control.Operator} - {op.Operator}");
                        }
                    }
                    break;

                case NumOperator.WHILE_NOT_ZERO:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else
                    {
                        uint top = this.stack.Peek();

                        if (top == 0)
                        {
                            i = op.JumpPosition;
                        }
                        else
                        {
                            this.controlStack.Push(op);
                        }
                    }
                    break;

                case NumOperator.END_WHILE:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in stack: {op.Operator}");
                    }
                    else if (this.controlStack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in control stack: {op.Operator}");
                    }
                    else
                    {
                        InterpreterOperator control = this.controlStack.Peek();
                        if (control.Operator != NumOperator.WHILE_NOT_ZERO)
                        {
                            throw new ApplicationException($"invalid control: {control.Operator} - {op.Operator}");
                        }

                        uint top = this.stack.Peek();

                        if (top != 0)
                        {
                            i = op.JumpPosition;
                        }
                        else
                        {
                            this.controlStack.Pop();
                        }
                    }
                    break;

                case NumOperator.BREAK:
                    if (this.controlStack.Count < 1)
                    {
                        throw new ApplicationException($"insufficient in control stack: {op.Operator}");
                    }
                    else
                    {
                        InterpreterOperator control = this.controlStack.Pop();
                        while (control.Operator != NumOperator.WHILE_NOT_ZERO)
                        {
                            if (!this.controlStack.TryPop(out control))
                            {
                                throw new ApplicationException($"insufficient in control stack: {op.Operator}");
                            }
                        }

                        i = control.JumpPosition;
                    }
                    break;

                case NumOperator.CONSTANT_8_BIT:
                case NumOperator.CONSTANT_16_BIT:
                case NumOperator.CONSTANT_32_BIT:
                    this.stack.Push(op.Value);
                    break;

                case NumOperator.INPUT_CHARACTER:
                    this.stack.Push((uint)Console.Read());
                    break;

                case NumOperator.OUTPUT_CHARACTER:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException("insufficient in stack");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        Console.Write(char.ConvertFromUtf32((int)top));
                    }
                    break;

                case NumOperator.STORE_VARIABLE:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException("insufficient in stack");
                    }
                    else
                    {
                        this.variables[op.Value] = this.stack.Pop();
                    }
                    break;

                case NumOperator.COPY_VAIRABLE:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException("insufficient in stack");
                    }
                    else
                    {
                        this.variables[op.Value] = this.stack.Peek();
                    }
                    break;

                case NumOperator.LOAD_VARIABLE:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException("insufficient in stack");
                    }
                    else
                    {
                        this.stack.Push(this.variables[op.Value]);
                    }
                    break;

                case NumOperator.INPUT_INTEGER:
                    string str = Console.ReadLine();
                    if (uint.TryParse(str, out uint value))
                    {
                        this.stack.Push(value);
                    }
                    else
                    {
                        throw new ApplicationException($"invalid value: \"{str}\"");
                    }
                    break;

                case NumOperator.OUTPUT_INTEGER:
                    if (this.stack.Count < 1)
                    {
                        throw new ApplicationException("insufficient in stack");
                    }
                    else
                    {
                        uint top = this.stack.Pop();

                        Console.Write(top);
                    }
                    break;

                default:
                    break;
                }
            }
        }