/// <summary> /// Parses parameters. /// </summary> /// <param name="args">The list of arguments to store.</param> /// <param name="tokenIt">The token iterator</param> /// <param name="parser">The parser</param> /// <param name="meta">The function meta for checking parameters</param> /// <param name="expectParenthesis">Whether or not to expect parenthis to designate the start of the parameters.</param> /// <param name="enableNewLineAsEnd">Whether or not to treat a newline as end</param> public static void ParseFuncParameters(List <Expr> args, TokenIterator tokenIt, Parser parser, bool expectParenthesis, bool enableNewLineAsEnd, FunctionMetaData meta) { int totalParameters = 0; if (tokenIt.NextToken.Token == Tokens.LeftParenthesis) { expectParenthesis = true; } // START with check for "(" if (expectParenthesis) { tokenIt.Expect(Tokens.LeftParenthesis); } bool passNewLine = !enableNewLineAsEnd; var endTokens = BuildEndTokens(enableNewLineAsEnd, meta); int totalNamedParams = 0; var hasMetaArguments = meta != null && meta.ArgumentNames != null && meta.ArgumentNames.Count > 0; while (true) { Expr exp = null; // Check for end of statment or invalid end of script. if (parser.IsEndOfParameterList(Tokens.RightParenthesis, enableNewLineAsEnd)) { break; } if (tokenIt.NextToken.Token == Tokens.Comma) { tokenIt.Advance(); } var token = tokenIt.NextToken.Token; var peek = tokenIt.Peek().Token; var isVar = parser.Context.Symbols.Contains(token.Text); var isParamNameMatch = hasMetaArguments && meta.ArgumentsLookup.ContainsKey(token.Text); var isKeywordParamName = token.Kind == TokenKind.Keyword && isParamNameMatch; // CASE 1: Named params for external c# object method calls // CASE 2: Named params for internal script functions ( where we have access to its param metadata ) if ((meta == null && token.Kind == TokenKind.Ident && peek == Tokens.Colon) || (token.Kind == TokenKind.Ident && isParamNameMatch && !isVar) || (isKeywordParamName && !isVar)) { string paramName = token.Text; tokenIt.Advance(); // Advance and check if ":" if (tokenIt.NextToken.Token == Tokens.Colon) { tokenIt.Advance(); } exp = parser.ParseExpression(endTokens, true, false, true, passNewLine, true); // Store named param exp = new NamedParamExpr(paramName, exp); args.Add(exp); totalNamedParams++; } // CASE 2: Name of variable being passed to function is same as one of the parameter names. else if (isVar && hasMetaArguments && meta.ArgumentsLookup.ContainsKey(token.Text)) { // Can not have normal parameters after named parameters. if (totalNamedParams > 0) { throw tokenIt.BuildSyntaxException("Un-named parameters must come before named parameters"); } exp = parser.ParseIdExpression(); args.Add(exp); } // CASE 3: Normal param else { // Can not have normal parameters after named parameters. if (totalNamedParams > 0) { throw tokenIt.BuildSyntaxException("Un-named parameters must come before named parameters"); } exp = parser.ParseExpression(endTokens, true, false, true, passNewLine, true); args.Add(exp); } totalParameters++; parser.Context.Limits.CheckParserFunctionParams(exp, totalParameters); // Check for end of statment or invalid end of script. if (parser.IsEndOfParameterList(Tokens.RightParenthesis, enableNewLineAsEnd)) { break; } // Advance if not using fluent-parameters if (meta == null) { tokenIt.Expect(Tokens.Comma); } } // END with check for ")" if (expectParenthesis) { tokenIt.Expect(Tokens.RightParenthesis); } }
/// <summary> /// Initailizes with function metadata. /// </summary> /// <param name="meta"></param> public void Init(FunctionMetaData meta) { this.Meta = meta; ParamList = new List <object>(); ParamListExpressions = new List <Expr>(); }
private static IDictionary <Token, bool> BuildEndTokens(bool enableNewLineAsEnd, FunctionMetaData meta) { var endTokens = new Dictionary <Token, bool>(); var formalEndTokens = enableNewLineAsEnd ? Terminators.ExpFluentFuncExpParenEnd : Terminators.ExpFuncExpEnd; foreach (var pair in formalEndTokens) { endTokens[pair.Key] = true; } if (meta == null) { return(endTokens); } // Go through all the arguments and use the if (meta.ArgumentsLookup != null && meta.ArgumentsLookup.Count > 0) { // Add all the parameter names and aliases to the map. foreach (var pair in meta.ArgumentsLookup) { var idToken = TokenBuilder.ToIdentifier(pair.Value.Name); endTokens[idToken] = true; if (!string.IsNullOrEmpty(pair.Value.Alias)) { idToken = TokenBuilder.ToIdentifier(pair.Value.Alias); endTokens[idToken] = true; } } } return(endTokens); }
/// <summary> /// Metadata about the function. /// </summary> /// <param name="meta"></param> public ExecExpr(FunctionMetaData meta) { this.Init(meta); }
/// <summary> /// Define a function symbol within this scope. /// </summary> /// <param name="func">The function metadata</param> /// <param name="functionExpr">The function expression object that can execute the function</param> public virtual void DefineFunction(FunctionMetaData func, object functionExpr) { _current.DefineFunction(func, functionExpr); }