aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sdlang/util.d
diff options
context:
space:
mode:
Diffstat (limited to 'src/sdlang/util.d')
-rw-r--r--src/sdlang/util.d126
1 files changed, 121 insertions, 5 deletions
diff --git a/src/sdlang/util.d b/src/sdlang/util.d
index 329e387..d192ea2 100644
--- a/src/sdlang/util.d
+++ b/src/sdlang/util.d
@@ -4,10 +4,14 @@
module sdlang.util;
import std.algorithm;
+import std.array;
+import std.conv;
import std.datetime;
+import std.range;
import std.stdio;
import std.string;
+import sdlang.exception;
import sdlang.token;
enum sdlangVersion = "0.9.1";
@@ -26,14 +30,14 @@ struct Location
int line; /// Zero-indexed
int col; /// Zero-indexed, Tab counts as 1
size_t index; /// Index into the source
-
+
this(int line, int col, int index)
{
this.line = line;
this.col = col;
this.index = index;
}
-
+
this(string file, int line, int col, int index)
{
this.file = file;
@@ -41,12 +45,106 @@ struct Location
this.col = col;
this.index = index;
}
-
+
+ /// Convert to string. Optionally takes output range as a sink.
+ string toString()
+ {
+ Appender!string sink;
+ this.toString(sink);
+ return sink.data;
+ }
+
+ ///ditto
+ void toString(Sink)(ref Sink sink) if(isOutputRange!(Sink,char))
+ {
+ sink.put(file);
+ sink.put("(");
+ sink.put(to!string(line+1));
+ sink.put(":");
+ sink.put(to!string(col+1));
+ sink.put(")");
+ }
+}
+
+struct FullName
+{
+ string namespace;
+ string name;
+
+ /// Convert to string. Optionally takes output range as a sink.
string toString()
{
- return "%s(%s:%s)".format(file, line+1, col+1);
+ if(namespace == "")
+ return name;
+
+ Appender!string sink;
+ this.toString(sink);
+ return sink.data;
+ }
+
+ ///ditto
+ void toString(Sink)(ref Sink sink) if(isOutputRange!(Sink,char))
+ {
+ if(namespace != "")
+ {
+ sink.put(namespace);
+ sink.put(":");
+ }
+
+ sink.put(name);
+ }
+
+ ///
+ static string combine(string namespace, string name)
+ {
+ return FullName(namespace, name).toString();
+ }
+ ///
+ @("FullName.combine example")
+ unittest
+ {
+ assert(FullName.combine("", "name") == "name");
+ assert(FullName.combine("*", "name") == "*:name");
+ assert(FullName.combine("namespace", "name") == "namespace:name");
+ }
+
+ ///
+ static FullName parse(string fullName)
+ {
+ FullName result;
+
+ auto parts = fullName.findSplit(":");
+ if(parts[1] == "") // No colon
+ {
+ result.namespace = "";
+ result.name = parts[0];
+ }
+ else
+ {
+ result.namespace = parts[0];
+ result.name = parts[2];
+ }
+
+ return result;
+ }
+ ///
+ @("FullName.parse example")
+ unittest
+ {
+ assert(FullName.parse("name") == FullName("", "name"));
+ assert(FullName.parse("*:name") == FullName("*", "name"));
+ assert(FullName.parse("namespace:name") == FullName("namespace", "name"));
+ }
+
+ /// Throws with appropriate message if this.name is "*".
+ /// Wildcards are only supported for namespaces, not names.
+ void ensureNoWildcardName(string extaMsg = null)
+ {
+ if(name == "*")
+ throw new ArgumentException(`Wildcards ("*") only allowed for namespaces, not names. `~extaMsg);
}
}
+struct Foo { string foo; }
void removeIndex(E)(ref E[] arr, ptrdiff_t index)
{
@@ -79,6 +177,24 @@ string toString(TypeInfo ti)
else if(ti == typeid( Duration )) return "Duration";
else if(ti == typeid( ubyte[] )) return "ubyte[]";
else if(ti == typeid( typeof(null) )) return "null";
-
+
return "{unknown}";
}
+
+enum BOM {
+ UTF8, /// UTF-8
+ UTF16LE, /// UTF-16 (little-endian)
+ UTF16BE, /// UTF-16 (big-endian)
+ UTF32LE, /// UTF-32 (little-endian)
+ UTF32BE, /// UTF-32 (big-endian)
+}
+
+enum NBOM = __traits(allMembers, BOM).length;
+immutable ubyte[][NBOM] ByteOrderMarks =
+[
+ [0xEF, 0xBB, 0xBF], //UTF8
+ [0xFF, 0xFE], //UTF16LE
+ [0xFE, 0xFF], //UTF16BE
+ [0xFF, 0xFE, 0x00, 0x00], //UTF32LE
+ [0x00, 0x00, 0xFE, 0xFF] //UTF32BE
+];