Thread overview
parse string as char
Feb 09, 2015
Timothee Cour
Feb 09, 2015
Rikki Cattermole
Feb 09, 2015
FG
Feb 09, 2015
FG
Feb 09, 2015
Kagamin
February 09, 2015
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 doesn't work (`\n`.to!char does not work)


February 09, 2015
On 9/02/2015 3:40 p.m., 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)

Ugh, if you are just wanting to get a singular char in a string just you slices.

assert("mystr"[0] == 'm');

February 09, 2015
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);
}




February 09, 2015
Of course consuming it dchar by dchar also works:

    string s = `\tabŁŃ\r\nx`;
    assert(parseDchar(s) == '\t');
    assert(parseDchar(s) == 'a');
    assert(parseDchar(s) == 'b');
    assert(parseDchar(s) == 'Ł');
    assert(parseDchar(s) == 'Ń');
    assert(parseDchar(s) == '\r');
    assert(parseDchar(s) == '\n');
    assert(parseDchar(s) == 'x');
    assert(s.empty);
February 09, 2015
https://github.com/Hackerpilot/libdparse/blob/master/src/std/d/lexer.d#L1491