Decoding Pattern to a Tuple

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Feb 19 14:16:10 PST 2016


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



More information about the Digitalmars-d-learn mailing list