about summary refs log tree commit diff stats
path: root/tangle/003tangle.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tangle/003tangle.cc')
-rw-r--r--tangle/003tangle.cc338
1 files changed, 0 insertions, 338 deletions
diff --git a/tangle/003tangle.cc b/tangle/003tangle.cc
deleted file mode 100644
index 64c841f1..00000000
--- a/tangle/003tangle.cc
+++ /dev/null
@@ -1,338 +0,0 @@
-// Reorder a file based on directives starting with ':(' (tangle directives).
-// Insert #line directives to preserve line numbers in the original.
-// Clear lines starting with '//:' (tangle comments).
-
-//// Preliminaries regarding line number management
-
-struct Line {
-  string filename;
-  size_t line_number;
-  string contents;
-  Line() :line_number(0) {}
-  Line(const string& text) :line_number(0) {
-    contents = text;
-  }
-  Line(const string& text, const string& f, const size_t& l) {
-    contents = text;
-    filename = f;
-    line_number = l;
-  }
-  Line(const string& text, const Line& origin) {
-    contents = text;
-    filename = origin.filename;
-    line_number = origin.line_number;
-  }
-};
-
-// Emit a list of line contents, inserting directives just at discontinuities.
-// Needs to be a macro because 'out' can have the side effect of creating a
-// new trace in Trace_stream.
-#define EMIT(lines, out) if (!lines.empty()) { \
-  string last_file = lines.begin()->filename; \
-  size_t last_line = lines.begin()->line_number-1; \
-  out << line_directive(lines.begin()->line_number, lines.begin()->filename) << '\n'; \
-  for (list<Line>::const_iterator p = lines.begin(); p != lines.end(); ++p) { \
-    if (last_file != p->filename || last_line != p->line_number-1) \
-      out << line_directive(p->line_number, p->filename) << '\n'; \
-    out << p->contents << '\n'; \
-    last_file = p->filename; \
-    last_line = p->line_number; \
-  } \
-}
-
-string line_directive(size_t line_number, string filename) {
-  ostringstream result;
-  if (filename.empty())
-    result << "#line " << line_number;
-  else
-    result << "#line " << line_number << " \"" << filename << '"';
-  return result.str();
-}
-
-//// Tangle
-
-string Toplevel = "run";
-
-int tangle(int argc, const char* argv[]) {
-  list<Line> result;
-  for (int i = 1; i < argc; ++i) {
-//?     cerr << "new file " << argv[i] << '\n';
-    Toplevel = "run";
-    ifstream in(argv[i]);
-    tangle(in, argv[i], result);
-  }
-
-  EMIT(result, cout);
-  return 0;
-}
-
-void tangle(istream& in, const string& filename, list<Line>& out) {
-  string curr_line;
-  size_t line_number = 1;
-  while (!in.eof()) {
-    getline(in, curr_line);
-    if (starts_with(curr_line, ":(")) {
-      ++line_number;
-      process_next_hunk(in, trim(curr_line), filename, line_number, out);
-      continue;
-    }
-    if (starts_with(curr_line, "//:")) {
-      ++line_number;
-      continue;
-    }
-    out.push_back(Line(curr_line, filename, line_number));
-    ++line_number;
-  }
-
-  // Trace all line contents, inserting directives just at discontinuities.
-  if (!Trace_stream) return;
-  EMIT(out, Trace_stream->stream("tangle"));
-}
-
-// just for tests
-void tangle(istream& in, list<Line>& out) {
-  tangle(in, "", out);
-}
-
-void process_next_hunk(istream& in, const string& directive, const string& filename, size_t& line_number, list<Line>& out) {
-  istringstream directive_stream(directive.substr(2));  // length of ":("
-  string cmd = next_tangle_token(directive_stream);
-
-  // first slurp all lines until next directive
-  list<Line> hunk;
-  {
-    string curr_line;
-    while (!in.eof()) {
-      std::streampos old = in.tellg();
-      getline(in, curr_line);
-      if (starts_with(curr_line, ":(")) {
-        in.seekg(old);
-        break;
-      }
-      if (starts_with(curr_line, "//:")) {
-        // tangle comments
-        ++line_number;
-        continue;
-      }
-      hunk.push_back(Line(curr_line, filename, line_number));
-      ++line_number;
-    }
-  }
-
-  if (cmd == "code") {
-    out.insert(out.end(), hunk.begin(), hunk.end());
-    return;
-  }
-
-  if (cmd == "before" || cmd == "after" || cmd == "replace" || cmd == "replace{}" || cmd == "delete" || cmd == "delete{}") {
-    list<Line>::iterator target = locate_target(out, directive_stream);
-    if (target == out.end()) {
-      raise << "couldn't find target " << directive << '\n' << die();
-      return;
-    }
-
-    indent_all(hunk, target);
-
-    if (cmd == "before") {
-      out.splice(target, hunk);
-    }
-    else if (cmd == "after") {
-      ++target;
-      out.splice(target, hunk);
-    }
-    else if (cmd == "replace" || cmd == "delete") {
-      out.splice(target, hunk);
-      out.erase(target);
-    }
-    else if (cmd == "replace{}" || cmd == "delete{}") {
-      if (find_trim(hunk, ":OLD_CONTENTS") == hunk.end()) {
-        out.splice(target, hunk);
-        out.erase(target, balancing_curly(target));
-      }
-      else {
-        list<Line>::iterator next = balancing_curly(target);
-        list<Line> old_version;
-        old_version.splice(old_version.begin(), out, target, next);
-        old_version.pop_back();  old_version.pop_front();  // contents only please, not surrounding curlies
-
-        list<Line>::iterator new_pos = find_trim(hunk, ":OLD_CONTENTS");
-        indent_all(old_version, new_pos);
-        hunk.splice(new_pos, old_version);
-        hunk.erase(new_pos);
-        out.splice(next, hunk);
-      }
-    }
-    return;
-  }
-
-  raise << "unknown directive " << cmd << '\n' << die();
-}
-
-list<Line>::iterator locate_target(list<Line>& out, istream& directive_stream) {
-  string pat = next_tangle_token(directive_stream);
-  if (pat == "") return out.end();
-
-  string next_token = next_tangle_token(directive_stream);
-  if (next_token == "") {
-    return find_substr(out, pat);
-  }
-  // first way to do nested pattern: pattern 'following' intermediate
-  else if (next_token == "following") {
-    string pat2 = next_tangle_token(directive_stream);
-    if (pat2 == "") return out.end();
-    list<Line>::iterator intermediate = find_substr(out, pat2);
-    if (intermediate == out.end()) return out.end();
-    return find_substr(out, intermediate, pat);
-  }
-  // second way to do nested pattern: intermediate 'then' pattern
-  else if (next_token == "then") {
-    list<Line>::iterator intermediate = find_substr(out, pat);
-    if (intermediate == out.end()) return out.end();
-    string pat2 = next_tangle_token(directive_stream);
-    if (pat2 == "") return out.end();
-    return find_substr(out, intermediate, pat2);
-  }
-  raise << "unknown keyword in directive: " << next_token << '\n';
-  return out.end();
-}
-
-// indent all lines in l like indentation at exemplar
-void indent_all(list<Line>& l, list<Line>::iterator exemplar) {
-  string curr_indent = indent(exemplar->contents);
-  for (list<Line>::iterator p = l.begin(); p != l.end(); ++p)
-    if (!p->contents.empty())
-      p->contents.insert(p->contents.begin(), curr_indent.begin(), curr_indent.end());
-}
-
-string next_tangle_token(istream& in) {
-  in >> std::noskipws;
-  ostringstream out;
-  skip_whitespace(in);
-  if (in.peek() == '"')
-    slurp_tangle_string(in, out);
-  else
-    slurp_word(in, out);
-  return out.str();
-}
-
-void slurp_tangle_string(istream& in, ostream& out) {
-  in.get();
-  char c;
-  while (in >> c) {
-    if (c == '\\') {
-      // skip backslash and save next character unconditionally
-      in >> c;
-      out << c;
-      continue;
-    }
-    if (c == '"') break;
-    out << c;
-  }
-}
-
-void slurp_word(istream& in, ostream& out) {
-  char c;
-  while (in >> c) {
-    if (isspace(c) || c == ')') {
-      in.putback(c);
-      break;
-    }
-    out << c;
-  }
-}
-
-void skip_whitespace(istream& in) {
-  while (isspace(in.peek()))
-    in.get();
-}
-
-list<Line>::iterator balancing_curly(list<Line>::iterator curr) {
-  long open_curlies = 0;
-  do {
-    for (string::iterator p = curr->contents.begin(); p != curr->contents.end(); ++p) {
-      if (*p == '{') ++open_curlies;
-      if (*p == '}') --open_curlies;
-    }
-    ++curr;
-    // no guard so far against unbalanced curly, including inside comments or strings
-  } while (open_curlies != 0);
-  return curr;
-}
-
-list<Line>::iterator find_substr(list<Line>& in, const string& pat) {
-  for (list<Line>::iterator p = in.begin(); p != in.end(); ++p)
-    if (p->contents.find(pat) != string::npos)
-      return p;
-  return in.end();
-}
-
-list<Line>::iterator find_substr(list<Line>& in, list<Line>::iterator p, const string& pat) {
-  for (; p != in.end(); ++p)
-    if (p->contents.find(pat) != string::npos)
-      return p;
-  return in.end();
-}
-
-list<Line>::iterator find_trim(list<Line>& in, const string& pat) {
-  for (list<Line>::iterator p = in.begin(); p != in.end(); ++p)
-    if (trim(p->contents) == pat)
-      return p;
-  return in.end();
-}
-
-string escape(string s) {
-  s = replace_all(s, "\\", "\\\\");
-  s = replace_all(s, "\"", "\\\"");
-  s = replace_all(s, "", "\\n");
-  return s;
-}
-
-string replace_all(string s, const string& a, const string& b) {
-  for (size_t pos = s.find(a); pos != string::npos; pos = s.find(a, pos+b.size()))
-    s = s.replace(pos, a.size(), b);
-  return s;
-}
-
-// does s start with pat, after skipping whitespace?
-// pat can't start with whitespace
-bool starts_with(const string& s, const string& pat) {
-  for (size_t pos = 0; pos < s.size(); ++pos)
-    if (!isspace(s.at(pos)))
-      return s.compare(pos, pat.size(), pat) == 0;
-  return false;
-}
-
-string indent(const string& s) {
-  for (size_t pos = 0; pos < s.size(); ++pos)
-    if (!isspace(s.at(pos)))
-      return s.substr(0, pos);
-  return "";
-}
-
-string strip_indent(const string& s, size_t n) {
-  if (s.empty()) return "";
-  string::const_iterator curr = s.begin();
-  while (curr != s.end() && n > 0 && isspace(*curr)) {
-    ++curr;
-    --n;
-  }
-  return string(curr, s.end());
-}
-
-string trim(const string& s) {
-  string::const_iterator first = s.begin();
-  while (first != s.end() && isspace(*first))
-    ++first;
-  if (first == s.end()) return "";
-
-  string::const_iterator last = --s.end();
-  while (last != s.begin() && isspace(*last))
-    --last;
-  ++last;
-  return string(first, last);
-}
-
-const Line& front(const list<Line>& l) {
-  assert(!l.empty());
-  return l.front();
-}