S-expressions: Difference between revisions
Content added Content deleted
(Strings like foo# wouldn't work, because /b would cut the # I really don't know why it was after the num.) |
(Updated D entry) |
||
Line 850: | Line 850: | ||
=={{header|D}}== |
=={{header|D}}== |
||
<lang d>import std.stdio |
<lang d>import std.stdio, std.conv, std.algorithm, std.variant, std.uni; |
||
import std.conv: text, parse; |
|||
import std.algorithm: canFind; |
|||
import std.variant: Variant; |
|||
import std.uni: isAlpha, isNumber, isWhite; |
|||
alias Sexp = Variant; |
alias Sexp = Variant; |
||
Line 860: | Line 856: | ||
struct Symbol { |
struct Symbol { |
||
private string name; |
private string name; |
||
string toString() { return name; } |
string toString() const { return name; } |
||
} |
} |
||
Sexp parseSexp( |
Sexp parseSexp(string txt) { |
||
static bool isIdentChar(in char c) @safe pure /*nothrow*/ { |
static bool isIdentChar(in char c) @safe pure /*nothrow*/ { |
||
return c.isAlpha || "0123456789!@#-".canFind(c); |
return c.isAlpha || "0123456789!@#-".canFind(c); |
||
Line 869: | Line 865: | ||
size_t pos = 0; |
size_t pos = 0; |
||
while (isWhite(raw[pos])) pos++; |
|||
Sexp _parse() { |
Sexp _parse() { |
||
auto i = pos + 1; |
|||
scope (exit) |
scope (exit) |
||
pos = i; |
pos = i; |
||
if ( |
if (txt[pos] == '"') { |
||
while ( |
while (txt[i] != '"' && i < txt.length) |
||
i++; |
i++; |
||
i++; |
i++; |
||
return Sexp( |
return Sexp(txt[pos + 1 .. i - 1]); |
||
} else if ( |
} else if (txt[pos].isNumber) { |
||
while ( |
while (txt[i].isNumber && i < txt.length) |
||
i++; |
i++; |
||
if ( |
if (txt[i] == '.') { |
||
i++; |
i++; |
||
while ( |
while (txt[i].isNumber && i < txt.length) |
||
i++; |
i++; |
||
auto aux = txt[pos .. i]; |
|||
return aux.parse!double.Sexp; |
|||
} |
} |
||
auto aux = txt[pos .. i]; |
|||
return aux.parse!ulong.Sexp; |
|||
⚫ | |||
} else if (isIdentChar(txt[pos])) { |
|||
⚫ | |||
i++; |
i++; |
||
return Sexp(Symbol( |
return Sexp(Symbol(txt[pos .. i])); |
||
} else if ( |
} else if (txt[pos] == '(') { |
||
Sexp[] lst; |
Sexp[] lst; |
||
while ( |
while (txt[i] != ')') { |
||
while ( |
while (txt[i].isWhite) |
||
i++; |
i++; |
||
pos = i; |
pos = i; |
||
lst ~= _parse |
lst ~= _parse; |
||
i = pos; |
i = pos; |
||
while ( |
while (txt[i].isWhite) |
||
i++; |
i++; |
||
} |
} |
||
Line 909: | Line 907: | ||
return Sexp(null); |
return Sexp(null); |
||
} |
} |
||
⚫ | |||
while (txt[pos].isWhite) |
|||
⚫ | |||
⚫ | |||
} |
} |
||
void writeSexp(Sexp expr) { |
void writeSexp(Sexp expr) { |
||
if (expr.type == typeid(string)) { |
if (expr.type == typeid(string)) { |
||
write(" |
write('"', expr, '"'); |
||
⚫ | |||
write("\""); |
|||
} else if (expr.type == typeid(Sexp[])) { |
} else if (expr.type == typeid(Sexp[])) { |
||
write |
'('.write; |
||
auto arr = expr.get!(Sexp[]); |
auto arr = expr.get!(Sexp[]); |
||
foreach (immutable i, e; arr) { |
foreach (immutable i, e; arr) { |
||
e.writeSexp; |
|||
if (i + 1 < arr.length) |
if (i + 1 < arr.length) |
||
' '.write; |
|||
} |
} |
||
write |
')'.write; |
||
} else { |
} else { |
||
expr.write; |
|||
} |
} |
||
} |
} |
||
void main() { |
void main() { |
||
auto |
auto pTest = `((data "quoted data" 123 4.5) |
||
(data (!@# (4.5) "(more" "data)")))`; |
(data (!@# (4.5) "(more" "data)")))`.parseSexp; |
||
auto pTest = parseSexp(test); |
|||
writeln("Parsed: ", pTest); |
writeln("Parsed: ", pTest); |
||
"Printed: ".write; |
|||
pTest.writeSexp; |
|||
writeln |
writeln; |
||
}</lang> |
}</lang> |
||
{{out}} |
{{out}} |