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); }
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); }