On 2015-02-09 at 03:40, Timothee Cour via Digitalmars-d-learn wrote:
Is there a simple way to parse a string as a char?
eg:
unittest{
   assert(parseChar(`a`)=='a');
   assert(parseChar(`\n`)=='\n'); //NOTE: I'm looking at `\n` not "\n"
   // should also work with other forms of characters, see 
http://dlang.org/lex.html
}
Note, std.conv.to <http://std.conv.to> doesn't work (`\n`.to!char does not work)


parseEscape does something similar to what you need:
https://github.com/D-Programming-Language/phobos/blob/master/std/conv.d#L3415

Unfortunately it is private and handles only escapes, so here is a modified 
version:



import std.range, std.stdio;

dchar parseDchar(Source)(ref Source s)
    if (isInputRange!Source && isSomeChar!(ElementType!Source))
{
    import std.utf, std.conv;
    if (s.front != '\\') {
        dchar c = decodeFront(s);
        return c;
    }
    s.popFront;
    if (s.empty)
        throw new Exception("Unterminated escape sequence");

    dchar getHexDigit()(ref Source s_ = s)  // workaround
    {
        import std.ascii : isAlpha, isHexDigit;
        if (s_.empty)
            throw new Exception("Unterminated escape sequence");
        s_.popFront();
        if (s_.empty)
            throw new Exception("Unterminated escape sequence");
        dchar c = s_.front;
        if (!isHexDigit(c))
            throw new Exception("Hex digit is missing");
        return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0';
    }

    dchar result;

    switch (s.front)
    {
        case '"':   result = '\"';  break;
        case '\'':  result = '\'';  break;
        case '0':   result = '\0';  break;
        case '?':   result = '\?';  break;
        case '\\':  result = '\\';  break;
        case 'a':   result = '\a';  break;
        case 'b':   result = '\b';  break;
        case 'f':   result = '\f';  break;
        case 'n':   result = '\n';  break;
        case 'r':   result = '\r';  break;
        case 't':   result = '\t';  break;
        case 'v':   result = '\v';  break;
        case 'x':
            result  = getHexDigit() << 4;
            result |= getHexDigit();
            break;
        case 'u':
            result  = getHexDigit() << 12;
            result |= getHexDigit() << 8;
            result |= getHexDigit() << 4;
            result |= getHexDigit();
            break;
        case 'U':
            result  = getHexDigit() << 28;
            result |= getHexDigit() << 24;
            result |= getHexDigit() << 20;
            result |= getHexDigit() << 16;
            result |= getHexDigit() << 12;
            result |= getHexDigit() << 8;
            result |= getHexDigit() << 4;
            result |= getHexDigit();
            break;
        default:
            throw new Exception("Unknown escape character " ~ 
to!string(s.front));
    }
    if (s.empty)
        throw new Exception("Unterminated escape sequence");

    s.popFront();

    return result;
}

dstring parseString(Source)(Source s)
    if (isInputRange!Source && isSomeChar!(ElementType!Source))
{
    import std.array;
    dchar[] result;
    auto app = appender(result);
    while (!s.empty)
        app.put(parseDchar(s));
    return app.data;
}

unittest
{
    assert(parseString(``) == ""d);
    assert(parseString(`abc`) == "abc"d);
    assert(parseString(`abc\\n\\n\\n`) == "abc\\n\\n\\n"d);
    assert(parseString(`ąćę\\nłńó`) == "ąćę\\nłńó"d);
    assert(parseString(`abc\\\nx`) == "abc\\\nx"d);
    assert(parseString(`\tabc\r\nx`) == "\tabc\r\nx"d);
    assert(parseString(` \x20 `) == "   "d);
}




Reply via email to