import file, ctype; char [] data; /* Data. */ char *c; /* Current point. */ char *s; /* Previous filter point. */ char *e; /* End of the data. */ char *p; /* Start of this token. */ /* Read in a token. */ char [] token () { restart: p = c; if (c >= e) return null; if (isalpha (*c) || *c == "_") { for (c ++; c < e; c ++) if (!isalnum (*c) && *c != "_") break; return p [0 .. (int) (c - p)]; } if (*c == " " || *c == "\r" || *c == "\n" || *c == "\t") { c ++; goto restart; } if (*c == '"') { for (c ++; c < e; c ++) if (*c == '\') c ++; else if (*c == '"') { c ++; break; } goto restart; } if (*c == "'") { for (c ++; c < e; c ++) if (*c == "'") { c ++; break; } goto restart; } if (c < e - 1) { if (*c == "/" && c [1] == "/") { for (c += 2; ; c ++) if (c >= e || *c == "\n") { c ++; goto restart; } } if (*c == "/" && c [1] == "*") { for (c += 2; ; c ++) if (c >= e - 1 || (*c == "*" && c [1] == "/")) { c += 2; goto restart; } } if (*c == "/" && c [1] == "+") { int depth = 1; for (c += 2; ; c ++) if (c >= e - 1) goto restart; else if (*c == "/" && c [1] == "+") { c += 2; depth ++; } else if (*c == "+" && c [1] == "/") { c += 2; depth --; if (!depth) goto restart; } } } c ++; return p [0 .. 1]; } /* Print all text to this point and set s to the current point. */ void flush (char *p) { fwrite (s, (int) (p - s), 1, stdout); s = c; } /* Consume a "{ ... }" or "(xxx) { ... }" block. */ void skipBlock (char *p) { char *o = s; flush (p); int depth = 0; char [] t = token (); if (t == "(") { while (1) { t = token (); if (t == ")" || t == null) break; } t = token (); } if (t != "{") { s = o; flush (c); return; } while (1) { if (t == null) break; if (t == "{") depth ++; if (t == "}") { depth --; if (depth == 0) break; } t = token (); } s = c; } void main (char [] [] args) { data = (char []) read (args [1]); c = s = data; e = s + data.length; char [] t; while (1) { t = token (); if (t == null) { flush (c); return; } switch (t) { /* Remove these keywords. */ case "body": flush (p); s = c; break; /* Remove these blocks. */ case "unittest": case "in": case "out": case "invariant": skipBlock (p); break; /* Remove these "keyword ... ;" sets. */ case "module": case "import": flush (p); while ((t = token ()) != null) if (t == ";") break; s = c; break; /* Remove "extern (...)". */ case "extern": flush (p); if ((t = token ()) != "(") { c = p; break; } while ((t = token ()) != null) if (t == ")") break; s = c; break; /* "alias" into "typedef". */ case "alias": flush (p); printf ("typedef"); s = c; break; /* "instance" into "typedef". */ case "instance": flush (p); printf ("typedef"); s = c; while ((t = token ()) != null) if (t == "(") { flush (p); printf ("<"); s = c; } else if (t == ")") { flush (p); printf (">"); s = c; break; } break; /* "}" into "};" */ case "}": flush (c); printf (";"); break; /* "class ... {" into "class ... { public:". */ case "class": while ((t = token ()) != null) if (t == ";") break; else if (t == "{") { flush (c); printf (" public:"); break; } break; /* "template name (x)" into "template namespace name ". */ case "template": flush (c); printf (" class"); while ((t = token ()) != null) if (t == "(") { flush (p); printf ("<"); s = c; } else if (t == ")") { flush (p); printf (">"); s = c; break; } while ((t = token ()) != null) if (t == "{") { flush (c); printf (" public:"); break; } else if (t == ";") break; break; /* "delegate (...) name" into "(*name) (...)". */ case "delegate": flush (p); s = c; while ((t = token ()) != null) if (t == ")") { t = token (); printf ("(*%.*s)", t); flush (p); s = c; break; } break; default: break; } } }