224 lines
5.1 KiB
D
Executable File
224 lines
5.1 KiB
D
Executable File
#!/usr/bin/env rdmd
|
|
|
|
import std.algorithm;
|
|
import std.ascii;
|
|
import std.file;
|
|
import std.regex;
|
|
import std.stdio;
|
|
import std.string;
|
|
|
|
struct ConstantCompletion
|
|
{
|
|
string[] identifiers;
|
|
string ddoc;
|
|
}
|
|
|
|
struct SingleConstantCompletion
|
|
{
|
|
string identifier;
|
|
string ddoc;
|
|
|
|
string toString() const
|
|
{
|
|
return "ConstantCompletion(\"" ~ identifier ~ "\", `" ~ ddoc.replaceAll(ctRegex!"`+",
|
|
"` ~ \"$0\" ~ `") ~ "`)";
|
|
}
|
|
}
|
|
|
|
unittest
|
|
{
|
|
ConstantCompletion completion;
|
|
completion.ddoc = "'abc``def'";
|
|
assert(completion.toString == q{ConstantCompletion("", `'abc` ~ "``" ~ `def'`)});
|
|
}
|
|
|
|
ConstantCompletion[] parsePragmas(string ddoc)
|
|
{
|
|
ConstantCompletion[] completions;
|
|
|
|
bool foundTerminator;
|
|
|
|
ConstantCompletion current;
|
|
bool inInlineCode;
|
|
bool seekingToFirst = true;
|
|
string indent;
|
|
|
|
void addCurrent()
|
|
{
|
|
if (seekingToFirst)
|
|
{
|
|
current = ConstantCompletion.init;
|
|
return;
|
|
}
|
|
// ret still has `$(DD content)` around it, strip that
|
|
if (current.ddoc.startsWith("$(DD"))
|
|
{
|
|
current.ddoc = current.ddoc["$(DD".length .. $].strip;
|
|
if (current.ddoc.endsWith(")"))
|
|
current.ddoc = current.ddoc[0 .. $ - 1].stripRight;
|
|
}
|
|
completions ~= current;
|
|
current = ConstantCompletion.init;
|
|
}
|
|
|
|
foreach (line; ddoc.lineSplitter!(KeepTerminator.yes))
|
|
{
|
|
auto strippedLine = line.stripLeft;
|
|
if (strippedLine.startsWith("$(SPEC_SUBNAV_PREV_NEXT"))
|
|
{
|
|
addCurrent();
|
|
// end of macros
|
|
foundTerminator = true;
|
|
break;
|
|
}
|
|
else if (strippedLine.startsWith("$(DT $(LNAME2 "))
|
|
{
|
|
addCurrent();
|
|
seekingToFirst = false;
|
|
indent = line[0 .. $ - strippedLine.length];
|
|
string identifierLine = strippedLine.stripRight; // fully stripped
|
|
auto closing = identifierLine.indexOfAny("),");
|
|
if (closing == -1)
|
|
closing = identifierLine.length;
|
|
current.identifiers = [identifierLine["$(DT $(LNAME2".length .. closing].strip];
|
|
}
|
|
else if (!seekingToFirst)
|
|
{
|
|
if (line.startsWith("---")) // code blocks aren't indented
|
|
inInlineCode = !inInlineCode;
|
|
|
|
if (inInlineCode)
|
|
current.ddoc ~= line;
|
|
else
|
|
{
|
|
if (line.startsWith(indent)) // strip indentation equal to DT (section header)
|
|
current.ddoc ~= line[indent.length .. $];
|
|
else
|
|
current.ddoc ~= line;
|
|
}
|
|
}
|
|
}
|
|
if (!foundTerminator)
|
|
throw new Exception("Could not find '$(SPEC_SUBNAV_PREV_NEXT' line in pragma.dd, format of the file has changed and code needs to be adjusted.");
|
|
|
|
return completions;
|
|
}
|
|
|
|
ConstantCompletion[] parseTraits(string ddoc)
|
|
{
|
|
ConstantCompletion[] completions;
|
|
|
|
bool foundTerminator;
|
|
|
|
ConstantCompletion current;
|
|
bool inInlineCode;
|
|
bool seekingToFirst = true;
|
|
string indent;
|
|
|
|
void addCurrent()
|
|
{
|
|
current.ddoc = current.ddoc.strip;
|
|
if (seekingToFirst || current == ConstantCompletion.init)
|
|
{
|
|
current = ConstantCompletion.init;
|
|
return;
|
|
}
|
|
completions ~= current;
|
|
current = ConstantCompletion.init;
|
|
}
|
|
|
|
foreach (line; ddoc.lineSplitter!(KeepTerminator.yes))
|
|
{
|
|
if (line.stripLeft.startsWith("$(SPEC_SUBNAV_PREV_NEXT"))
|
|
{
|
|
addCurrent();
|
|
foundTerminator = true;
|
|
break;
|
|
}
|
|
else if (line.canFind("$(GNAME "))
|
|
{
|
|
addCurrent();
|
|
ptrdiff_t i = line.indexOf("$(GNAME ");
|
|
while (i != -1)
|
|
{
|
|
auto closing = line.indexOfAny("),", i);
|
|
current.identifiers ~= line[i + "$(GNAME ".length .. closing].strip;
|
|
i = line.indexOf("$(GNAME ", closing);
|
|
}
|
|
seekingToFirst = false;
|
|
|
|
if (current.identifiers.length == 1 && current.identifiers[0][0].isUpper)
|
|
seekingToFirst = true; // not considering capitalized identifiers traits (TraitsKeyword, TraitsExpression, etc.)
|
|
}
|
|
else if (!seekingToFirst)
|
|
{
|
|
if (line.startsWith("---"))
|
|
inInlineCode = !inInlineCode;
|
|
if (inInlineCode)
|
|
current.ddoc ~= line;
|
|
else
|
|
{
|
|
if (!current.ddoc.length)
|
|
indent = line[0 .. $ - line.stripLeft.length];
|
|
if (line.startsWith(indent))
|
|
current.ddoc ~= line[indent.length .. $];
|
|
else
|
|
current.ddoc ~= line;
|
|
}
|
|
}
|
|
}
|
|
if (!foundTerminator)
|
|
throw new Exception("Could not find '$(SPEC_SUBNAV_PREV_NEXT' line in traits.dd, format of the file has changed and code needs to be adjusted.");
|
|
|
|
return completions;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
immutable pragmaDDoc = readText("pragma.dd");
|
|
immutable traitsDDoc = readText("traits.dd");
|
|
|
|
auto pragmas = parsePragmas(pragmaDDoc);
|
|
auto traits = parseTraits(traitsDDoc);
|
|
|
|
string part1 = `//
|
|
//
|
|
// this file is auto generated by constants-gen/generator.d, do not edit manually.
|
|
//
|
|
//
|
|
|
|
module dcd.common.constants2;
|
|
|
|
import dcd.common.constants : ConstantCompletion;
|
|
|
|
/**
|
|
* Pragma arguments
|
|
*/
|
|
immutable ConstantCompletion[] pragmas = [
|
|
// generated from pragma.dd`;
|
|
string part2 = `];
|
|
|
|
/**
|
|
* Traits arguments
|
|
*/
|
|
immutable ConstantCompletion[] traits = [
|
|
// generated from traits.dd`;
|
|
|
|
string part3 = "];";
|
|
|
|
auto file = File("../src/dcd/common/constants2.d", "w");
|
|
file.writeln(part1);
|
|
foreach (pragma_; pragmas.sorted)
|
|
file.writeln('\t', pragma_, ",");
|
|
file.writeln(part2);
|
|
foreach (trait; traits.sorted)
|
|
file.writeln('\t', trait, ",");
|
|
file.writeln(part3);
|
|
}
|
|
|
|
auto sorted(T)(T range)
|
|
{
|
|
return range.map!(a => a.identifiers.map!(identifier => SingleConstantCompletion(identifier,
|
|
a.ddoc))).join.sort!"a.identifier < b.identifier";
|
|
}
|