public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { BlockNode result = new BlockNode(); // Iterating indices (and not values via foreach) // to avoid crashes occuring with AddToPool within AddToPool for (int i = 0; i < p.Pool.Lines.Count; ++i) { Pool.PooledLine line = p.Pool.Lines[i]; MergeableGenerator <Token> tempGenerator = new MergeableGenerator <Token>(line.Tokens); tempGenerator.MoveNext(); while (!tempGenerator.EOS) { p.ParseLine(tempGenerator, line.Scope).IfJust( (lineNode) => result.Children.Add(lineNode)); } } p.Pool.Lines.Clear(); return(new Just <ILineNode>(result)); }
private static Maybe <IList <Token> > TokenizeParam(EAParser p, IParamNode param) { switch (param.Type) { case ParamType.STRING: Token input = ((StringNode)param).MyToken; Tokenizer t = new Tokenizer(); return(new Just <IList <Token> >(new List <Token>(t.TokenizeLine(input.Content, input.FileName, input.LineNumber, input.ColumnNumber)))); case ParamType.MACRO: try { IList <Token> myBody = new List <Token>(((MacroInvocationNode)param).ExpandMacro()); return(new Just <IList <Token> >(myBody)); } catch (KeyNotFoundException) { MacroInvocationNode asMacro = (MacroInvocationNode)param; p.Error(asMacro.MyLocation, "Undefined macro: " + asMacro.Name); } break; case ParamType.LIST: ListNode n = (ListNode)param; return(new Just <IList <Token> >(new List <Token>(n.ToTokens()))); case ParamType.ATOM: return(new Just <IList <Token> >(new List <Token>(((IAtomNode)param).ToTokens()))); } return(new Nothing <IList <Token> >()); }
public MacroInvocationNode(EAParser p, Token invokeTok, IList <IList <Token> > parameters, ImmutableStack <Closure> scopes) { this.p = p; this.invokeToken = invokeTok; this.Parameters = parameters; this.scope = scopes; }
public Maybe <ILineNode> HandleDirective(EAParser p, Token directive, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { string directiveName = directive.Content.Substring(1); if (directives.TryGetValue(directiveName, out IDirective? toExec)) { if (!toExec.RequireInclusion || p.IsIncluding) { if (toExec.MinParams <= parameters.Count && (!toExec.MaxParams.HasValue || parameters.Count <= toExec.MaxParams)) { return(toExec.Execute(p, directive, parameters, tokens)); } else { p.Error(directive.Location, "Invalid number of parameters (" + parameters.Count + ") to directive " + directiveName + "."); } } } else { p.Error(directive.Location, "Directive not recognized: " + directiveName); } return(new Nothing <ILineNode>()); }
public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { Maybe <string> existantFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), parameters[0].ToString()); if (!existantFile.IsNothing) { try { string pathname = existantFile.FromJust; FileStream inputFile = new FileStream(pathname, FileMode.Open); Tokenizer newFileTokenizer = new Tokenizer(); tokens.PrependEnumerator(newFileTokenizer.Tokenize(inputFile).GetEnumerator()); } catch (Exception) { p.Error(self.Location, "Error reading file \"" + parameters[0].ToString() + "\"."); } } else { p.Error(parameters[0].MyLocation, "Could not find file \"" + parameters[0].ToString() + "\"."); } return(new Nothing <ILineNode>()); }
public MacroCollection(EAParser parent) { Macros = new Dictionary <string, Dictionary <int, IMacro> >(); Parent = parent; BuiltInMacros = new Dictionary <string, BuiltInMacro> { { "String", new String() }, { "IsDefined", new IsDefined(parent) }, { "AddToPool", new AddToPool(parent) }, }; }
private static IEnumerable <Token> ExpandAllIdentifiers(EAParser p, Queue <Token> tokens, ImmutableStack <string> seenDefs, ImmutableStack <Tuple <string, int> > seenMacros) { IEnumerable <Token> output = new List <Token>(); while (tokens.Count > 0) { Token current = tokens.Dequeue(); if (current.Type == TokenType.IDENTIFIER) { if (p.Macros.ContainsName(current.Content) && tokens.Count > 0 && tokens.Peek().Type == TokenType.OPEN_PAREN) { IList <IList <Token> > param = p.ParseMacroParamList(new MergeableGenerator <Token>(tokens)); //TODO: I don't like wrapping this in a mergeable generator..... Maybe interface the original better? if (!seenMacros.Contains(new Tuple <string, int>(current.Content, param.Count)) && p.Macros.HasMacro(current.Content, param.Count)) { foreach (Token t in p.Macros.GetMacro(current.Content, param.Count).ApplyMacro(current, param, p.GlobalScope)) { yield return(t); } } else if (seenMacros.Contains(new Tuple <string, int>(current.Content, param.Count))) { yield return(current); foreach (IList <Token> l in param) { foreach (Token t in l) { yield return(t); } } } else { yield return(current); } } else if (!seenDefs.Contains(current.Content) && p.Definitions.ContainsKey(current.Content)) { foreach (Token t in p.Definitions[current.Content].ApplyDefinition(current)) { yield return(t); } } else { yield return(current); } } else { yield return(current); } } }
public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { if (p.Inclusion.IsEmpty) { p.Error(self.Location, "No matching if[n]def."); } else { p.Inclusion = p.Inclusion.Tail; } return(new Nothing <ILineNode>()); }
public EAInterpreter(IOutput output, string game, string rawsFolder, string rawsExtension, Stream sin, string inFileName, Log log) { this.game = game; this.output = output; try { allRaws = ProcessRaws(game, ListAllRaws(rawsFolder, rawsExtension)); } catch (RawReader.RawParseException e) { Location loc = new Location { file = e.FileName, lineNum = e.LineNumber, colNum = 1 }; log.Message(Log.MsgKind.ERROR, loc, "An error occured while parsing raws"); log.Message(Log.MsgKind.ERROR, loc, e.Message); Environment.Exit(-1); // ew? } this.sin = sin; this.log = log; iFile = inFileName; IncludeFileSearcher includeSearcher = new IncludeFileSearcher(); includeSearcher.IncludeDirectories.Add(AppDomain.CurrentDomain.BaseDirectory); foreach (string path in EAOptions.Instance.includePaths) { includeSearcher.IncludeDirectories.Add(path); } IncludeFileSearcher toolSearcher = new IncludeFileSearcher { AllowRelativeInclude = false }; toolSearcher.IncludeDirectories.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tools")); foreach (string path in EAOptions.Instance.toolsPaths) { includeSearcher.IncludeDirectories.Add(path); } myParser = new EAParser(allRaws, log, new Preprocessor.DirectiveHandler(includeSearcher, toolSearcher)); myParser.Definitions['_' + game + '_'] = new Definition(); myParser.Definitions["__COLORZ_CORE__"] = new Definition(); }
public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { foreach (IParamNode parm in parameters) { string s = parm.ToString(); if (p.Definitions.ContainsKey(s)) { p.Definitions.Remove(parm.ToString()); } else { p.Warning(parm.MyLocation, "Undefining non-existant definition: " + s); } } return(new Nothing <ILineNode>()); }
public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { bool flag = true; Maybe <string> identifier; foreach (IParamNode parameter in parameters) { if (parameter.Type == ParamType.ATOM && !(identifier = ((IAtomNode)parameter).GetIdentifier()).IsNothing) { flag &= p.Macros.ContainsName(identifier.FromJust) || p.Definitions.ContainsKey(identifier.FromJust); //TODO: Built in definitions? } else { p.Error(parameter.MyLocation, "Definition name must be an identifier."); } } p.Inclusion = new ImmutableStack <bool>(flag, p.Inclusion); return(new Nothing <ILineNode>()); }
public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { Maybe <string> existantFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), parameters[0].ToString() !); if (!existantFile.IsNothing) { try { string pathname = existantFile.FromJust; return(new Just <ILineNode>(new DataNode(p.CurrentOffset, File.ReadAllBytes(pathname)))); } catch (Exception) { p.Error(self.Location, "Error reading file \"" + parameters[0].ToString() + "\"."); } } else { p.Error(parameters[0].MyLocation, "Could not find file \"" + parameters[0].ToString() + "\"."); } return(new Nothing <ILineNode>()); }
public Maybe <ILineNode> Execute(EAParser parse, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { ExecTimer.Timer.AddTimingPoint(ExecTimer.KEY_GENERIC); Maybe <string> validFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), IOUtility.GetToolFileName(parameters[0].ToString() !)); if (validFile.IsNothing) { parse.Error(parameters[0].MyLocation, "Tool " + parameters[0].ToString() + " not found."); return(new Nothing <ILineNode>()); } //TODO: abstract out all this running stuff into a method so I don't have code duplication with inctext //from http://stackoverflow.com/a/206347/1644720 // Start the child process. System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.RedirectStandardError = true; // Redirect the output stream of the child process. p.StartInfo.WorkingDirectory = Path.GetDirectoryName(self.FileName) !; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.CreateNoWindow = true; p.StartInfo.FileName = validFile.FromJust; StringBuilder argumentBuilder = new StringBuilder(); for (int i = 1; i < parameters.Count; i++) { if (parameters[i].Type == ParamType.ATOM) { parameters[i] = ((IAtomNode)parameters[i]).Simplify(); } argumentBuilder.Append(parameters[i].PrettyPrint()); argumentBuilder.Append(' '); } argumentBuilder.Append("--to-stdout"); p.StartInfo.Arguments = argumentBuilder.ToString(); p.Start(); // Do not wait for the child process to exit before // reading to the end of its redirected stream. // p.WaitForExit(); // Read the output stream first and then wait. MemoryStream outputBytes = new MemoryStream(); MemoryStream errorStream = new MemoryStream(); p.StandardOutput.BaseStream.CopyTo(outputBytes); p.StandardError.BaseStream.CopyTo(errorStream); p.WaitForExit(); byte[] output = outputBytes.GetBuffer().Take((int)outputBytes.Length).ToArray(); if (errorStream.Length > 0) { parse.Error(self.Location, Encoding.ASCII.GetString(errorStream.GetBuffer().Take((int)errorStream.Length).ToArray())); } else if (output.Length >= 7 && Encoding.ASCII.GetString(output.Take(7).ToArray()) == "ERROR: ") { parse.Error(self.Location, Encoding.ASCII.GetString(output.Skip(7).ToArray())); } ExecTimer.Timer.AddTimingPoint(parameters[0].ToString() !.ToLower()); return(new Just <ILineNode>(new DataNode(parse.CurrentOffset, output))); }
public AddToPool(EAParser parent) { ParentParser = parent; }
public BaseClosure(EAParser enclosing) { this.enclosing = enclosing; }
public Maybe <ILineNode> Execute(EAParser p, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { if (parameters[0].Type == ParamType.MACRO) { MacroInvocationNode signature = (MacroInvocationNode)(parameters[0]); string name = signature.Name; IList <Token> myParams = new List <Token>(); foreach (IList <Token> l1 in signature.Parameters) { if (l1.Count != 1 || l1[0].Type != TokenType.IDENTIFIER) { p.Error(l1[0].Location, "Macro parameters must be identifiers (got " + l1[0].Content + ")."); } else { myParams.Add(l1[0]); } } /* if (!p.IsValidMacroName(name, myParams.Count)) * { * if (p.IsReservedName(name)) * { * p.Error(signature.MyLocation, "Invalid redefinition: " + name); * } * else * p.Warning(signature.MyLocation, "Redefining " + name + '.'); * }*/ if (p.Macros.HasMacro(name, myParams.Count)) { p.Warning(signature.MyLocation, "Redefining " + name + '.'); } Maybe <IList <Token> > toRepl; if (parameters.Count != 2) { toRepl = new Just <IList <Token> >(new List <Token>()); } else { toRepl = ExpandParam(p, parameters[1], myParams.Select((Token t) => t.Content)); } if (!toRepl.IsNothing) { p.Macros.AddMacro(new Macro(myParams, toRepl.FromJust), name, myParams.Count); } } else { //Note [mutually] recursive definitions are handled by Parser expansion. Maybe <string> maybeIdentifier; if (parameters[0].Type == ParamType.ATOM && !(maybeIdentifier = ((IAtomNode)parameters[0]).GetIdentifier()).IsNothing) { string name = maybeIdentifier.FromJust; if (p.Definitions.ContainsKey(name)) { p.Warning(parameters[0].MyLocation, "Redefining " + name + '.'); } if (parameters.Count == 2) { Maybe <IList <Token> > toRepl = ExpandParam(p, parameters[1], Enumerable.Empty <string>()); if (!toRepl.IsNothing) { p.Definitions[name] = new Definition(toRepl.FromJust); } } else { p.Definitions[name] = new Definition(); } } else { p.Error(parameters[0].MyLocation, "Definition names must be identifiers (got " + parameters[0].ToString() + ")."); } } return(new Nothing <ILineNode>()); }
public Maybe <ILineNode> Execute(EAParser parse, Token self, IList <IParamNode> parameters, MergeableGenerator <Token> tokens) { ExecTimer.Timer.AddTimingPoint(ExecTimer.KEY_GENERIC); Maybe <string> validFile = FileSearcher.FindFile(Path.GetDirectoryName(self.FileName), IOUtility.GetToolFileName(parameters[0].ToString())); if (validFile.IsNothing) { parse.Error(parameters[0].MyLocation, "Tool " + parameters[0].ToString() + " not found."); return(new Nothing <ILineNode>()); } //from http://stackoverflow.com/a/206347/1644720 // Start the child process. System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.RedirectStandardError = true; // Redirect the output stream of the child process. p.StartInfo.WorkingDirectory = Path.GetDirectoryName(self.FileName); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.CreateNoWindow = true; p.StartInfo.FileName = validFile.FromJust; StringBuilder argumentBuilder = new StringBuilder(); for (int i = 1; i < parameters.Count; i++) { parameters[i].AsAtom().IfJust((IAtomNode n) => { parameters[i] = n.Simplify(); }); argumentBuilder.Append(parameters[i].PrettyPrint()); argumentBuilder.Append(' '); } argumentBuilder.Append("--to-stdout"); p.StartInfo.Arguments = argumentBuilder.ToString(); p.Start(); // Do not wait for the child process to exit before // reading to the end of its redirected stream. // p.WaitForExit(); // Read the output stream first and then wait. MemoryStream outputBytes = new MemoryStream(); MemoryStream errorStream = new MemoryStream(); p.StandardOutput.BaseStream.CopyTo(outputBytes); p.StandardError.BaseStream.CopyTo(errorStream); p.WaitForExit(); byte[] output = outputBytes.GetBuffer().Take((int)outputBytes.Length).ToArray(); if (errorStream.Length > 0) { parse.Error(self.Location, Encoding.ASCII.GetString(errorStream.GetBuffer().Take((int)errorStream.Length).ToArray())); } else if (output.Length >= 7 && Encoding.ASCII.GetString(output.Take(7).ToArray()) == "ERROR: ") { parse.Error(self.Location, Encoding.ASCII.GetString(output.Skip(7).ToArray())); } else { outputBytes.Position = 0; //Reset MemoryStream position so StreamReader starts reading from beginning. Tokenizer t = new Tokenizer(); tokens.PrependEnumerator(t.Tokenize(outputBytes, Path.GetFileName(self.FileName) + ", Line " + self.LineNumber + "; " + parameters[0].ToString()).GetEnumerator()); } ExecTimer.Timer.AddTimingPoint(parameters[0].ToString().ToLower()); return(new Nothing <ILineNode>()); }
public IsDefined(EAParser parent) { ParentParser = parent; }