예제 #1
0
        /// <summary>
        /// Create CodeNode representing hierarchy sequence.
        /// </summary>
        /// <returns>CodeNode created according to layout.</returns>
        public CodeNode HierarchyLayout()
        {
            var node = new CodeNode(_lexer.Move(), NodeTypes.hierarchy);

            if (_checkToken("("))//function call
            {
                node.NodeType = NodeTypes.call;
                resolveBracket(() => { node.AddArgument(_nextTree()); return(false); }, "(", ",", ")", "Error in call, expected '{0}'"); //on fail throw exception
                node.EndingToken = _lexer.Current.Previous;                                                                              //aby ukazoval na zavorku
            }

            if (_shiftToken("."))
            {
                var child = HierarchyLayout();
                if (child == null)
                {
                    throw CSharpSyntax.ParsingException(_lexer.Current, "Expected identifier after '.'");
                }
                node.Child = child;
            }

            if (_checkToken("["))
            {
                var indexer = IndexerLayout();
                node.SetIndexer(indexer);
            }

            if (_checkToken("{")) //initializer
            {
                var seq = InitializerLayout();
                node.SetSubsequence(seq);
            }

            return(node);
        }
예제 #2
0
        /// <summary>
        /// repair newNode if prefix/postfix operator, according to expect prefix/postfix context.
        /// </summary>
        /// <param name="newNode">The new node.</param>
        /// <param name="operands">The operands.</param>
        /// <param name="expectPrefix">if set to <c>true</c> prefix operator is expected.</param>
        /// <param name="expectPostfix">if set to <c>true</c> postfix operator is expected.</param>
        private void operatorContext(CodeNode newNode, Stack <CodeNode> operands, bool expectPrefix, bool expectPostfix)
        {
            bool      shouldRepair = false;
            NodeTypes nodeType     = newNode.NodeType;

            CodeNode argument = null;

            if (expectPrefix && _language.IsPrefixOperator(newNode.Value))
            {
                shouldRepair = true;
                nodeType     = NodeTypes.prefixOperator;
                argument     = _getTree();
            }
            else if (expectPostfix && _language.IsPostfixOperator(newNode.Value))
            {
                shouldRepair = true;
                nodeType     = NodeTypes.postOperator;

                //postfix operator has argument already on the stack
                argument = operands.Pop();
            }

            if (!shouldRepair)
            {
                //nothing to repair
                return;
            }

            newNode.NodeType = nodeType;

            newNode.AddArgument(argument);
            newNode.IsTreeEnding |= argument.IsTreeEnding;
        }
예제 #3
0
        /// <summary>
        /// Create CodeNode representing conditional block.
        /// </summary>
        /// <returns>CodeNode created according to layout.</returns>
        public CodeNode CondBlockLayout()
        {
            var condNode = new CodeNode(_lexer.Move(), NodeTypes.block);

            condition(condNode);

            //on { nextTree gives sequence, else return command

            condNode.AddArgument(_nextTree());
            if (_shiftToken("else"))
            {
                condNode.AddArgument(_nextTree());
            }

            return(condNode);
        }
예제 #4
0
        /// <summary>
        /// Create CodeNode representing for block.
        /// </summary>
        /// <returns>CodeNode created according to layout.</returns>
        public CodeNode ForeachLayout()
        {
            var node = new CodeNode(_lexer.Move(), NodeTypes.block);

            _shiftToken("(", "Error in Foreach layout, expected '('");
            var declaration = _nextTree();

            node.AddArgument(declaration);
            _shiftToken("in", "Expected 'in'");
            var expression = _nextTree();

            node.AddArgument(expression);
            _shiftToken(")", "Error in For layout, expected ')'");

            node.Child       = _nextTree();
            node.EndingToken = _lexer.Current;
            return(node);
        }
예제 #5
0
        /// <summary>
        /// Create <see cref="CodeNode"/> representing do{}while() block
        /// </summary>
        /// <returns><see cref="CodeNode"/> created according to layout</returns>
        public CodeNode DoLayout()
        {
            var commandNode = new CodeNode(_lexer.Move(), NodeTypes.block);

            //on { nextTree gives sequence, else return command
            commandNode.AddArgument(_nextTree());

            _shiftToken("while", "Missing {0} after do");
            condition(commandNode);
            commandNode.EndingToken = _lexer.Current.Next;

            return(commandNode);
        }
