Пример #1
0
        private void ParsePenCommand(ParseTreeNode node)
        {
            var commandNode = node.ChildNodes[0];

            switch (commandNode.Term.Name)
            {
            case "PEN_UP":
                this.OnPenUp(EventArgs.Empty);
                break;

            case "PEN_DOWN":
                this.OnPenDown(EventArgs.Empty);
                break;

            case "SET_PEN_COLOR":
                switch (commandNode.ChildNodes[1].Term.Name)
                {
                case "TUPLE":
                    var rgb = new List <float>();
                    ParseTupleValues(commandNode.ChildNodes[1], rgb);
                    if (rgb.Count != 3)
                    {
                        throw new ParsingException("Incorrect command invocation.", new[]
                        {
                            ParsingError.FromParseTreeNode(node, $"The number of arguments must be 3, instead of {rgb.Count}.")
                        });
                    }

                    if (rgb.Any(v => v < 0 || v > 255))
                    {
                        throw new ParsingException("Command parameters are out of range.", new[]
                        {
                            ParsingError.FromParseTreeNode(node, "The parameter value should be greater than or equal to 0 and less than or equal to 255.")
                        });
                    }

                    this.OnSetPenColor(new PenColorEventArgs(Convert.ToInt32(rgb[0]), Convert.ToInt32(rgb[1]), Convert.ToInt32(rgb[2])));
                    break;

                case "EXPRESSION":
                    var evaluation = this.EvaluateArithmeticExpression(commandNode.ChildNodes[1]);
                    var colorIndex = Convert.ToInt32(evaluation.Value) % 16;
                    var colorValue = colorTable[colorIndex];
                    this.OnSetPenColor(new PenColorEventArgs(colorValue.Item1, colorValue.Item2, colorValue.Item3));
                    break;
                }

                break;
            }
        }
Пример #2
0
        private Evaluation EvaluateArithmeticExpression(ParseTreeNode expression)
        {
            switch (expression.Term.Name)
            {
            case "EXPRESSION":
                if (expression.ChildNodes.Count == 1)
                {
                    return(EvaluateArithmeticExpression(expression.ChildNodes[0]));
                }
                else if (expression.ChildNodes.Count == 3 &&
                         expression.ChildNodes[0].Token.Text == "(" &&
                         expression.ChildNodes[2].Token.Text == ")")
                {
                    return(EvaluateArithmeticExpression(expression.ChildNodes[1]));
                }
                else
                {
                    throw new RuntimeException($"Invalid expression at: {expression.Span.Location}");
                }

            case "VARIABLE_REF":
                var variableName = expression.ChildNodes[1].Token.Text;
                if (!CurrentProcedureScope.Exists(variableName))
                {
                    throw new ParsingException("Variable has not been defined.", new[] { ParsingError.FromParseTreeNode(expression, $"The requested parameter '{variableName}' is not defined.") });
                }

                return(new ConstantEvaluation(Convert.ToSingle(CurrentProcedureScope[variableName])));

            case "BINARY_EXPRESSION":
                var leftNode        = expression.ChildNodes[0];
                var operatorNode    = expression.ChildNodes[1];
                var rightNode       = expression.ChildNodes[2];
                var leftEvaluation  = EvaluateArithmeticExpression(leftNode);
                var rightEvaluation = EvaluateArithmeticExpression(rightNode);
                var binaryOperation = BinaryOperation.Add;
                switch (operatorNode.Term.Name)
                {
                case "+":
                    binaryOperation = BinaryOperation.Add;
                    break;

                case "-":
                    binaryOperation = BinaryOperation.Sub;
                    break;

                case "*":
                    binaryOperation = BinaryOperation.Mul;
                    break;

                case "/":
                    binaryOperation = BinaryOperation.Div;
                    break;
                }
                return(new BinaryEvaluation(leftEvaluation, rightEvaluation, binaryOperation));

            case "REP_COUNT":
                if (CurrentRepeatScope != null)
                {
                    return(new ConstantEvaluation(CurrentRepeatScope.RepCount));
                }
                throw new ParsingException("Variable repCount doesn't have a valid value.", new[] { ParsingError.FromParseTreeNode(expression, "Reference to repCount variable is not in a valid REPEAT scope.") });

            case "FUNCTION_CALL":
                var val = ExecuteProcedureCall(expression);
                return(new ConstantEvaluation(Convert.ToSingle(val)));

            default:
                return(new ConstantEvaluation(Convert.ToSingle(expression.Token.Text)));
            }
        }