/// <summary> /// Initialize /// </summary> public ExecPlugin() { this.Init("exec"); _funcMeta = new FunctionMetaData("exec", null); _funcMeta.AddArg("program", "string", true, "", string.Empty, @"c:\tools\nunit\nunit.exe", "program to launch"); _funcMeta.AddArg("workingdir", "string", false, "in", string.Empty, @"c:\tools\nunit\", "working directory to launch in"); _funcMeta.AddArg("args", "list", false, "", string.Empty, "", "arguments to the program"); _funcMeta.AddArg("failOnError","bool", false, "", false, "", "arguments to the program"); }
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> /// 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 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) || (token.Kind == TokenKind.Ident && !isParamNameMatch && !isVar && peek == Tokens.Colon) || (isKeywordParamName && !isVar ) ) { var paramName = token.Text; var namedParamToken = tokenIt.NextToken; tokenIt.Advance(); // Advance and check if ":" if (tokenIt.NextToken.Token == Tokens.Colon) tokenIt.Advance(); exp = parser.ParseExpression(endTokens, true, false, true, passNewLine, true); exp = Exprs.NamedParam(paramName, exp, namedParamToken); 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"); var next = tokenIt.Peek(); if (next.Token.Kind == TokenKind.Symbol) exp = parser.ParseExpression(endTokens, true, false, true, passNewLine, false); else exp = parser.ParseIdExpression(null, null, false); 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> /// Creates functionmetadata object with the supplied inputs. /// </summary> /// <param name="memberType">What type of member e.g. property,function.</param> /// <param name="name">The name of the function</param> /// <param name="implementationMethod">The method that implements the funcion in this host language.</param> /// <param name="returnType">The return values type</param> /// <param name="description">Description of the function.</param> /// <returns></returns> private FunctionMetaData AddMethodInfo(MemberTypes memberType, string name, string implementationMethod, Type returnType, string description, bool convertParams) { var funcdef = new FunctionMetaData(name, null); funcdef.Doc = new DocTags(); // Todo: funcdef.ReturnType = LangTypeHelper.ConvertToLangType(returnType); funcdef.Doc.Summary = description; var mappedMethod = new MappedMethod(); mappedMethod.DataTypeMethod = name; mappedMethod.HostLanguageMethod = implementationMethod; mappedMethod.FuncDef = funcdef; mappedMethod.ConvertParameters = convertParams; _methodMap[name] = mappedMethod; _allMembersMap[name] = memberType; return funcdef; }
/// <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>(); }
/// <summary> /// Metadata about the function. /// </summary> /// <param name="meta"></param> public ExecExpr(FunctionMetaData meta) { this.Init(meta); }
/// <summary> /// Resolve the parameters in the function call. /// </summary> /// <param name="meta">The function metadata</param> /// <param name="paramListExpressions">The list of expressions that should be evaulated first to pass as parameters</param> /// <param name="paramList">The list of parameters to a populate from paramListExpressions</param> /// <param name="visitor">The visitor that will evaulate the expressions.</param> public static void ResolveParametersForScriptFunction(FunctionMetaData meta, List<Expr> paramListExpressions, List<object> paramList, IAstVisitor visitor) { int totalParams = meta.Arguments == null ? 0 : meta.Arguments.Count; ResolveParameters(totalParams, paramListExpressions, paramList, namedParam => meta.ArgumentsLookup[namedParam.Name].Index, namedParam => meta.ArgumentsLookup.ContainsKey(namedParam.Name), visitor); }