示例#1
0
        public Expr Parse(TokenStream stream)
        {
            // Parse the left side of the expression.
            Expr leftSide = new PrimaryExprParser().Parse(stream);

            // Ensure left side was successfully parsed, otherwise return null.
            if (leftSide == null)
            {
                return(null);
            }

            // Invoke the binary expression parser.
            Expr expr = new BinaryOpRightSideParser(leftSide, 0).Parse(stream);

            // Return the parsed expression.
            return(expr);
        }
示例#2
0
        public Expr Parse(ParserContext context)
        {
            // Parse the left side of the expression.
            Expr leftSide = new PrimaryExprParser().Parse(context);

            // Ensure left side was successfully parsed, otherwise throw an error.
            if (leftSide == null)
            {
                throw new Exception("Unexpected expression left-side to be null");
            }

            // Invoke the binary expression parser, for potential following expression(s).
            Expr expr = new BinaryOpRightSideParser(leftSide, 0).Parse(context);

            // Return the parsed expression.
            return(expr);
        }
示例#3
0
        public Expr Parse(ParserContext context)
        {
            // If this is a binary operation, find it's precedence.
            while (true)
            {
                // Capture the current token.
                Token token = context.Stream.Current;

                // Calculate precedence for the current token.
                int firstPrecedence = Precedence.Get(token);

                /*
                 * If this is a binary operation that binds at least as tightly
                 * as the current binary operation, consume it. Otherwise, the process
                 * is complete.
                 */
                if (firstPrecedence < this.minimalPrecedence)
                {
                    // TODO: This should throw error? Research.
                    return(this.leftSide);
                }

                // At this point, it's a binary operation.
                TokenType binaryOperator = token.Type;

                // TODO: Should check if it's a BINARY operator, not just an operator.
                // Ensure the captured operator is validated.
                if (!TokenIdentifier.IsOperator(binaryOperator))
                {
                    throw context.NoticeRepository.CreateException($"Expected token to be a binary operator but got token type '{binaryOperator}'");
                }

                // Skip operator.
                context.Stream.Skip();

                // Parse the right-side.
                Expr rightSide = new PrimaryExprParser().Parse(context);

                // Ensure that the right-side was successfully parsed.
                if (rightSide == null)
                {
                    throw new Exception("Unable to parse the right-side of the binary expression");
                }

                // Determine the token precedence of the current token.
                int secondPrecedence = Precedence.Get(token);

                /*
                 * If binary operator binds less tightly with the right-side than
                 * the operator after right-side, let the pending operator take the
                 * right-side as its left-side.
                 */
                if (firstPrecedence < secondPrecedence)
                {
                    // Invoke the right-side parser.
                    rightSide = new BinaryOpRightSideParser(rightSide, firstPrecedence + 1).Parse(context);

                    // Ensure the right-side was successfully parsed.
                    if (rightSide == null)
                    {
                        throw new Exception("Unable to parse the right-side of the binary expression");
                    }
                }

                // Create the binary expression entity.
                BinaryExpr binaryExpr = new BinaryExpr(binaryOperator, this.leftSide, rightSide, firstPrecedence);

                // TODO: Name is temporary?
                // Set the name of the binary expression's output.
                binaryExpr.SetName("tmp");

                // Merge left-side/right-side.
                this.leftSide = binaryExpr;
            }
        }
        public Expr Parse(TokenStream stream)
        {
            // If this is a binary operation, find it's precedence.
            while (true)
            {
                var firstPrecedence = Precedence.Get(stream.Get());

                /*
                 * If this is a binary operation that binds at least as tightly
                 * as the current binary operation, consume it. Otherwise, the process
                 * is complete.
                 */
                if (firstPrecedence < minimalPrecedence)
                {
                    return(leftSide);
                }

                // At this point, it's a binary operation.
                TokenType binaryOperator = stream.Get().Type;

                // TODO: Should check if it's a BINARY operator, not just an operator.
                // Ensure the captured operator is validated.
                if (!TokenIdentifier.IsOperator(binaryOperator))
                {
                    throw new Exception(
                              $"Expected token to be a binary operator but got token type '{binaryOperator}'");
                }

                // Skip operator.
                stream.Skip();

                // Parse the right-side.
                Expr rightSide = new PrimaryExprParser().Parse(stream);

                // Ensure that the right-side was successfully parsed.
                if (rightSide == null)
                {
                    throw new Exception("Unable to parse the right-side of the binary expression");
                }

                // Determine the token precedence of the current token.
                var secondPrecedence = Precedence.Get(stream.Get());

                /*
                 * If binary operator binds less tightly with the right-side than
                 * the operator after right-side, let the pending operator take the
                 * right-side as its left-side.
                 */
                if (firstPrecedence < secondPrecedence)
                {
                    // Invoke the right-side parser.
                    rightSide = new BinaryOpRightSideParser(rightSide, firstPrecedence + 1).Parse(stream);

                    // Ensure the right-side was successfully parsed.
                    if (rightSide == null)
                    {
                        throw new Exception("Unable to parse the right-side of the binary expression");
                    }
                }

                // Create the binary expression entity.
                var binaryExpr = new BinaryExpr(leftSide, rightSide, firstPrecedence);

                // Merge left-side/right-side.
                leftSide = binaryExpr;
            }
        }
示例#5
0
        public Block Parse(TokenStream stream)
        {
            // Consume next token. Either '{' or '=>' for anonymous functions.
            Token begin = stream.Next();

            // Create the block.
            var block = new Block();

            // Set the block as active in the symbol table.
            SymbolTable.activeBlock = block;

            // Mark the block as default.
            if (begin.Type == TokenType.SymbolBlockL)
            {
                block.Type = BlockType.Default;
            }
            // Mark the block as short.
            else if (begin.Type == TokenType.SymbolArrow)
            {
                block.Type = BlockType.Short;
            }
            // Otherwise, the block type could not be identified.
            else
            {
                throw new Exception("Unexpected block type");
            }

            // Look at the next token.
            Token nextToken = stream.Peek();

            // While next token is not a block-closing token.
            while (nextToken.Type != TokenType.SymbolBlockR && block.Type != BlockType.Short)
            {
                // Returning a value.
                if (nextToken.Type == TokenType.KeywordReturn)
                {
                    // Invoke the return parser. It's okay if it returns null, as it will be emitted as void.
                    Expr returnExpr = new FunctionReturnParser().Parse(stream);

                    // Assign the return expression to the block.
                    block.ReturnExpr = returnExpr;

                    // Exit the loop and return
                    break;
                }

                // Token must be an expression.
                Expr expr = new PrimaryExprParser().Parse(stream);

                block.Expressions.Add(expr);

                // Ensure expression was successfully parsed.
                if (expr == null)
                {
                    throw new Exception("Unexpected expression to be null");
                }

                // SKip over the semi colon.
                stream.Skip();

                // Peek the new token for next parse.
                nextToken = stream.Peek();
            }

            // Skip default block end '}' or short block end ';'.
            stream.Skip();

            return(block);
        }