예제 #6
0
        /// <summary>
        /// Create CodeNode representing expression prefixed with opening bracket.
        /// </summary>
        /// <returns>CodeNode created according to layout.</returns>
        public CodeNode BracketLayout()
        {
            var node = new CodeNode(_lexer.Move(), NodeTypes.bracket);

            node.AddArgument(_nextTree());
            _shiftToken(")", "Expected closing {0}");

            if (_shiftToken("."))
            {
                //call on expression
                node.Child = HierarchyLayout();
            }

            return(node);
        }
예제 #7
0
        /// <summary>
        /// Create CodeNode representing switch block.
        /// </summary>
        /// <returns>CodeNode created according to layout.</returns>
        public CodeNode SwitchLayout()
        {
            var switchNode = new CodeNode(_lexer.Move(), NodeTypes.block);

            condition(switchNode);
            _shiftToken("{", "expected '{' in switch layout");

            var inSwitch = true;

            while (inSwitch)
            {
                var label = _current();
                switch (label)
                {
                case "case":
                case "default":
                    var labelBlock = new CodeNode(_lexer.Move(), NodeTypes.block);
                    if (labelBlock.Value == "case")
                    {
                        labelBlock.AddArgument(_nextTree());
                    }
                    _shiftToken(":", "expected '{0}' after '{1}', in switch statement", label);

                    var lines = new List <CodeNode>();

                    while (_current() != "case" && _current() != "default" && _current() != "}")
                    {
                        lines.Add(_nextTree());
                        _shiftToken(";");
                    }

                    labelBlock.SetSubsequence(lines, _lexer.Current);
                    switchNode.AddArgument(labelBlock);
                    break;

                case "}":
                    inSwitch = false;
                    break;

                default:
                    throw CSharpSyntax.ParsingException(_lexer.Current, "unrecognized label '{0}' in switch statement", label);
                }
            }

            _shiftToken("}", "expected '{0}' in switch layout");
            return(switchNode);
        }
예제 #8
0
        /// <summary>
        /// Satisfy given operator node. Satisfied operator is added into operands stack.
        /// </summary>
        /// <param name="operatorNode">Operator to satisfy.</param>
        /// <param name="operands">Operands used for satisfying.</param>
        private void satisfyOperator(CodeNode operatorNode, Stack <CodeNode> operands)
        {
            var arity = _language.Arity(operatorNode);

            if (operands.Count < arity)
            {
                throw CSharpSyntax.ParsingException(operatorNode, "There aren't enough operands for the operator {0}", operatorNode.Value);
            }

            var reverseStack = new Stack <CodeNode>();

            for (int i = 0; i < arity; i++)
            {
                reverseStack.Push(operands.Pop());
            }
            for (int i = 0; i < arity; i++)
            {
                operatorNode.AddArgument(reverseStack.Pop());
            }

            operands.Push(operatorNode);
        }
예제 #9
0
        /// <summary>
        /// Create CodeNode representing for block.
        /// </summary>
        /// <returns>CodeNode created according to layout.</returns>
        public CodeNode ForLayout()
        {
            var node = new CodeNode(_lexer.Move(), NodeTypes.block);

            _shiftToken("(", "Error in For layout, expected '('");

            for (int i = 0; i < 3; i++)
            {
                node.AddArgument(_nextTree());
                if (i < 2)
                {
                    _shiftToken(";", "Error in For layout, expected ';'");
                }
            }

            _shiftToken(")", "Error in For layout, expected ')'");

            node.Child       = _nextTree();
            node.EndingToken = _lexer.Current;

            return(node);
        }
예제 #10
0
 /// <summary>
 /// Add condition argument to given node.
 /// </summary>
 /// <param name="condNode">Node to add condition argument.</param>
 private void condition(CodeNode condNode)
 {
     _shiftToken("(", "expected '{0}' in {1} clause", condNode.Value);
     condNode.AddArgument(_nextTree());
     _shiftToken(")", "expected '{0}' in {1} clause", condNode.Value);
 }