/// 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); } }
private Ast.Stmt ParseExecuteStmt(TokenQueue q) { var stmt = new Ast.ExecuteStmt { SourceToken = q.SourceToken }; q.Take("exec", "execute"); if (q.Peek(1) == "=") { stmt.ReturnVariableName = ParseVariableName(q); q.Take("="); } if (q.PeekToken().Type == TokenType.String || q.PeekToken().Type == TokenType.Id) { stmt.ScriptName = q.Take().GetUnescapedText(); } else { throw new SyntaxException(new[] { "string", "identifier" }, q); } if (IsVariableName(q.PeekToken()?.GetUnescapedText() ?? "") && q.Peek(1) == "=") { while (true) { var arg = new Ast.ArgumentPair(); arg.Name = ParseVariableName(q); q.Take("="); if (q.Peek() == "default") { q.Take(); } else { arg.Value = ParseExpr(q); } stmt.Arguments.Add(arg); if (!q.TakeMaybe(",")) { break; } } } ConsumeSemicolon(q); return(stmt); }
/// <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. } }
/// <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 } }
/// <summary> /// Parse the supplied expression. /// If the expression is not valid, then a ParserException will be thrown. /// Finally we test to see that all tokens have been parsed. /// If not, this is likely to be an error in the expression, for example something like /// 4535+54345+5345345POWER(2, 3) /// </summary> public void ParseExpression(TokenQueue tokens) { ParseExpressionR(tokens); if (tokens.PeekToken().TokenType != TokenType.EOF) { throw new ParserException(string.Format("Tokens remain after parsing: {0}.", tokens.ToString())); } return; }
/// ArgList :=nil | NonEmptyArgList void ParseArgList(TokenQueue tokens, ref int argc) { Token current = tokens.PeekToken(); // If it is a close parenthesis then its the end of the arglist. if (current.TokenType != TokenType.CloseParenthesis) { ParseNonEmptyArgList(tokens, ref argc); } }
/// 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); } }