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: write, writeln;
<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(in string raw) {
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() {
size_t i = pos + 1;
auto i = pos + 1;
scope (exit)
scope (exit)
pos = i;
pos = i;
if (raw[pos] == '"') {
if (txt[pos] == '"') {
while (raw[i] != '"' && i < raw.length)
while (txt[i] != '"' && i < txt.length)
i++;
i++;
i++;
i++;
return Sexp(raw[pos+1..i-1]);
return Sexp(txt[pos + 1 .. i - 1]);
} else if (isNumber(raw[pos])) {
} else if (txt[pos].isNumber) {
while (isNumber(raw[i]) && i < raw.length)
while (txt[i].isNumber && i < txt.length)
i++;
i++;
if (raw[i] == '.') {
if (txt[i] == '.') {
i++;
i++;
while (isNumber(raw[i]) && i < raw.length)
while (txt[i].isNumber && i < txt.length)
i++;
i++;
return Sexp(parse!double(raw[pos .. i]));
auto aux = txt[pos .. i];
return aux.parse!double.Sexp;
}
}
return Sexp(parse!ulong(raw[pos .. i]));
auto aux = txt[pos .. i];
return aux.parse!ulong.Sexp;
} else if (isIdentChar(raw[pos])) {
while (isIdentChar(raw[i]) && i < raw.length)
} else if (isIdentChar(txt[pos])) {
while (isIdentChar(txt[i]) && i < txt.length)
i++;
i++;
return Sexp(Symbol(raw[pos .. i]));
return Sexp(Symbol(txt[pos .. i]));
} else if (raw[pos] == '(') {
} else if (txt[pos] == '(') {
Sexp[] lst;
Sexp[] lst;
while (raw[i] != ')') {
while (txt[i] != ')') {
while (isWhite(raw[i]))
while (txt[i].isWhite)
i++;
i++;
pos = i;
pos = i;
lst ~= _parse();
lst ~= _parse;
i = pos;
i = pos;
while (isWhite(raw[i]))
while (txt[i].isWhite)
i++;
i++;
}
}
Line 909: Line 907:
return Sexp(null);
return Sexp(null);
}
}

return _parse();
while (txt[pos].isWhite)
pos++;
return _parse;
}
}


void writeSexp(Sexp expr) {
void writeSexp(Sexp expr) {
if (expr.type == typeid(string)) {
if (expr.type == typeid(string)) {
write("\"");
write('"', expr, '"');
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) {
writeSexp(e);
e.writeSexp;
if (i + 1 < arr.length)
if (i + 1 < arr.length)
write(" ");
' '.write;
}
}
write(")");
')'.write;
} else {
} else {
write(expr);
expr.write;
}
}
}
}


void main() {
void main() {
auto test = `((data "quoted data" 123 4.5)
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);
write("Printed: ");
"Printed: ".write;
writeSexp(pTest);
pTest.writeSexp;
writeln();
writeln;
}</lang>
}</lang>
{{out}}
{{out}}