/// <summary> /// Constructs AST node from operator (root) and one or two operands. /// In order for the node to be successfully created stacks must contain /// an operator and, depending on the operator, one or two operands. /// </summary> /// <example> /// The newly created subtree (operator and root and operands are children) /// is then pushed into the operands stack. Example: in a*b+c before '+' /// can be processed, a*b is turned into an subtree and pushed as an operand /// to the operands stack. Then new subtree can be created with + at the root /// and 'c' and 'a*b' as its child nodes. /// </example> /// <param name="context">Parsing context</param> /// <returns>Parsing error of any</returns> private ParseErrorType MakeNode(ParseContext context) { IOperator operatorNode = _operators.Pop(); IRValueNode rightOperand = this.SafeGetOperand(); if (rightOperand == null) { // Oddly, no operands return(ParseErrorType.RightOperandExpected); } if (operatorNode.IsUnary) { operatorNode.AppendChild(rightOperand); operatorNode.RightOperand = rightOperand; } else { IRValueNode leftOperand = this.SafeGetOperand(); if (leftOperand == null) { // Operand is missing in expression like x <- []. // Operator on top of the stack is <- since [] was not // successfully parsed. So we need to mark right operand // as error token. context.AddError(new ParseError(ParseErrorType.LeftOperandExpected, ErrorLocation.Token, GetIndexerOrFunctionErrorRange(context, operatorNode))); return(ParseErrorType.LeftOperandExpected); } if (leftOperand.End <= operatorNode.Start && rightOperand.Start >= operatorNode.End) { operatorNode.LeftOperand = leftOperand; operatorNode.RightOperand = rightOperand; operatorNode.AppendChild(leftOperand); operatorNode.AppendChild(rightOperand); } else { return(ParseErrorType.UnexpectedToken); } } _operands.Push(operatorNode); return(ParseErrorType.None); }
private ParseErrorType HandleFunctionOrIndexer(IOperator operatorNode) { // Indexing or function call is performed on the topmost operand which // generally should be a variable or a node that evaluates to it. // However, we leave syntax check to separate code. IRValueNode operand = this.SafeGetOperand(); if (operand == null) { // Oddly, no operand return(ParseErrorType.IndentifierExpected); } operatorNode.LeftOperand = operand; operatorNode.AppendChild(operand); _operands.Push(operatorNode); return(ParseErrorType.None); }
private ParseErrorType HandleFunctionOrIndexer(IOperator operatorNode) { // Indexing or function call is performed on the topmost operand which // generally should be a variable or a node that evaluates to it. // However, we leave syntax check to separate code. IRValueNode operand = this.SafeGetOperand(); if (operand == null) { // Oddly, no operand return ParseErrorType.IndentifierExpected; } operatorNode.LeftOperand = operand; operatorNode.AppendChild(operand); _operands.Push(operatorNode); return ParseErrorType.None; }