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