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