On 02/19/2016 11:04 AM, Ali Çehreli wrote:

> can be templatized:

Not ready for prime time but now it's templatized:

import std.stdio;
import std.string;
import std.regex;
import std.typecons;
import std.conv;
import std.algorithm;
import std.range;

template regexClass(T) {
    static if (is (T == int)) {
        // Warning: Treats "012" as int (value 12), not octal (value 10).
        enum regexClass = `[0-9]+`;

    } else static if (is (T == char)) {
        enum regexClass = `.`;

    } else static if (is (T == double)) {
        enum regexClass = `[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?`;

    } else {
        static assert(false, format("Unsupported type %s", arg));
    }
}

string regexEscape(string s) {
    // TODO: Expand the array and fix the logic.
    enum specialRegexChars = [ '(', ')' ];

    return s.map!(c => (specialRegexChars.canFind(c)
                        ? format("[%s]", c)
                        : format("%s", c)))
        .joiner
        .text;
}

auto parseDecodeArgs(Args...)(string matchedElementName) {
    string regexString;
    string tupleString = "return tuple(";

    size_t selectionId = 1;

    foreach (arg; Args) {
        static if (is (arg)) {
            regexString ~= format("(%s)", regexClass!arg);
            tupleString ~=
                format("%s[%s].to!%s, ",
                       matchedElementName, selectionId, arg.stringof);
            ++selectionId;

        } else static if (is (typeof(arg) == string)) {
            regexString ~= regexEscape(arg);

        } else {
static assert(false, format("Unsupported type %s", typeof(arg)));
        }
    }

    tupleString ~= ");";
    return tuple(regexString, tupleString);
}

auto decode(Args...)(string s) {
    enum parseResult = parseDecodeArgs!Args("e");
    enum r = ctRegex!(parseResult[0]);

    // pragma(msg, parseResult[0]);
    // pragma(msg, parseResult[1]);

    auto matched = s.match(r);

    if (matched) {
        foreach (e; matched) {
            mixin (parseResult[1]);
        }
    }

    return typeof(return)();
}

void main() {
    auto t = decode!("(", int, ")", char, "(", double, ")")("(1)-(2.5)");
    writeln(t);

    // Create a decoder for repeated use
    auto decoder = (string s) => decode!(int, "/", double)(s);

    // Decode each with the same decoder
    auto decoded = ["1/1.5", "2/2.5", "3/3.5"]
                   .map!decoder;

    writeln(decoded);
}

Ali

Reply via email to