Пример #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>
        /// Parse given C# source into <see cref="CodeNode"/> representation.
        /// </summary>
        /// <param name="source">The source that will be parsed.</param>
        /// <returns>Parsed abstract syntax tree.</returns>
        public CodeNode Parse(Source source)
        {
            var lexer = new Lexer(source);

            _language = new CSharpSyntax(lexer, _getTree);

            return(_getTree());
        }
Пример #3
0
        /// <summary>
        /// Test if current lexer token value is equal to expectedString.
        /// </summary>
        /// <param name="expectedString">Value which is used to test lexer current value.</param>
        /// <param name="errorMessage">If is not null and test doesn't succeed, is used for
        /// throwing parsing exception. If null, no exception is thrown</param>
        /// <param name="msgArgs">Format arguments for errorMessage.</param>
        /// <returns>True if expectedString is equal to lexers current value.</returns>
        private bool _checkToken(string expectedString, string errorMessage = null, params object[] msgArgs)
        {
            if (_lexer.Current.Value != expectedString)
            {
                if (errorMessage != null)
                {
                    var args = new List <object>();
                    args.Add(expectedString);
                    args.AddRange(msgArgs);

                    throw CSharpSyntax.ParsingException(_lexer.Current, errorMessage, args.ToArray());
                }
                return(false);
            }
            return(true);
        }
Пример #4
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);
        }
Пример #5
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);
        }
Пример #6
0
        /// <summary>
        /// Build node tree from operands and operators while resolving its priorities.
        /// </summary>
        /// <returns>Built tree.</returns>
        /// <exception cref="System.NotSupportedException">newNode cannot be null</exception>
        private CodeNode _getTree()
        {
            var operands  = new Stack <CodeNode>();
            var operators = new Stack <CodeNode>();

            CodeNode newNode = null;

            //determine context to next node
            bool _expectPrefix  = true;
            bool _expectPostfix = false;

            //until tree end token is reached
            while (newNode == null || !newNode.IsTreeEnding)
            {
                if (_language.End)
                {
                    throw CSharpSyntax.ParsingException(newNode, "Expected syntax tree ending");
                }

                //infix to tree, according to priorities
                newNode = _language.Next(true);
                if (newNode == null)
                {
                    throw new NotSupportedException("newNode cannot be null");
                }

                //resolve prefix/postfix operators they go on stack as operands
                operatorContext(newNode, operands, _expectPrefix, _expectPostfix);



                //add operand on the stack - behind operand we expect postfix/binary operator
                if (newNode.NodeType != NodeTypes.binaryOperator)
                {
                    _expectPostfix = true;
                    _expectPrefix  = false;
                    operands.Push(newNode);
                    if (newNode.NodeType == NodeTypes.block)
                    {
                        break;
                    }

                    continue;
                }

                //we are adding new operator
                //satisfy all operators with lesser arity
                while (operators.Count > 0 && isLesser(newNode, operators.Peek()))
                {
                    satisfyOperator(operators.Pop(), operands);
                }

                //add operator on the stack
                operators.Push(newNode);

                //after operator we expect operand/prefix operator
                _expectPrefix  = true;
                _expectPostfix = false;
            }

            //satisfy all pending operators
            while (operators.Count > 0)
            {
                satisfyOperator(operators.Pop(), operands);
            }

            //check stack state
            if (operands.Count > 1)
            {
                throw CSharpSyntax.ParsingException(operands.Peek(), "Missing operator for operand {0}", operands.Peek());
            }
            if (operators.Count > 0)
            {
                throw CSharpSyntax.ParsingException(operators.Peek(), "Missing operand for operator {0}", operators.Peek());
            }

            var result = operands.Pop();

            result.IsTreeEnding = true;
            return(result);
        }