/// <summary> /// ExprTail := nil | '+' Term ExprTail | '-' Term ExprTail /// </summary> void ParseExprTail(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Plus) { current = tokens.NextToken(); ParseTerm(tokens); // Append operators postfix EmitBinaryOperator("+", current.Position); ParseExprTail(tokens); } else if (current.TokenType == TokenType.Minus) { current = tokens.NextToken(); ParseTerm(tokens); // Append operators postfix EmitBinaryOperator("-", current.Position); ParseExprTail(tokens); } else { // nil - but this is ok. } }
/// Function := Name '(' ArgList ')' void ParseFunction(TokenQueue tokens) { var funcStartPosition = tokens.PeekToken().Position; RegisteredFunction function = ParseFunctionName(tokens); Token current = tokens.PeekToken(); if (current.TokenType != TokenType.OpenParenthesis) { throw new ParserExceptionWithPosistion(string.Format("Expected open bracket at {0}.", current.Position), current.Position); } tokens.NextToken(); int args = 0; ParseArgList(tokens, ref args); current = tokens.PeekToken(); if (args != function.ArgCount) { throw new ParserExceptionWithPosistion(string.Format("Invalid number of function parameters in function {0}. Expected {1} at {2}.", function.Name, function.ArgCount, current.Position), current.Position); } if (current.TokenType != TokenType.CloseParenthesis) { throw new ParserExceptionWithPosistion(string.Format("Expected close bracket at {0}.", current.Position), current.Position); } // Append function names after all their arguments. EmitFunction(function, funcStartPosition); tokens.NextToken(); }
/// <summary> /// FactorTail := Number | '(' Expr ')' | Function /// </summary> void ParseFactorTail(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.OpenParenthesis) { current = tokens.NextToken(); ParseExpressionR(tokens); // Skip the closing bracket if (tokens.PeekToken().TokenType != TokenType.CloseParenthesis) { throw new ParserExceptionWithPosistion(string.Format("Expected close bracket at {0}.", current.Position), current.Position); } tokens.NextToken(); } else if (current.TokenType == TokenType.Text && IsRegisteredFunction(current.Value)) { ParseFunction(tokens); } else if (current.TokenType == TokenType.Numeric) { ParseNumber(tokens); } else { throw new ParserExceptionWithPosistion(string.Format("Unrecognised factor at {0}.", current.Position), current.Position); } }
/// <summary> /// TermTail := nil | '*' Factor | '/' Factor /// </summary> void ParseTermTail(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Divide) { current = tokens.NextToken(); ParseFactor(tokens); // Append operators postfix EmitBinaryOperator("/", current.Position); ParseTermTail(tokens); } else if (current.TokenType == TokenType.Multiply) { current = tokens.NextToken(); ParseFactor(tokens); // Append operators postfix EmitBinaryOperator("*", current.Position); ParseTermTail(tokens); } else { // nil - but this is ok } }
/// Name := (One of a recognised/registered list of function Names) RegisteredFunction ParseFunctionName(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Text && IsRegisteredFunction(current.Value)) { tokens.NextToken(); return(_functions[current.Value.ToUpperInvariant()]); } else { throw new ParserExceptionWithPosistion(string.Format("Expected known function at {0}.", current.Position), current.Position); } }
/// ArgListTail : = nil | ',' NonEmptyArgList void ParseArgListTail(TokenQueue tokens, ref int argc) { Token current = tokens.PeekToken(); // Otherwise it's the end of the arg list if (current.TokenType != TokenType.CloseParenthesis) { if (current.TokenType == TokenType.Separator) { tokens.NextToken(); ParseNonEmptyArgList(tokens, ref argc); } else { throw new ParserExceptionWithPosistion(string.Format("Expected comma at {0}.", current.Position), current.Position); } } }
/// <summary> /// </summary> void ParseNumber(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Numeric) { // Append numbers as encountered. Double result = (Double.Parse(current.Value, NumberFormatInfo.InvariantInfo)); EmitNumeric(result, current.Position); current = tokens.NextToken(); } else { throw new ParserExceptionWithPosistion(string.Format("Expected number at {0}.", current.Position), current.Position); } }
/// <summary> /// Factor := UnaryPrefixOp FactorTail | FactorTail /// </summary> void ParseFactor(TokenQueue tokens) { Token current = tokens.PeekToken(); if (current.TokenType == TokenType.Minus) { current = tokens.NextToken(); ParseFactorTail(tokens); // We negate by multiplying by -1. EmitNumeric(-1d, current.Position); EmitBinaryOperator("*", current.Position); } else { ParseFactorTail(tokens); } }