parse string as char

FG via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Feb 9 07:44:06 PST 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);
}






More information about the Digitalmars-d-learn mailing list