public static void PrintTree(Command cmd, string space) { Console.WriteLine(space + cmd.Type); foreach (var arg in cmd.Args) { if (arg is Literal) { Literal literal = (Literal)arg; Console.WriteLine(space + " " + literal.Value + " [" + literal.Type + "]"); } else { Command child = (Command)arg; PrintTree(child, space + " "); } } }
object ExecuteFunction(Command cmd, object instance, bool useDefaultVar) { object result = null; string origName = ((Literal)cmd.Args[0]).Value; string assemblyName = null; string className = null; string methodName = null; string[] splitName = origName.ToLowerInvariant().Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries); if (splitName.Length == 1) { methodName = splitName[0]; } else if (splitName.Length == 2) { className = splitName[0]; methodName = splitName[1]; } else if (splitName.Length == 3) { assemblyName = splitName[0]; className = splitName[1]; methodName = splitName[2]; } else { throw new Exception("Invalid function name: " + origName + "()"); } if (methodName == LoadPluginName) { string path; if (useDefaultVar) { path = (string)defaultVar; } else { path = (string)ExecuteExpr(cmd.Args[1]); } PluginManager.LoadPlugin(path); } else if (methodName == ImportName) { string path; if (useDefaultVar) { path = (string)defaultVar; } else { path = (string)ExecuteExpr(cmd.Args[1]); } ScriptParser parser = new ScriptParser(path); string prevCWD = Environment.CurrentDirectory; Environment.CurrentDirectory = parser.CWD; ExecuteExpr(parser.CommandRoot); Environment.CurrentDirectory = prevCWD; } else { List<FunctionBase> plugins; if (!PluginManager.Functions.TryGetValue(methodName, out plugins) || (plugins.Count <= 0)) { throw new Exception("Couldn't find plugin for " + origName + "()"); } if (assemblyName != null) { for (int i = 0; i < plugins.Count; ) { string pluginAssemblyName = Path.GetFileNameWithoutExtension(plugins[i].Type.Assembly.CodeBase).ToLowerInvariant(); if (assemblyName == pluginAssemblyName) { i++; } else { plugins.RemoveAt(i); } } } if (className != null) { for (int i = 0; i < plugins.Count; ) { string pluginClassName = plugins[i].Type.Name.ToLowerInvariant(); if (className == pluginClassName) { i++; } else { plugins.RemoveAt(i); } } } if (plugins.Count <= 0) { throw new Exception("Couldn't find plugin for " + origName + "()"); } ScriptArg[] scriptArgs; int argIdx = 0; if (useDefaultVar) { scriptArgs = new ScriptArg[cmd.Args.Count]; ScriptArg scriptArg = new ScriptArg(); scriptArg.Value = defaultVar; scriptArgs[argIdx] = scriptArg; argIdx++; } else { scriptArgs = new ScriptArg[cmd.Args.Count - 1]; } for (int cmdIdx = 1; cmdIdx < cmd.Args.Count; cmdIdx++) { ScriptArg scriptArg = new ScriptArg(); Expr cmdArg = cmd.Args[cmdIdx]; if (cmdArg.Type == ExprType.Assign) { Command assign = (Command)cmdArg; scriptArg.Name = ((Literal)assign.Args[0]).Value; cmdArg = assign.Args[1]; } if (cmdArg.Type == ExprType.Name) { scriptArg.Variable = ((Literal)cmdArg).Value; } scriptArg.Value = ExecuteExpr(cmdArg); scriptArgs[argIdx] = scriptArg; argIdx++; } bool instanceExactMatch = false; int minConversions = Int32.MaxValue; FunctionArg[] pluginArgs = null; FunctionBase plugin = null; for (int i = 0; i < plugins.Count; i++) { int numConversions; FunctionArg[] matchArgs = plugins[i].Match(scriptArgs, useDefaultVar, out numConversions); if ((matchArgs != null) && (numConversions < minConversions)) { if (instance == null) { pluginArgs = matchArgs; plugin = plugins[i]; minConversions = numConversions; } else { Type instanceType = instance.GetType(); if (plugins[i].Type.Equals(instanceType)) { pluginArgs = matchArgs; plugin = plugins[i]; minConversions = numConversions; instanceExactMatch = true; } else if (!instanceExactMatch && plugins[i].Type.IsAssignableFrom(instanceType)) { pluginArgs = matchArgs; plugin = plugins[i]; minConversions = numConversions; } } } } if (pluginArgs == null) { throw new Exception("Couldn't match args for " + origName + "()"); } List<FunctionArg> changedVars; result = plugin.RunPlugin(instance, pluginArgs, out changedVars); for (int i = 0; i < changedVars.Count; i++) { FunctionArg pluginArg = changedVars[i]; if (pluginArg.DefaultVar) { defaultVar = pluginArg.Value; } else { Variables[pluginArg.Variable] = pluginArg.Value; } } } return result; }
Expr GetNegative(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Minus)) { Token token = tokens[tokenIdx]; tokenIdx++; Command cmd = new Command(ExprType.Negative); result = cmd; Expr expr = GetNegVar(tokens, ref tokenIdx); if (expr == null) { throw new Exception("Expected a numeric expression" + token.Error()); } cmd.Args.Add(expr); } return result; }
void Parse(StreamReaderCursor reader, string scriptName) { var tokenList = Scanner(reader, scriptName); this.CommandRoot = new Command(ExprType.Root); foreach (var tokens in tokenList) { int tokenIdx = 0; while (tokenIdx < tokens.Count) { Expr expr = ParseStmt(tokens, ref tokenIdx); if (expr != null) { this.CommandRoot.Args.Add(expr); } } } }
Expr GetFunction(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Name) && ((tokenIdx + 1) < tokens.Count) && (tokens[tokenIdx + 1].Type == TokenType.LP)) { Token token = tokens[tokenIdx]; tokenIdx += 2; Command cmd = new Command(ExprType.Function); result = cmd; cmd.Args.Add(new Literal(ExprType.Name, token.Value)); GetExprList(cmd, token, TokenType.RP, ')', tokens, ref tokenIdx); if ((token.Value.ToLowerInvariant() == ScriptExecutor.LoadPluginName) && (cmd.Args.Count != 2)) { throw new Exception("Invalid path for LoadPlugin()" + token.Error()); } else if ((token.Value.ToLowerInvariant() == ScriptExecutor.ImportName) && (cmd.Args.Count != 2)) { throw new Exception("Invalid path for Import()" + token.Error()); } result = GetIndexed(result, tokens, ref tokenIdx); result = GetChain(result, tokens, ref tokenIdx); } return result; }
Expr GetIndexed(Expr result, List<Token> tokens, ref int tokenIdx) { if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.HexOrIndex || tokens[tokenIdx].Type == TokenType.Name)) { Command cmd = new Command(ExprType.Indexed); cmd.Args.Add(result); cmd.Args.Add(new Literal(tokens[tokenIdx].Type == TokenType.HexOrIndex ? ExprType.Number : ExprType.Name, tokens[tokenIdx].Value)); tokenIdx++; result = cmd; } return result; }
Expr GetDotPropertyChain(Expr result, List<Token> tokens, ref int tokenIdx) { Expr chain = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Dot) && ((tokenIdx + 1) < tokens.Count) && (tokens[tokenIdx + 1].Type == TokenType.Name)) { Token property = tokens[tokenIdx + 1]; tokenIdx += 2; Command cmd = new Command(ExprType.DotPropertyChain); cmd.Args.Add(result); cmd.Args.Add(new Literal(ExprType.Name, property.Value)); chain = cmd; chain = GetIndexed(chain, tokens, ref tokenIdx); chain = GetChain(chain, tokens, ref tokenIdx); } return chain; }
void GetExprList(Command cmd, Token startToken, TokenType endToken, char endTokenChar, List<Token> tokens, ref int tokenIdx) { Token token = startToken; while ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type != endToken)) { token = tokens[tokenIdx]; Expr expr; if ((expr = GetAssign(tokens, ref tokenIdx)) != null) { } else if ((expr = GetExpr(tokens, ref tokenIdx)) != null) { } else { throw new Exception("Expected an expression" + token.Error()); } cmd.Args.Add(expr); if (tokenIdx < tokens.Count) { token = tokens[tokenIdx]; if (token.Type != endToken) { if (token.Type == TokenType.Comma) { tokenIdx++; } else { throw new Exception("Expected a comma" + token.Error()); } } } } if ((tokenIdx >= tokens.Count) || ((token = tokens[tokenIdx]).Type != endToken)) { throw new Exception("Missing '" + endTokenChar + "'" + token.Error()); } tokenIdx++; }
Expr GetDotInstanceDefaultChain(Expr result, List<Token> tokens, ref int tokenIdx) { Expr chain = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Dot) && ((tokenIdx + 1) < tokens.Count) && (tokens[tokenIdx + 1].Type == TokenType.Dot)) { Token token = tokens[tokenIdx]; tokenIdx += 2; Command cmd = new Command(ExprType.DotInstanceDefaultChain); chain = cmd; cmd.Args.Add(result); Expr expr = GetFunction(tokens, ref tokenIdx); if (expr == null) { throw new Exception("Expected a function" + token.Error(2)); } cmd.Args.Add(expr); } return chain; }
Expr GetDotProperty(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Name) && ((tokenIdx + 1) < tokens.Count) && (tokens[tokenIdx + 1].Type == TokenType.Dot) && ((tokenIdx + 2) < tokens.Count) && (tokens[tokenIdx + 2].Type == TokenType.Name)) { Token token = tokens[tokenIdx]; Token property = tokens[tokenIdx + 2]; tokenIdx += 3; Command cmd = new Command(ExprType.DotProperty); cmd.Args.Add(new Literal(ExprType.Name, token.Value)); cmd.Args.Add(new Literal(ExprType.Name, property.Value)); result = cmd; result = GetIndexed(result, tokens, ref tokenIdx); result = GetChain(result, tokens, ref tokenIdx); } return result; }
Expr GetDotInstanceDefault(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Name) && ((tokenIdx + 1) < tokens.Count) && (tokens[tokenIdx + 1].Type == TokenType.Dot) && ((tokenIdx + 2) < tokens.Count) && (tokens[tokenIdx + 2].Type == TokenType.Dot)) { Token token = tokens[tokenIdx]; tokenIdx += 3; Command cmd = new Command(ExprType.DotInstanceDefault); result = cmd; cmd.Args.Add(new Literal(ExprType.Name, token.Value)); Expr expr = GetFunction(tokens, ref tokenIdx); if (expr == null) { throw new Exception("Expected a function" + token.Error(2)); } cmd.Args.Add(expr); } return result; }
Expr GetDotDefault(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Dot)) { Token token = tokens[tokenIdx]; tokenIdx++; Command cmd = new Command(ExprType.DotDefault); result = cmd; Expr expr = GetFunction(tokens, ref tokenIdx); if (expr == null) { throw new Exception("Expected a function" + token.Error(1)); } cmd.Args.Add(expr); } return result; }
Expr GetAssign(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.Name) && ((tokenIdx + 1) < tokens.Count) && (tokens[tokenIdx + 1].Type == TokenType.Equals)) { Token token = tokens[tokenIdx]; tokenIdx += 2; Command cmd = new Command(ExprType.Assign); result = cmd; cmd.Args.Add(new Literal(ExprType.Name, token.Value)); Expr expr = GetExpr(tokens, ref tokenIdx); if (expr == null) { throw new Exception("Expected an expression" + token.Error()); } cmd.Args.Add(expr); } return result; }
Expr GetArray(List<Token> tokens, ref int tokenIdx) { Expr result = null; if ((tokenIdx < tokens.Count) && (tokens[tokenIdx].Type == TokenType.LCB)) { Token token = tokens[tokenIdx]; tokenIdx++; Command cmd = new Command(ExprType.Array); result = cmd; GetExprList(cmd, token, TokenType.RCB, '}', tokens, ref tokenIdx); } return result; }
Expr GetArithHelper(Expr result, ExprType exprType, List<Token> tokens, ref int tokenIdx) { Token token = tokens[tokenIdx]; tokenIdx++; Command cmd = new Command(exprType); cmd.Args.Add(result); Expr expr = GetArith(tokens, ref tokenIdx); if (expr == null) { throw new Exception("Expected a numeric expression" + token.Error()); } cmd.Args.Add(expr); return cmd; }