diff interps/rail/src/main.cpp @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interps/rail/src/main.cpp	Sun Dec 09 19:30:08 2012 +0000
@@ -0,0 +1,223 @@
+// main.cpp
+
+#include "lib.h"
+#include "Thread.h"
+#include "Board.h"
+#include "interactive.h"
+
+using namespace std;
+
+void parseAllArguments(int argc, char * argv[]);
+void parseArgument(string const & arg);
+bool hasPrefix(string const & subject, string const & prefix);
+void parseInput(map<string, Board> & globals);
+void parseFile(ifstream & file, map<string, Board> & globals);
+void parseField(ifstream & file, list<string> & field, string & line);
+string parseHeader(string const & line);
+
+int main(int argc, char * argv[])
+{
+  int result = 0;
+  try
+  {
+    parseAllArguments(argc, argv);
+    map<string, Board> globals;
+    parseInput(globals);
+
+    Thread program;
+    map<string, Board>::iterator mainPos = globals.find("main");
+    if (mainPos != globals.end())
+    {
+      program.reset(mainPos->second, &globals);
+    }
+    else
+    {
+      throw InternalException("Crash: No 'main' function found");
+    }
+    if (args::isBatch)
+    {
+      program.go();
+    }
+    else
+    {
+      runInteractive(program);
+    }
+  }
+  catch(ArgumentException & error)
+  {
+    cerr << "Argument Error: " << error.what() << endl;
+    cerr << "Usage: " << argv[0] << " [--batch] [--interactive] " << endl
+         << "        [--input=<file>] [--output=<file>] <sourcefile> " << endl
+         << "        [<sourcefile> [...]]" << endl << endl;
+
+    cerr << "--batch           Runs in batch mode. The interpreted program will run" << endl
+         << "                  silently to completion." << endl;
+
+    cerr << "--interactive     Runs in interactive mode. A step by step readout of the" << endl
+         << "                  interpreted program is displayed with debugging controls." << endl
+         << "                  If the run is interactive, then input and output must both"
+         << "                  be bound to files." << endl;
+
+    cerr << "--input=<file>    Sets standard input of the interpreted program to <file>." << endl
+         << "                  Default is the outer program's standard input." << endl;
+
+    cerr << "--ouput=<file>    Sets standard output of the interpreted program to <file>" << endl
+         << "                  Default is the outer program's standard output." << endl;
+
+    result = 2;
+  }
+  catch(std::exception & error)
+  {
+    cerr << "Internal Error: " << error.what() << endl;
+    result = 1;
+  }
+  return result;
+}
+
+void parseAllArguments(int argc, char * argv[])
+{
+  for (int i = 1; i < argc; ++i)
+  {
+    parseArgument(argv[i]);
+  }
+  if (!(args::isBatch) && (args::output == NULL || args::input == NULL))
+  {
+    throw ArgumentException("If the run is interactive, then input and output must both be bound to files.");
+  }
+  else if (args::sourceFiles.empty())
+  {
+    throw ArgumentException("No source files to interpret.");
+  }
+
+  if (args::output == NULL)
+  {
+    args::output = &cout;
+  }
+  if (args::input == NULL)
+  {
+    args::input = &cin;
+  }
+}
+
+void parseArgument(string const & arg)
+{
+  static const string batchFlag = "--batch";
+  static const string interactiveFlag = "--interactive";
+  static const string inputPrefix = "--input=";
+  static const string outputPrefix = "--output=";
+
+  static ifstream input;
+  static ofstream output;
+  if (arg == batchFlag)
+  {
+    args::isBatch = true;
+  }
+  else if (arg == interactiveFlag)
+  {
+    args::isBatch = false;
+  }
+  else if (hasPrefix(arg, inputPrefix))
+  {
+    if (args::input == NULL)
+    {
+      input.open(arg.substr(inputPrefix.size()).c_str(), ios::in);
+      if (!input)
+      {
+        throw ArgumentException("Failed to open '--input' file: "
+                                + arg.substr(inputPrefix.size()));
+      }
+      args::input = &input;
+    }
+    else
+    {
+      throw ArgumentException("Only one '--input' file is allowed: " + arg);
+    }
+  }
+  else if (hasPrefix(arg, outputPrefix))
+  {
+    if (args::output == NULL)
+    {
+      output.open(arg.substr(outputPrefix.size()).c_str(),
+                  ios::out | ios::trunc);
+      if (!output)
+      {
+        throw ArgumentException("Failed to open '--output' file: "
+                                + arg.substr(outputPrefix.size()));
+      }
+      args::output = &output;
+    }
+    else
+    {
+      throw ArgumentException("Only one '--output' file is allowed: " + arg);
+    }
+  }
+  else
+  {
+    // This must be a source filename.
+    args::sourceFiles.push_back(arg);
+  }
+}
+
+bool hasPrefix(string const & subject, string const & prefix)
+{
+  return subject.compare(0, prefix.size(), prefix) == 0;
+}
+
+void parseInput(map<string, Board> & globals)
+{
+  list<string>::iterator pos = args::sourceFiles.begin();
+  list<string>::iterator limit = args::sourceFiles.end();
+  for (; pos != limit; ++pos)
+  {
+    ifstream source(pos->c_str(), ios::in);
+    if (!source)
+    {
+      throw ArgumentException("Failed to open source file: " + *pos);
+    }
+    parseFile(source, globals);
+  }
+}
+
+void parseFile(ifstream & file, map<string, Board> & globals)
+{
+  list<string> field;
+  string line;
+  string name;
+  parseField(file, field, line);
+  while (file)
+  {
+    field.clear();
+    field.push_back(line);
+    name = parseHeader(line);
+    parseField(file, field, line);
+    if (name != "")
+    {
+      globals[name].reset(name, field);
+    }
+  }
+}
+
+void parseField(ifstream & file, list<string> & field, string & line)
+{
+  getline(file, line);
+  while (file && line[0] != '$')
+  {
+    field.push_back(line);
+    getline(file, line);
+  }
+}
+
+string parseHeader(string const & line)
+{
+  string result;
+  size_t first = line.find('\'');
+  if (first != string::npos)
+  {
+    size_t second = line.find('\'', first + 1);
+    if (second != string::npos)
+    {
+      result = line.substr(first + 1, second - (first + 1));
+    }
+  }
+  return result;
+}