예제 #1
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);
        }
예제 #2
0
        public Block Parse(ParserContext context)
        {
            // Capture current token. Either block start or arrow for anonymous functions.
            Token begin = context.Stream.Current;

            // Skip begin token.
            context.Stream.Skip();

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

            // Set the block as active in the symbol table.
            context.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");
            }

            // Begin the iteration.
            context.Stream.NextUntil(TokenType.SymbolBlockR, (Token token) =>
            {
                // Returning a value.
                if (token.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(context);

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

                    // Return immediatly, signal to update the token buffer to the current token.
                    return(true);
                }

                // Token must be a statement.
                Expr statement = new StatementParser().Parse(context);

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

                // Append the parsed statement to the block's expression list.
                block.Expressions.Add(statement);

                // Ensure current token is a semi-colon, if previous statement did not parse a block.
                if (statement.ExprType != ExprType.If)
                {
                    // Ensure semi-colon token.
                    context.Stream.EnsureCurrent(SyntaxAnalysis.TokenType.SymbolSemiColon);

                    // Skip over the semi-colon.
                    context.Stream.Skip();
                }

                // Signal to update the token buffer with the current token.
                return(true);
            });

            // Skip onto default block end or short block end.
            context.Stream.Skip();

            // Return the resulting block.
            return(block);
        }