Cleaned up exceptions and their messages.
Some minor dog fixes.
This commit is contained in:
parent
009017eef0
commit
8ad650e089
Binary file not shown.
|
@ -105,6 +105,11 @@
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Construct a Dumper writing to a stream. This is useful to e.g. write to memory.</p>
|
<dd><p>Construct a Dumper writing to a stream. This is useful to e.g. write to memory.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt class="d_decl">@property void <a name="name"></a><span class="ddoc_psymbol">name</span>(string <a name="name"></a><span class="ddoc_psymbol">name</span>);
|
||||||
|
</dt>
|
||||||
|
<dd><p>Set stream name. Used in debugging messages.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">void <a name="resolver"></a><span class="ddoc_psymbol">resolver</span>(Resolver <a name="resolver"></a><span class="ddoc_psymbol">resolver</span>);
|
<dt class="d_decl">void <a name="resolver"></a><span class="ddoc_psymbol">resolver</span>(Resolver <a name="resolver"></a><span class="ddoc_psymbol">resolver</span>);
|
||||||
</dt>
|
</dt>
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
<dl><dt class="d_decl">this(string <b>msg</b>, string <b>file</b> = __FILE__, int <b>line</b> = __LINE__);
|
<dl><dt class="d_decl">this(string <b>msg</b>, string <b>file</b> = __FILE__, int <b>line</b> = __LINE__);
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Construct a YAMLException with specified message, and position where it was thrown.</p>
|
<dd><p>Construct a YAMLException with specified message and position where it was thrown.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>string <b>filename</b></td>
|
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>string <b>filename</b></td>
|
||||||
<td valign=top>Name of the file to load from.</td></tr>
|
<td valign=top>Name of the file to load from.</td></tr>
|
||||||
</table></div>
|
</table></div>
|
||||||
<b>Throws:</b><div class="pbr">YAMLException if the file could not be opened or read from.</div>
|
<b>Throws:</b><div class="pbr">YAMLException if the file could not be opened or read.</div>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">this(Stream <b>stream</b>);
|
<dt class="d_decl">this(Stream <b>stream</b>);
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>Stream <b>stream</b></td>
|
<b>Parameters:</b><div class="pbr"><table class=parms><tr><td valign=top>Stream <b>stream</b></td>
|
||||||
<td valign=top>Stream to read from. Must be readable.</td></tr>
|
<td valign=top>Stream to read from. Must be readable.</td></tr>
|
||||||
</table></div>
|
</table></div>
|
||||||
<b>Throws:</b><div class="pbr">YAMLException if <b>stream</b> could not be read from.</div>
|
<b>Throws:</b><div class="pbr">YAMLException if <b>stream</b> could not be read.</div>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">@property void <a name="name"></a><span class="ddoc_psymbol">name</span>(string <a name="name"></a><span class="ddoc_psymbol">name</span>);
|
<dt class="d_decl">@property void <a name="name"></a><span class="ddoc_psymbol">name</span>(string <a name="name"></a><span class="ddoc_psymbol">name</span>);
|
||||||
|
@ -136,7 +136,7 @@
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Load single YAML document.
|
<dd><p>Load single YAML document.
|
||||||
</p>
|
</p>
|
||||||
<p>If none or more than one YAML document is found, this will throw a YAMLException.
|
<p>If none or more than one YAML document is found, this throws a YAMLException.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<b>Returns:</b><div class="pbr">Root node of the document.
|
<b>Returns:</b><div class="pbr">Root node of the document.
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
<b>Returns:</b><div class="pbr">Array of root nodes of all documents in the file/stream.
|
<b>Returns:</b><div class="pbr">Array of root nodes of all documents in the file/stream.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<b>Throws:</b><div class="pbr">YAMLException on a YAML parsing error.</div>
|
<b>Throws:</b><div class="pbr">YAMLException on a parsing error.</div>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="d_decl">int <a name="opApply"></a><span class="ddoc_psymbol">opApply</span>(int delegate(ref Node) <b>dg</b>);
|
<dt class="d_decl">int <a name="opApply"></a><span class="ddoc_psymbol">opApply</span>(int delegate(ref Node) <b>dg</b>);
|
||||||
|
|
|
@ -69,13 +69,13 @@
|
||||||
</dt>
|
</dt>
|
||||||
<dd><p>Add a function to represent nodes with a specific data type.
|
<dd><p>Add a function to represent nodes with a specific data type.
|
||||||
</p>
|
</p>
|
||||||
<p>The representer function takes a reference to a Node storing the data
|
<p>The representer function takes references to a Node storing the data
|
||||||
type and to the Representer. It returns the represented node and may
|
type and to the Representer. It returns the represented node and may
|
||||||
throw a RepresenterException. See the example for more information.
|
throw a RepresenterException. See the example for more information.
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
Only one function may be specified for one data type. Default data
|
Only one function may be specified for one data type. Default data
|
||||||
types already have representer functions unless disabled in these
|
types already have representer functions unless disabled in the
|
||||||
Representer constructor.
|
Representer constructor.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -138,7 +138,7 @@ struct appears in Phobos.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 17, 2011.
|
Last updated on Oct 18, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 17, 2011.
|
Last updated on Oct 18, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 17, 2011.
|
Last updated on Oct 18, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -369,7 +369,7 @@ directory of the D:YAML package.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 17, 2011.
|
Last updated on Oct 18, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -237,7 +237,7 @@ example in the <tt class="docutils literal"><span class="pre">example/getting_st
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 17, 2011.
|
Last updated on Oct 18, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -330,7 +330,7 @@ Some of these might change in the future (especially !!map and !!set).</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
© Copyright 2011, Ferdinand Majerech. Based on PyYAML http://www.pyyaml.org by Kirill Simonov.
|
||||||
Last updated on Oct 17, 2011.
|
Last updated on Oct 18, 2011.
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.7.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -26,7 +26,7 @@ import dyaml.resolver;
|
||||||
|
|
||||||
package:
|
package:
|
||||||
/**
|
/**
|
||||||
* Marked exception thrown at composer errors.
|
* Exception thrown at composer errors.
|
||||||
*
|
*
|
||||||
* See_Also: MarkedYAMLException
|
* See_Also: MarkedYAMLException
|
||||||
*/
|
*/
|
||||||
|
@ -113,7 +113,7 @@ final class Composer
|
||||||
//Ensure that the stream contains no more documents.
|
//Ensure that the stream contains no more documents.
|
||||||
enforce(parser_.checkEvent(EventID.StreamEnd),
|
enforce(parser_.checkEvent(EventID.StreamEnd),
|
||||||
new ComposerException("Expected single document in the stream, "
|
new ComposerException("Expected single document in the stream, "
|
||||||
"but found another document: ",
|
"but found another document.",
|
||||||
parser_.getEvent().startMark));
|
parser_.getEvent().startMark));
|
||||||
|
|
||||||
//Drop the STREAM-END event.
|
//Drop the STREAM-END event.
|
||||||
|
@ -246,6 +246,18 @@ final class Composer
|
||||||
{
|
{
|
||||||
Node.Pair[] result;
|
Node.Pair[] result;
|
||||||
|
|
||||||
|
void error(Node node)
|
||||||
|
{
|
||||||
|
//this is Composer, but the code is related to Constructor.
|
||||||
|
throw new ConstructorException("While constructing a mapping, "
|
||||||
|
"expected a mapping or a list of "
|
||||||
|
"mappings for merging, but found: "
|
||||||
|
~ node.type.toString ~
|
||||||
|
" NOTE: line/column shows topmost parent "
|
||||||
|
"to which the content is being merged",
|
||||||
|
startMark, endMark);
|
||||||
|
}
|
||||||
|
|
||||||
if(root.isMapping)
|
if(root.isMapping)
|
||||||
{
|
{
|
||||||
Node[] toMerge;
|
Node[] toMerge;
|
||||||
|
@ -259,32 +271,15 @@ final class Composer
|
||||||
merge(result, flatten(node, startMark, endMark));
|
merge(result, flatten(node, startMark, endMark));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(root.isSequence)
|
//Must be a sequence of mappings.
|
||||||
|
else if(root.isSequence) foreach(ref Node node; root)
|
||||||
{
|
{
|
||||||
//Must be a sequence of mappings.
|
if(!node.isType!(Node.Pair[])){error(node);}
|
||||||
foreach(ref Node node; root)
|
merge(result, flatten(node, startMark, endMark));
|
||||||
{
|
|
||||||
//this is Composer, but the code is related to constructor
|
|
||||||
enforce(node.isType!(Node.Pair[]),
|
|
||||||
new ConstructorException("While constructing a mapping, " ~
|
|
||||||
"expected a mapping for merging, but found"
|
|
||||||
~ node.type.toString ~
|
|
||||||
"NOTE: line/column shows topmost parent "
|
|
||||||
"to which the content is being merged",
|
|
||||||
startMark, endMark));
|
|
||||||
merge(result, flatten(node, startMark, endMark));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//this is Composer, but the code is related to constructor
|
error(root);
|
||||||
throw new ConstructorException("While constructing a mapping, " ~
|
|
||||||
"expected a mapping or a list of mappings for "
|
|
||||||
"merging, but found: "
|
|
||||||
~ root.type.toString ~
|
|
||||||
"NOTE: line/column shows topmost parent "
|
|
||||||
"to which the content is being merged",
|
|
||||||
startMark, endMark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -45,11 +45,13 @@ class ConstructorException : YAMLException
|
||||||
*/
|
*/
|
||||||
this(string msg, Mark start, Mark end, string file = __FILE__, int line = __LINE__)
|
this(string msg, Mark start, Mark end, string file = __FILE__, int line = __LINE__)
|
||||||
{
|
{
|
||||||
super(msg ~ "\nstart:" ~ start.toString() ~ "\nend:" ~ end.toString(),
|
super(msg ~ "\nstart: " ~ start.toString() ~ "\nend: " ~ end.toString(),
|
||||||
file, line);
|
file, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private alias ConstructorException Error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs YAML values.
|
* Constructs YAML values.
|
||||||
*
|
*
|
||||||
|
@ -177,8 +179,7 @@ final class Constructor
|
||||||
if(is(T : string) || is(T == Node[]) || is(T == Node.Pair[]))
|
if(is(T : string) || is(T == Node[]) || is(T == Node.Pair[]))
|
||||||
{
|
{
|
||||||
enforce((tag in *delegates!T) !is null,
|
enforce((tag in *delegates!T) !is null,
|
||||||
new ConstructorException("Could not determine a constructor for tag "
|
new Error("No constructor function for tag " ~ tag.get(), start, end));
|
||||||
~ tag.get(), start, end));
|
|
||||||
Node node = Node(value);
|
Node node = Node(value);
|
||||||
return Node.rawNode((*delegates!T)[tag](start, end, node), start, tag);
|
return Node.rawNode((*delegates!T)[tag](start, end, node), start, tag);
|
||||||
}
|
}
|
||||||
|
@ -234,7 +235,7 @@ bool constructBool(Mark start, Mark end, ref Node node)
|
||||||
string value = node.get!string().toLower();
|
string value = node.get!string().toLower();
|
||||||
if(["yes", "true", "on"].canFind(value)) {return true;}
|
if(["yes", "true", "on"].canFind(value)) {return true;}
|
||||||
if(["no", "false", "off"].canFind(value)){return false;}
|
if(["no", "false", "off"].canFind(value)){return false;}
|
||||||
throw new ConstructorException("Unable to parse boolean value: " ~ value, start, end);
|
throw new Error("Unable to parse boolean value: " ~ value, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Construct an integer (long) node.
|
///Construct an integer (long) node.
|
||||||
|
@ -248,8 +249,7 @@ long constructLong(Mark start, Mark end, ref Node node)
|
||||||
value = value[1 .. $];
|
value = value[1 .. $];
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(value != "", new ConstructorException("Unable to parse float value: " ~ value,
|
enforce(value != "", new Error("Unable to parse float value: " ~ value, start, end));
|
||||||
start, end));
|
|
||||||
|
|
||||||
long result;
|
long result;
|
||||||
try
|
try
|
||||||
|
@ -279,7 +279,7 @@ long constructLong(Mark start, Mark end, ref Node node)
|
||||||
}
|
}
|
||||||
catch(ConvException e)
|
catch(ConvException e)
|
||||||
{
|
{
|
||||||
throw new ConstructorException("Unable to parse integer value: " ~ value, start, end);
|
throw new Error("Unable to parse integer value: " ~ value, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -318,7 +318,7 @@ real constructReal(Mark start, Mark end, ref Node node)
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(value != "" && value != "nan" && value != "inf" && value != "-inf",
|
enforce(value != "" && value != "nan" && value != "inf" && value != "-inf",
|
||||||
new ConstructorException("Unable to parse float value: " ~ value, start, end));
|
new Error("Unable to parse float value: " ~ value, start, end));
|
||||||
|
|
||||||
real result;
|
real result;
|
||||||
try
|
try
|
||||||
|
@ -344,7 +344,7 @@ real constructReal(Mark start, Mark end, ref Node node)
|
||||||
}
|
}
|
||||||
catch(ConvException e)
|
catch(ConvException e)
|
||||||
{
|
{
|
||||||
throw new ConstructorException("Unable to parse float value: " ~ value, start, end);
|
throw new Error("Unable to parse float value: " ~ value, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -386,13 +386,13 @@ ubyte[] constructBinary(Mark start, Mark end, ref Node node)
|
||||||
try{return Base64.decode(value.removechars("\n"));}
|
try{return Base64.decode(value.removechars("\n"));}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
throw new ConstructorException("Unable to decode base64 value: " ~ e.msg, start,
|
throw new Error("Unable to decode base64 value: " ~ e.msg,
|
||||||
end);
|
start, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(UtfException e)
|
catch(UtfException e)
|
||||||
{
|
{
|
||||||
throw new ConstructorException("Unable to decode base64 value: " ~ e.msg, start, end);
|
throw new Error("Unable to decode base64 value: " ~ e.msg, start, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unittest
|
unittest
|
||||||
|
@ -419,8 +419,8 @@ SysTime constructTimestamp(Mark start, Mark end, ref Node node)
|
||||||
//First, get year, month and day.
|
//First, get year, month and day.
|
||||||
auto matches = match(value, YMDRegexp);
|
auto matches = match(value, YMDRegexp);
|
||||||
|
|
||||||
enforce(!matches.empty, new ConstructorException("Unable to parse timestamp value: "
|
enforce(!matches.empty,
|
||||||
~ value, start, end));
|
new Error("Unable to parse timestamp value: " ~ value, start, end));
|
||||||
|
|
||||||
auto captures = matches.front.captures;
|
auto captures = matches.front.captures;
|
||||||
const year = to!int(captures[1]);
|
const year = to!int(captures[1]);
|
||||||
|
@ -467,13 +467,11 @@ SysTime constructTimestamp(Mark start, Mark end, ref Node node)
|
||||||
}
|
}
|
||||||
catch(ConvException e)
|
catch(ConvException e)
|
||||||
{
|
{
|
||||||
throw new ConstructorException("Unable to parse timestamp value: " ~ value ~
|
throw new Error("Unable to parse timestamp value " ~ value ~ " : " ~ e.msg, start, end);
|
||||||
" Reason: " ~ e.msg, start, end);
|
|
||||||
}
|
}
|
||||||
catch(DateTimeException e)
|
catch(DateTimeException e)
|
||||||
{
|
{
|
||||||
throw new ConstructorException("Invalid timestamp value: " ~ value ~
|
throw new Error("Invalid timestamp value " ~ value ~ " : " ~ e.msg, start, end);
|
||||||
" Reason: " ~ e.msg, start, end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false, "This code should never be reached");
|
assert(false, "This code should never be reached");
|
||||||
|
@ -520,9 +518,8 @@ Node.Pair[] getPairs(string type, Mark start, Mark end, Node[] nodes)
|
||||||
foreach(ref node; nodes)
|
foreach(ref node; nodes)
|
||||||
{
|
{
|
||||||
enforce(node.isMapping && node.length == 1,
|
enforce(node.isMapping && node.length == 1,
|
||||||
new ConstructorException("While constructing " ~ type ~
|
new Error("While constructing " ~ type ~
|
||||||
", expected a mapping with single element,", start,
|
", expected a mapping with single element", start, end));
|
||||||
end));
|
|
||||||
|
|
||||||
pairs ~= node.get!(Node.Pair[]);
|
pairs ~= node.get!(Node.Pair[]);
|
||||||
}
|
}
|
||||||
|
@ -542,8 +539,7 @@ Node.Pair[] constructOrderedMap(Mark start, Mark end, ref Node node)
|
||||||
foreach(ref pair; pairs)
|
foreach(ref pair; pairs)
|
||||||
{
|
{
|
||||||
enforce((pair.key in map) is null,
|
enforce((pair.key in map) is null,
|
||||||
new ConstructorException("Found a duplicate entry in an ordered map",
|
new Error("Duplicate entry in an ordered map", start, end));
|
||||||
start, end));
|
|
||||||
map[pair.key] = true;
|
map[pair.key] = true;
|
||||||
}
|
}
|
||||||
clear(map);
|
clear(map);
|
||||||
|
@ -611,7 +607,7 @@ Node[] constructSet(Mark start, Mark end, ref Node node)
|
||||||
foreach(ref pair; pairs)
|
foreach(ref pair; pairs)
|
||||||
{
|
{
|
||||||
enforce((pair.key in map) is null,
|
enforce((pair.key in map) is null,
|
||||||
new ConstructorException("Found a duplicate entry in a set", start, end));
|
new Error("Duplicate entry in a set", start, end));
|
||||||
map[pair.key] = 0;
|
map[pair.key] = 0;
|
||||||
nodes ~= pair.key;
|
nodes ~= pair.key;
|
||||||
}
|
}
|
||||||
|
@ -679,7 +675,7 @@ Node.Pair[] constructMap(Mark start, Mark end, ref Node node)
|
||||||
foreach(ref pair; pairs)
|
foreach(ref pair; pairs)
|
||||||
{
|
{
|
||||||
enforce((pair.key in map) is null,
|
enforce((pair.key in map) is null,
|
||||||
new ConstructorException("Found a duplicate entry in a map", start, end));
|
new Error("Duplicate entry in a map", start, end));
|
||||||
map[pair.key] = true;
|
map[pair.key] = true;
|
||||||
}
|
}
|
||||||
return pairs;
|
return pairs;
|
||||||
|
|
|
@ -140,6 +140,9 @@ struct Dumper
|
||||||
///Always write document end?
|
///Always write document end?
|
||||||
bool explicitEnd_ = false;
|
bool explicitEnd_ = false;
|
||||||
|
|
||||||
|
///Name of the output file or stream, used in error messages.
|
||||||
|
string name_ = "<unknown>";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@disable this();
|
@disable this();
|
||||||
|
|
||||||
|
@ -152,10 +155,12 @@ struct Dumper
|
||||||
*/
|
*/
|
||||||
this(string filename)
|
this(string filename)
|
||||||
{
|
{
|
||||||
|
name_ = filename;
|
||||||
try{this(new File(filename, FileMode.OutNew));}
|
try{this(new File(filename, FileMode.OutNew));}
|
||||||
catch(StreamException e)
|
catch(StreamException e)
|
||||||
{
|
{
|
||||||
throw new YAMLException("Unable to use file for YAML dumping " ~ filename ~ " : " ~ e.msg);
|
throw new YAMLException("Unable to open file " ~ filename ~
|
||||||
|
" for YAML dumping: " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +182,12 @@ struct Dumper
|
||||||
YAMLVersion_ = null;
|
YAMLVersion_ = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Set stream _name. Used in debugging messages.
|
||||||
|
@property void name(string name)
|
||||||
|
{
|
||||||
|
name_ = name;
|
||||||
|
}
|
||||||
|
|
||||||
///Specify custom Resolver to use.
|
///Specify custom Resolver to use.
|
||||||
void resolver(Resolver resolver)
|
void resolver(Resolver resolver)
|
||||||
{
|
{
|
||||||
|
@ -312,7 +323,8 @@ struct Dumper
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
throw new YAMLException("Unable to dump YAML: " ~ e.msg);
|
throw new YAMLException("Unable to dump YAML to stream "
|
||||||
|
~ name_ ~ " : " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +348,8 @@ struct Dumper
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
throw new YAMLException("Unable to emit YAML: " ~ e.msg);
|
throw new YAMLException("Unable to emit YAML to stream "
|
||||||
|
~ name_ ~ " : " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ class EmitterException : YAMLException
|
||||||
mixin ExceptionCtors;
|
mixin ExceptionCtors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private alias EmitterException Error;
|
||||||
|
|
||||||
//Stores results of analysis of a scalar, determining e.g. what scalar style to use.
|
//Stores results of analysis of a scalar, determining e.g. what scalar style to use.
|
||||||
align(4) struct ScalarAnalysis
|
align(4) struct ScalarAnalysis
|
||||||
{
|
{
|
||||||
|
@ -230,7 +232,7 @@ struct Emitter
|
||||||
}
|
}
|
||||||
catch(WriteException e)
|
catch(WriteException e)
|
||||||
{
|
{
|
||||||
throw new EmitterException("Unable to write to stream");
|
throw new Error("Unable to write to stream: " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +295,7 @@ struct Emitter
|
||||||
bool eventTypeIs(in EventID id) const
|
bool eventTypeIs(in EventID id) const
|
||||||
{
|
{
|
||||||
enforce(!event_.isNull,
|
enforce(!event_.isNull,
|
||||||
new EmitterException("Expected an event, but no event is available."));
|
new Error("Expected an event, but no event is available."));
|
||||||
return event_.id == id;
|
return event_.id == id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,8 +309,7 @@ struct Emitter
|
||||||
void expectStreamStart()
|
void expectStreamStart()
|
||||||
{
|
{
|
||||||
enforce(eventTypeIs(EventID.StreamStart),
|
enforce(eventTypeIs(EventID.StreamStart),
|
||||||
new EmitterException("Expected StreamStart, but got "
|
new Error("Expected StreamStart, but got " ~ event_.idString));
|
||||||
~ to!string(event_.id)));
|
|
||||||
|
|
||||||
encoding_ = event_.encoding;
|
encoding_ = event_.encoding;
|
||||||
writeStreamStart();
|
writeStreamStart();
|
||||||
|
@ -318,7 +319,7 @@ struct Emitter
|
||||||
///Expect nothing, throwing if we still have something.
|
///Expect nothing, throwing if we still have something.
|
||||||
void expectNothing()
|
void expectNothing()
|
||||||
{
|
{
|
||||||
throw new EmitterException("Expected nothing, but got " ~ to!string(event_.id));
|
throw new Error("Expected nothing, but got " ~ event_.idString);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Document handlers.
|
//Document handlers.
|
||||||
|
@ -327,8 +328,8 @@ struct Emitter
|
||||||
void expectDocumentStart(bool first)()
|
void expectDocumentStart(bool first)()
|
||||||
{
|
{
|
||||||
enforce(eventTypeIs(EventID.DocumentStart) || eventTypeIs(EventID.StreamEnd),
|
enforce(eventTypeIs(EventID.DocumentStart) || eventTypeIs(EventID.StreamEnd),
|
||||||
new EmitterException("Expected DocumentStart or StreamEnd, but got "
|
new Error("Expected DocumentStart or StreamEnd, but got "
|
||||||
~ to!string(event_.id)));
|
~ event_.idString));
|
||||||
|
|
||||||
if(event_.id == EventID.DocumentStart)
|
if(event_.id == EventID.DocumentStart)
|
||||||
{
|
{
|
||||||
|
@ -386,8 +387,7 @@ struct Emitter
|
||||||
void expectDocumentEnd()
|
void expectDocumentEnd()
|
||||||
{
|
{
|
||||||
enforce(eventTypeIs(EventID.DocumentEnd),
|
enforce(eventTypeIs(EventID.DocumentEnd),
|
||||||
new EmitterException("Expected DocumentEnd, but got "
|
new Error("Expected DocumentEnd, but got " ~ event_.idString));
|
||||||
~ to!string(event_.id)));
|
|
||||||
|
|
||||||
writeIndent();
|
writeIndent();
|
||||||
if(event_.explicitDocument)
|
if(event_.explicitDocument)
|
||||||
|
@ -450,17 +450,15 @@ struct Emitter
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new EmitterException("Expected Alias, Scalar, SequenceStart "
|
throw new Error("Expected Alias, Scalar, SequenceStart or "
|
||||||
"or MappingStart, but got: "
|
"MappingStart, but got: " ~ event_.idString);
|
||||||
~ to!string(event_.id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///Handle an alias.
|
///Handle an alias.
|
||||||
void expectAlias()
|
void expectAlias()
|
||||||
{
|
{
|
||||||
enforce(!event_.anchor.isNull(),
|
enforce(!event_.anchor.isNull(), new Error("Anchor is not specified for alias"));
|
||||||
new EmitterException("Anchor is not specified for alias"));
|
|
||||||
processAnchor("*");
|
processAnchor("*");
|
||||||
state_ = popState();
|
state_ = popState();
|
||||||
}
|
}
|
||||||
|
@ -785,7 +783,7 @@ struct Emitter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(!tag.isNull(), new EmitterException("Tag is not specified"));
|
enforce(!tag.isNull(), new Error("Tag is not specified"));
|
||||||
if(preparedTag_ is null){preparedTag_ = prepareTag(tag);}
|
if(preparedTag_ is null){preparedTag_ = prepareTag(tag);}
|
||||||
if(preparedTag_ !is null && preparedTag_ != "")
|
if(preparedTag_ !is null && preparedTag_ != "")
|
||||||
{
|
{
|
||||||
|
@ -841,7 +839,7 @@ struct Emitter
|
||||||
static string prepareVersion(in string YAMLVersion)
|
static string prepareVersion(in string YAMLVersion)
|
||||||
{
|
{
|
||||||
enforce(YAMLVersion.split(".")[0] == "1",
|
enforce(YAMLVersion.split(".")[0] == "1",
|
||||||
new EmitterException("Unsupported YAML version: " ~ YAMLVersion));
|
new Error("Unsupported YAML version: " ~ YAMLVersion));
|
||||||
return YAMLVersion;
|
return YAMLVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,13 +859,13 @@ struct Emitter
|
||||||
static string prepareTagHandle(in string handle)
|
static string prepareTagHandle(in string handle)
|
||||||
{
|
{
|
||||||
enforce(handle !is null && handle != "",
|
enforce(handle !is null && handle != "",
|
||||||
new EmitterException("Tag handle must not be empty"));
|
new Error("Tag handle must not be empty"));
|
||||||
|
|
||||||
if(handle.length > 1) foreach(const dchar c; handle[1 .. $ - 1])
|
if(handle.length > 1) foreach(const dchar c; handle[1 .. $ - 1])
|
||||||
{
|
{
|
||||||
enforce(isAlphaNum(c) || "-_".canFind(c),
|
enforce(isAlphaNum(c) || "-_".canFind(c),
|
||||||
new EmitterException("Invalid character: " ~ to!string(c) ~
|
new Error("Invalid character: " ~ to!string(c) ~
|
||||||
" in tag handle " ~ handle));
|
" in tag handle " ~ handle));
|
||||||
}
|
}
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -876,7 +874,7 @@ struct Emitter
|
||||||
static string prepareTagPrefix(in string prefix)
|
static string prepareTagPrefix(in string prefix)
|
||||||
{
|
{
|
||||||
enforce(prefix !is null && prefix != "",
|
enforce(prefix !is null && prefix != "",
|
||||||
new EmitterException("Tag prefix must not be empty"));
|
new Error("Tag prefix must not be empty"));
|
||||||
|
|
||||||
auto appender = appender!string();
|
auto appender = appender!string();
|
||||||
const offset = prefix[0] == '!' ? 1 : 0;
|
const offset = prefix[0] == '!' ? 1 : 0;
|
||||||
|
@ -906,7 +904,7 @@ struct Emitter
|
||||||
///Prepare tag for output.
|
///Prepare tag for output.
|
||||||
string prepareTag(in Tag tag)
|
string prepareTag(in Tag tag)
|
||||||
{
|
{
|
||||||
enforce(!tag.isNull(), new EmitterException("Tag must not be empty"));
|
enforce(!tag.isNull(), new Error("Tag must not be empty"));
|
||||||
|
|
||||||
string tagString = tag.get;
|
string tagString = tag.get;
|
||||||
if(tagString == "!"){return tagString;}
|
if(tagString == "!"){return tagString;}
|
||||||
|
@ -954,13 +952,12 @@ struct Emitter
|
||||||
static string prepareAnchor(in Anchor anchor)
|
static string prepareAnchor(in Anchor anchor)
|
||||||
{
|
{
|
||||||
enforce(!anchor.isNull() && anchor.get != "",
|
enforce(!anchor.isNull() && anchor.get != "",
|
||||||
new EmitterException("Anchor must not be empty"));
|
new Error("Anchor must not be empty"));
|
||||||
const str = anchor.get;
|
const str = anchor.get;
|
||||||
foreach(const dchar c; str)
|
foreach(const dchar c; str)
|
||||||
{
|
{
|
||||||
enforce(isAlphaNum(c) || "-_".canFind(c),
|
enforce(isAlphaNum(c) || "-_".canFind(c),
|
||||||
new EmitterException("Invalid character: " ~ to!string(c) ~
|
new Error("Invalid character: " ~ to!string(c) ~ " in anchor: " ~ str));
|
||||||
" in anchor: " ~ str));
|
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -1150,8 +1147,7 @@ struct Emitter
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(stream_.write(bom) == bom.length,
|
enforce(stream_.write(bom) == bom.length, new Error("Unable to write to stream"));
|
||||||
new EmitterException("Unable to write to stream"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///End the YAML stream.
|
///End the YAML stream.
|
||||||
|
|
|
@ -83,6 +83,9 @@ struct Event
|
||||||
{
|
{
|
||||||
return id == EventID.Invalid;
|
return id == EventID.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Get string representation of the token ID.
|
||||||
|
@property string idString() const {return to!string(id);}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,19 +16,11 @@ import std.string;
|
||||||
///Base class for all exceptions thrown by D:YAML.
|
///Base class for all exceptions thrown by D:YAML.
|
||||||
class YAMLException : Exception
|
class YAMLException : Exception
|
||||||
{
|
{
|
||||||
public:
|
///Construct a YAMLException with specified message and position where it was thrown.
|
||||||
///Construct a YAMLException with specified message, and position where it was thrown.
|
public this(string msg, string file = __FILE__, int line = __LINE__)
|
||||||
this(string msg, string file = __FILE__, int line = __LINE__)
|
{
|
||||||
{
|
super(msg, file, line);
|
||||||
super(msg, file, line);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
package:
|
|
||||||
//Set name of the file that was being processed when this exception was thrown.
|
|
||||||
@property name(in string name)
|
|
||||||
{
|
|
||||||
msg = name ~ ":\n" ~ msg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///Position in a YAML stream, used for error messages.
|
///Position in a YAML stream, used for error messages.
|
||||||
|
@ -65,9 +57,9 @@ abstract class MarkedYAMLException : YAMLException
|
||||||
this(string context, Mark contextMark, string problem, Mark problemMark,
|
this(string context, Mark contextMark, string problem, Mark problemMark,
|
||||||
string file = __FILE__, int line = __LINE__)
|
string file = __FILE__, int line = __LINE__)
|
||||||
{
|
{
|
||||||
string msg = context ~ '\n';
|
const msg = context ~ '\n' ~
|
||||||
if(contextMark != problemMark){msg ~= contextMark.toString() ~ '\n';}
|
(contextMark != problemMark ? contextMark.toString() ~ '\n' : "") ~
|
||||||
msg ~= problem ~ '\n' ~ problemMark.toString() ~ '\n';
|
problem ~ '\n' ~ problemMark.toString() ~ '\n';
|
||||||
super(msg, file, line);
|
super(msg, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,11 +73,10 @@ abstract class MarkedYAMLException : YAMLException
|
||||||
//Constructors of YAML exceptions are mostly the same, so we use a mixin.
|
//Constructors of YAML exceptions are mostly the same, so we use a mixin.
|
||||||
template ExceptionCtors()
|
template ExceptionCtors()
|
||||||
{
|
{
|
||||||
public:
|
public this(string msg, string file = __FILE__, int line = __LINE__)
|
||||||
this(string msg, string file = __FILE__, int line = __LINE__)
|
{
|
||||||
{
|
super(msg, file, line);
|
||||||
super(msg, file, line);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Constructors of marked YAML exceptions are mostly the same, so we use a mixin.
|
//Constructors of marked YAML exceptions are mostly the same, so we use a mixin.
|
||||||
|
|
|
@ -104,23 +104,23 @@ struct Loader
|
||||||
string name_ = "<unknown>";
|
string name_ = "<unknown>";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@disable this();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a Loader to load YAML from a file.
|
* Construct a Loader to load YAML from a file.
|
||||||
*
|
*
|
||||||
* Params: filename = Name of the file to load from.
|
* Params: filename = Name of the file to load from.
|
||||||
*
|
*
|
||||||
* Throws: YAMLException if the file could not be opened or read from.
|
* Throws: YAMLException if the file could not be opened or read.
|
||||||
*/
|
*/
|
||||||
this(in string filename)
|
this(in string filename)
|
||||||
{
|
{
|
||||||
try
|
name_ = filename;
|
||||||
{
|
try{this(new File(filename));}
|
||||||
name = filename;
|
|
||||||
this(new File(filename));
|
|
||||||
}
|
|
||||||
catch(StreamException e)
|
catch(StreamException e)
|
||||||
{
|
{
|
||||||
throw new YAMLException("Unable to load YAML file " ~ filename ~ " : " ~ e.msg);
|
throw new YAMLException("Unable to open file " ~ filename ~
|
||||||
|
" for YAML loading: " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ struct Loader
|
||||||
*
|
*
|
||||||
* Params: stream = Stream to read from. Must be readable.
|
* Params: stream = Stream to read from. Must be readable.
|
||||||
*
|
*
|
||||||
* Throws: YAMLException if stream could not be read from.
|
* Throws: YAMLException if stream could not be read.
|
||||||
*/
|
*/
|
||||||
this(Stream stream)
|
this(Stream stream)
|
||||||
{
|
{
|
||||||
|
@ -145,8 +145,8 @@ struct Loader
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
e.name = name_;
|
throw new YAMLException("Unable to open stream " ~ name_ ~
|
||||||
throw e;
|
" for YAML loading: " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ struct Loader
|
||||||
/**
|
/**
|
||||||
* Load single YAML document.
|
* Load single YAML document.
|
||||||
*
|
*
|
||||||
* If none or more than one YAML document is found, this will throw a YAMLException.
|
* If none or more than one YAML document is found, this throws a YAMLException.
|
||||||
*
|
*
|
||||||
* Returns: Root node of the document.
|
* Returns: Root node of the document.
|
||||||
*
|
*
|
||||||
|
@ -198,8 +198,8 @@ struct Loader
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
e.name = name_;
|
throw new YAMLException("Unable to load YAML from stream " ~
|
||||||
throw e;
|
name_ ~ " : " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,15 +208,12 @@ struct Loader
|
||||||
*
|
*
|
||||||
* Returns: Array of root nodes of all documents in the file/stream.
|
* Returns: Array of root nodes of all documents in the file/stream.
|
||||||
*
|
*
|
||||||
* Throws: YAMLException on a YAML parsing error.
|
* Throws: YAMLException on a parsing error.
|
||||||
*/
|
*/
|
||||||
Node[] loadAll()
|
Node[] loadAll()
|
||||||
{
|
{
|
||||||
Node[] nodes;
|
Node[] nodes;
|
||||||
foreach(ref node; this)
|
foreach(ref node; this){nodes ~= node;}
|
||||||
{
|
|
||||||
nodes ~= node;
|
|
||||||
}
|
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,8 +242,8 @@ struct Loader
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
e.name = name_;
|
throw new YAMLException("Unable to load YAML from stream " ~
|
||||||
throw e;
|
name_ ~ " : " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +259,8 @@ struct Loader
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
e.name = name_;
|
throw new YAMLException("Unable to scan YAML from stream " ~
|
||||||
throw e;
|
name_ ~ " : " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,8 +275,8 @@ struct Loader
|
||||||
}
|
}
|
||||||
catch(YAMLException e)
|
catch(YAMLException e)
|
||||||
{
|
{
|
||||||
e.name = name_;
|
throw new YAMLException("Unable to parse YAML from stream " ~
|
||||||
throw e;
|
name_ ~ " : " ~ e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
59
dyaml/node.d
59
dyaml/node.d
|
@ -39,10 +39,12 @@ class NodeException : YAMLException
|
||||||
*/
|
*/
|
||||||
this(string msg, Mark start, string file = __FILE__, int line = __LINE__)
|
this(string msg, Mark start, string file = __FILE__, int line = __LINE__)
|
||||||
{
|
{
|
||||||
super(msg ~ "\nNode at:" ~ start.toString(), file, line);
|
super(msg ~ "\nNode at: " ~ start.toString(), file, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private alias NodeException Error;
|
||||||
|
|
||||||
//Node kinds.
|
//Node kinds.
|
||||||
package enum NodeID : ubyte
|
package enum NodeID : ubyte
|
||||||
{
|
{
|
||||||
|
@ -532,8 +534,8 @@ struct Node
|
||||||
void throwUnexpectedType()
|
void throwUnexpectedType()
|
||||||
{
|
{
|
||||||
//Can't get the value.
|
//Can't get the value.
|
||||||
throw new NodeException("Node has unexpected type " ~ type.toString ~
|
throw new Error("Node has unexpected type: " ~ type.toString ~
|
||||||
". Expected " ~ typeid(T).toString, startMark_);
|
". Expected: " ~ typeid(T).toString, startMark_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static if(isSomeString!T)
|
static if(isSomeString!T)
|
||||||
|
@ -546,8 +548,7 @@ struct Node
|
||||||
}
|
}
|
||||||
catch(VariantException e)
|
catch(VariantException e)
|
||||||
{
|
{
|
||||||
throw new NodeException("Unable to convert node value to a string",
|
throw new Error("Unable to convert node value to string", startMark_);
|
||||||
startMark_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else static if(isFloatingPoint!T)
|
else static if(isFloatingPoint!T)
|
||||||
|
@ -571,9 +572,9 @@ struct Node
|
||||||
long temp = value_.get!long;
|
long temp = value_.get!long;
|
||||||
if(temp < T.min || temp > T.max)
|
if(temp < T.min || temp > T.max)
|
||||||
{
|
{
|
||||||
throw new NodeException("Integer value out of range of type " ~
|
throw new Error("Integer value out of range of type " ~
|
||||||
typeid(T).toString ~ "Value: " ~
|
typeid(T).toString ~ "Value: " ~ to!string(temp),
|
||||||
to!string(temp), startMark_);
|
startMark_);
|
||||||
}
|
}
|
||||||
target = to!T(temp);
|
target = to!T(temp);
|
||||||
return;
|
return;
|
||||||
|
@ -602,8 +603,7 @@ struct Node
|
||||||
{
|
{
|
||||||
if(isSequence) {return get!(Node[]).length;}
|
if(isSequence) {return get!(Node[]).length;}
|
||||||
else if(isMapping){return get!(Pair[]).length;}
|
else if(isMapping){return get!(Pair[]).length;}
|
||||||
throw new NodeException("Trying to get length of a node that is not a collection",
|
throw new Error("Trying to get length of a scalar node", startMark_);
|
||||||
startMark_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -637,12 +637,10 @@ struct Node
|
||||||
auto idx = findPair(index);
|
auto idx = findPair(index);
|
||||||
if(idx >= 0){return get!(Pair[])[idx].value;}
|
if(idx >= 0){return get!(Pair[])[idx].value;}
|
||||||
|
|
||||||
throw new NodeException("Mapping index not found" ~
|
throw new Error("Mapping index not found" ~
|
||||||
isSomeString!T ? ": " ~ to!string(index) : "",
|
isSomeString!T ? ": " ~ to!string(index) : "", startMark_);
|
||||||
startMark_);
|
|
||||||
}
|
}
|
||||||
throw new NodeException("Trying to index node that does not support indexing",
|
throw new Error("Trying to index node that does not support indexing", startMark_);
|
||||||
startMark_);
|
|
||||||
}
|
}
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
@ -723,8 +721,7 @@ struct Node
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NodeException("Trying to index a YAML node that is not a collection.",
|
throw new Error("Trying to index a scalar node.", startMark_);
|
||||||
startMark_);
|
|
||||||
}
|
}
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
@ -758,8 +755,8 @@ struct Node
|
||||||
int opApply(T)(int delegate(ref T) dg)
|
int opApply(T)(int delegate(ref T) dg)
|
||||||
{
|
{
|
||||||
enforce(isSequence,
|
enforce(isSequence,
|
||||||
new NodeException("Trying to iterate over a node that is not a sequence",
|
new Error("Trying to iterate over a node that is not a sequence",
|
||||||
startMark_));
|
startMark_));
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
foreach(ref node; get!(Node[]))
|
foreach(ref node; get!(Node[]))
|
||||||
|
@ -815,8 +812,8 @@ struct Node
|
||||||
int opApply(K, V)(int delegate(ref K, ref V) dg)
|
int opApply(K, V)(int delegate(ref K, ref V) dg)
|
||||||
{
|
{
|
||||||
enforce(isMapping,
|
enforce(isMapping,
|
||||||
new NodeException("Trying to iterate over a node that is not a mapping",
|
new Error("Trying to iterate over a node that is not a mapping",
|
||||||
startMark_));
|
startMark_));
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
foreach(ref pair; get!(Node.Pair[]))
|
foreach(ref pair; get!(Node.Pair[]))
|
||||||
|
@ -915,8 +912,7 @@ struct Node
|
||||||
void add(T)(T value)
|
void add(T)(T value)
|
||||||
{
|
{
|
||||||
enforce(isSequence(),
|
enforce(isSequence(),
|
||||||
new NodeException("Trying to add an element to a "
|
new Error("Trying to add an element to a non-sequence node", startMark_));
|
||||||
"non-sequence YAML node", startMark_));
|
|
||||||
|
|
||||||
auto nodes = get!(Node[])();
|
auto nodes = get!(Node[])();
|
||||||
static if(is(T == Node)){nodes ~= value;}
|
static if(is(T == Node)){nodes ~= value;}
|
||||||
|
@ -953,8 +949,8 @@ struct Node
|
||||||
void add(K, V)(K key, V value)
|
void add(K, V)(K key, V value)
|
||||||
{
|
{
|
||||||
enforce(isMapping(),
|
enforce(isMapping(),
|
||||||
new NodeException("Trying to add a key-value pair to a "
|
new Error("Trying to add a key-value pair to a non-mapping node",
|
||||||
"non-mapping YAML node", startMark_));
|
startMark_));
|
||||||
|
|
||||||
auto pairs = get!(Node.Pair[])();
|
auto pairs = get!(Node.Pair[])();
|
||||||
pairs ~= Pair(key, value);
|
pairs ~= Pair(key, value);
|
||||||
|
@ -1010,8 +1006,7 @@ struct Node
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new NodeException("Trying to remove an element from a YAML node that "
|
throw new Error("Trying to remove an element from a scalar node", startMark_);
|
||||||
"is not a collection.", startMark_);
|
|
||||||
}
|
}
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
@ -1077,8 +1072,7 @@ struct Node
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new NodeException("Trying to remove an element from a YAML node that "
|
throw new Error("Trying to remove an element from a scalar node", startMark_);
|
||||||
"is not a collection.", startMark_);
|
|
||||||
}
|
}
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
@ -1334,14 +1328,13 @@ struct Node
|
||||||
{
|
{
|
||||||
static if(!isIntegral!T)
|
static if(!isIntegral!T)
|
||||||
{
|
{
|
||||||
throw new NodeException("Indexing a YAML sequence with a non-integral type.",
|
throw new Error("Indexing a sequence with a non-integral type.", startMark_);
|
||||||
startMark_);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enforce(index >= 0 && index < value_.get!(Node[]).length,
|
enforce(index >= 0 && index < value_.get!(Node[]).length,
|
||||||
new NodeException("Index to a YAML sequence out of range: "
|
new Error("Sequence index out of range: " ~ to!string(index),
|
||||||
~ to!string(index), startMark_));
|
startMark_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,8 @@ class ParserException : MarkedYAMLException
|
||||||
mixin MarkedExceptionCtors;
|
mixin MarkedExceptionCtors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private alias ParserException Error;
|
||||||
|
|
||||||
///Generates events from tokens provided by a Scanner.
|
///Generates events from tokens provided by a Scanner.
|
||||||
final class Parser
|
final class Parser
|
||||||
{
|
{
|
||||||
|
@ -225,7 +227,7 @@ final class Parser
|
||||||
Event delegate() popState()
|
Event delegate() popState()
|
||||||
{
|
{
|
||||||
enforce(states_.length > 0,
|
enforce(states_.length > 0,
|
||||||
new YAMLException("Parser: Need to pop a state but there are no states left"));
|
new YAMLException("Parser: Need to pop state but no states left to pop"));
|
||||||
const result = states_.back();
|
const result = states_.back();
|
||||||
states_.popBack;
|
states_.popBack;
|
||||||
return result;
|
return result;
|
||||||
|
@ -235,7 +237,7 @@ final class Parser
|
||||||
Mark popMark()
|
Mark popMark()
|
||||||
{
|
{
|
||||||
enforce(marks_.length > 0,
|
enforce(marks_.length > 0,
|
||||||
new YAMLException("Parser: Need to pop a mark but there are no marks left"));
|
new YAMLException("Parser: Need to pop mark but no marks left to pop"));
|
||||||
const result = marks_.back();
|
const result = marks_.back();
|
||||||
marks_.popBack;
|
marks_.popBack;
|
||||||
return result;
|
return result;
|
||||||
|
@ -286,9 +288,9 @@ final class Parser
|
||||||
|
|
||||||
auto tagDirectives = processDirectives();
|
auto tagDirectives = processDirectives();
|
||||||
enforce(scanner_.checkToken(TokenID.DocumentStart),
|
enforce(scanner_.checkToken(TokenID.DocumentStart),
|
||||||
new ParserException("Expected document start but found " ~
|
new Error("Expected document start but found " ~
|
||||||
to!string(scanner_.peekToken().id),
|
scanner_.peekToken().idString,
|
||||||
scanner_.peekToken().startMark));
|
scanner_.peekToken().startMark));
|
||||||
|
|
||||||
const endMark = scanner_.getToken().endMark;
|
const endMark = scanner_.getToken().endMark;
|
||||||
states_ ~= &parseDocumentEnd;
|
states_ ~= &parseDocumentEnd;
|
||||||
|
@ -347,12 +349,11 @@ final class Parser
|
||||||
if(name == "YAML")
|
if(name == "YAML")
|
||||||
{
|
{
|
||||||
enforce(YAMLVersion_ is null,
|
enforce(YAMLVersion_ is null,
|
||||||
new ParserException("Found duplicate YAML directive",
|
new Error("Duplicate YAML directive", token.startMark));
|
||||||
token.startMark));
|
|
||||||
const minor = parts[1].split(".")[0];
|
const minor = parts[1].split(".")[0];
|
||||||
enforce(to!int(minor) == 1,
|
enforce(to!int(minor) == 1,
|
||||||
new ParserException("Found incompatible YAML document (version "
|
new Error("Incompatible document (version 1.x is required)",
|
||||||
"1.* is required)", token.startMark));
|
token.startMark));
|
||||||
YAMLVersion_ = parts[1];
|
YAMLVersion_ = parts[1];
|
||||||
}
|
}
|
||||||
else if(name == "TAG")
|
else if(name == "TAG")
|
||||||
|
@ -365,8 +366,8 @@ final class Parser
|
||||||
//handle
|
//handle
|
||||||
auto h = pair[0];
|
auto h = pair[0];
|
||||||
auto replacement = pair[1];
|
auto replacement = pair[1];
|
||||||
enforce(h != handle, new ParserException("Duplicate tag handle: " ~
|
enforce(h != handle, new Error("Duplicate tag handle: " ~ handle,
|
||||||
handle, token.startMark));
|
token.startMark));
|
||||||
}
|
}
|
||||||
tagHandles_ ~= tuple(handle, parts[2]);
|
tagHandles_ ~= tuple(handle, parts[2]);
|
||||||
}
|
}
|
||||||
|
@ -515,9 +516,9 @@ final class Parser
|
||||||
}
|
}
|
||||||
|
|
||||||
Token token = scanner_.peekToken();
|
Token token = scanner_.peekToken();
|
||||||
throw new ParserException("While parsing a " ~ (block ? "block" : "flow") ~ " node",
|
throw new Error("While parsing a " ~ (block ? "block" : "flow") ~ " node",
|
||||||
startMark, "expected the node content, but found: "
|
startMark, "expected the node content, but found: "
|
||||||
~ to!string(token.id), token.startMark);
|
~ token.idString, token.startMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -549,8 +550,8 @@ final class Parser
|
||||||
}
|
}
|
||||||
//handle must be in tagHandles_
|
//handle must be in tagHandles_
|
||||||
enforce(replacement !is null,
|
enforce(replacement !is null,
|
||||||
new ParserException("While parsing a node", startMark,
|
new Error("While parsing a node", startMark,
|
||||||
"found undefined tag handle: " ~ handle, tagMark));
|
"found undefined tag handle: " ~ handle, tagMark));
|
||||||
return replacement ~ suffix;
|
return replacement ~ suffix;
|
||||||
}
|
}
|
||||||
return suffix;
|
return suffix;
|
||||||
|
@ -584,9 +585,9 @@ final class Parser
|
||||||
if(!scanner_.checkToken(TokenID.BlockEnd))
|
if(!scanner_.checkToken(TokenID.BlockEnd))
|
||||||
{
|
{
|
||||||
Token token = scanner_.peekToken();
|
Token token = scanner_.peekToken();
|
||||||
throw new ParserException("While parsing a block collection", marks_[$ - 1],
|
throw new Error("While parsing a block collection", marks_[$ - 1],
|
||||||
"expected block end, but found "
|
"expected block end, but found " ~ token.idString,
|
||||||
~ to!string(token.id), token.startMark);
|
token.startMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ = popState();
|
state_ = popState();
|
||||||
|
@ -649,9 +650,9 @@ final class Parser
|
||||||
if(!scanner_.checkToken(TokenID.BlockEnd))
|
if(!scanner_.checkToken(TokenID.BlockEnd))
|
||||||
{
|
{
|
||||||
Token token = scanner_.peekToken();
|
Token token = scanner_.peekToken();
|
||||||
throw new ParserException("While parsing a block mapping", marks_[$ - 1],
|
throw new Error("While parsing a block mapping", marks_[$ - 1],
|
||||||
"expected block end, but found: "
|
"expected block end, but found: " ~ token.idString,
|
||||||
~ to!string(token.id), token.startMark);
|
token.startMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ = popState();
|
state_ = popState();
|
||||||
|
@ -710,10 +711,9 @@ final class Parser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Token token = scanner_.peekToken;
|
Token token = scanner_.peekToken;
|
||||||
throw new ParserException("While parsing a flow sequence",
|
throw new Error("While parsing a flow sequence", marks_[$ - 1],
|
||||||
marks_[$ - 1],
|
"expected ',' or ']', but got: " ~
|
||||||
"expected ',' or ']', but got: " ~
|
token.idString, token.startMark);
|
||||||
to!string(token.id), token.startMark);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,10 +818,9 @@ final class Parser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Token token = scanner_.peekToken;
|
Token token = scanner_.peekToken;
|
||||||
throw new ParserException("While parsing a flow mapping",
|
throw new Error("While parsing a flow mapping", marks_[$ - 1],
|
||||||
marks_[$ - 1],
|
"expected ',' or '}', but got: " ~
|
||||||
"expected ',' or '}', but got: " ~
|
token.idString, token.startMark);
|
||||||
to!string(token.id), token.startMark);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class ReaderException : YAMLException
|
||||||
{
|
{
|
||||||
this(string msg, string file = __FILE__, int line = __LINE__)
|
this(string msg, string file = __FILE__, int line = __LINE__)
|
||||||
{
|
{
|
||||||
super("Error reading YAML stream: " ~ msg, file, line);
|
super("Error reading stream: " ~ msg, file, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,11 +105,11 @@ final class Reader
|
||||||
rawBuffer16_[0] = stream_.getcw();
|
rawBuffer16_[0] = stream_.getcw();
|
||||||
rawUsed_ = 1;
|
rawUsed_ = 1;
|
||||||
enforce(stream_.available % 2 == 0,
|
enforce(stream_.available % 2 == 0,
|
||||||
new ReaderException("Odd number of bytes in an UTF-16 stream"));
|
new ReaderException("Odd byte count in an UTF-16 stream"));
|
||||||
break;
|
break;
|
||||||
case 3, 4:
|
case 3, 4:
|
||||||
enforce(stream_.available % 4 == 0,
|
enforce(stream_.available % 4 == 0,
|
||||||
new ReaderException("Number of bytes in an UTF-32 stream not divisible by 4"));
|
new ReaderException("Byte count in an UTF-32 stream not divisible by 4"));
|
||||||
encoding_ = Encoding.UTF_32;
|
encoding_ = Encoding.UTF_32;
|
||||||
break;
|
break;
|
||||||
default: assert(false, "Unknown UTF BOM");
|
default: assert(false, "Unknown UTF BOM");
|
||||||
|
@ -286,7 +286,7 @@ final class Reader
|
||||||
*
|
*
|
||||||
* Params: chars = Maximum number of characters to load.
|
* Params: chars = Maximum number of characters to load.
|
||||||
*
|
*
|
||||||
* Throws: ReaderException on unicode decoding error,
|
* Throws: ReaderException on Unicode decoding error,
|
||||||
* if nonprintable characters are detected, or
|
* if nonprintable characters are detected, or
|
||||||
* if there is an error reading from the stream.
|
* if there is an error reading from the stream.
|
||||||
*/
|
*/
|
||||||
|
@ -382,13 +382,12 @@ final class Reader
|
||||||
catch(UtfException e)
|
catch(UtfException e)
|
||||||
{
|
{
|
||||||
const position = stream_.position;
|
const position = stream_.position;
|
||||||
throw new ReaderException("Unicode decoding error between bytes " ~
|
throw new ReaderException(format("Unicode decoding error between bytes ",
|
||||||
to!string(oldPosition) ~ " and " ~
|
oldPosition, " and ", position, " : ", e.msg));
|
||||||
to!string(position) ~ " " ~ e.msg);
|
|
||||||
}
|
}
|
||||||
catch(ReadException e)
|
catch(ReadException e)
|
||||||
{
|
{
|
||||||
throw new ReaderException("Error reading from the stream: " ~ e.msg);
|
throw new ReaderException(e.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(printable(buffer_[oldLength .. $]),
|
enforce(printable(buffer_[oldLength .. $]),
|
||||||
|
|
|
@ -73,12 +73,12 @@ final class Representer
|
||||||
/**
|
/**
|
||||||
* Add a function to represent nodes with a specific data type.
|
* Add a function to represent nodes with a specific data type.
|
||||||
*
|
*
|
||||||
* The representer function takes a reference to a Node storing the data
|
* The representer function takes references to a Node storing the data
|
||||||
* type and to the Representer. It returns the represented node and may
|
* type and to the Representer. It returns the represented node and may
|
||||||
* throw a RepresenterException. See the example for more information.
|
* throw a RepresenterException. See the example for more information.
|
||||||
*
|
*
|
||||||
* Only one function may be specified for one data type. Default data
|
* Only one function may be specified for one data type. Default data
|
||||||
* types already have representer functions unless disabled in these
|
* types already have representer functions unless disabled in the
|
||||||
* Representer constructor.
|
* Representer constructor.
|
||||||
*
|
*
|
||||||
* Params: representer = Representer function to add.
|
* Params: representer = Representer function to add.
|
||||||
|
@ -297,8 +297,8 @@ final class Representer
|
||||||
auto type = data.isUserType ? data.get!YAMLObject.type : data.type;
|
auto type = data.isUserType ? data.get!YAMLObject.type : data.type;
|
||||||
|
|
||||||
enforce((type in representers_) !is null,
|
enforce((type in representers_) !is null,
|
||||||
new RepresenterException("No YAML representer function for type "
|
new RepresenterException("No representer function for type "
|
||||||
~ type.toString() ~ " cannot represent."));
|
~ type.toString() ~ " , cannot represent."));
|
||||||
Node result = representers_[type](data, this);
|
Node result = representers_[type](data, this);
|
||||||
if(!data.tag.isNull()){result.tag = data.tag;}
|
if(!data.tag.isNull()){result.tag = data.tag;}
|
||||||
return result;
|
return result;
|
||||||
|
@ -426,8 +426,7 @@ Node representPairs(ref Node node, Representer representer)
|
||||||
if(node.tag == Tag("tag:yaml.org,2002:omap"))
|
if(node.tag == Tag("tag:yaml.org,2002:omap"))
|
||||||
{
|
{
|
||||||
enforce(!hasDuplicates(pairs),
|
enforce(!hasDuplicates(pairs),
|
||||||
new RepresenterException("Found a duplicate entry "
|
new RepresenterException("Duplicate entry in an ordered map"));
|
||||||
"in an ordered map"));
|
|
||||||
return representer.representSequence(node.tag.get, mapToSequence(pairs));
|
return representer.representSequence(node.tag.get, mapToSequence(pairs));
|
||||||
}
|
}
|
||||||
else if(node.tag == Tag("tag:yaml.org,2002:pairs"))
|
else if(node.tag == Tag("tag:yaml.org,2002:pairs"))
|
||||||
|
@ -437,8 +436,7 @@ Node representPairs(ref Node node, Representer representer)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enforce(!hasDuplicates(pairs),
|
enforce(!hasDuplicates(pairs),
|
||||||
new RepresenterException("Found a duplicate entry "
|
new RepresenterException("Duplicate entry in an unordered map"));
|
||||||
"in an unordered map"));
|
|
||||||
return representer.representMapping("tag:yaml.org,2002:map", pairs);
|
return representer.representMapping("tag:yaml.org,2002:map", pairs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
162
dyaml/scanner.d
162
dyaml/scanner.d
|
@ -63,6 +63,8 @@ class ScannerException : MarkedYAMLException
|
||||||
mixin MarkedExceptionCtors;
|
mixin MarkedExceptionCtors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private alias ScannerException Error;
|
||||||
|
|
||||||
///Generates tokens from data provided by a Reader.
|
///Generates tokens from data provided by a Reader.
|
||||||
final class Scanner
|
final class Scanner
|
||||||
{
|
{
|
||||||
|
@ -269,9 +271,9 @@ final class Scanner
|
||||||
if(c == '\"') {return fetchDouble();}
|
if(c == '\"') {return fetchDouble();}
|
||||||
if(checkPlain()) {return fetchPlain();}
|
if(checkPlain()) {return fetchPlain();}
|
||||||
|
|
||||||
throw new ScannerException(format("While scanning for the next token, found "
|
throw new Error(format("While scanning for the next token, found "
|
||||||
"character \'", c, "\', index ",to!int(c),
|
"character \'", c, "\', index ",to!int(c),
|
||||||
" that cannot start " "any token"), reader_.mark);
|
" that cannot start any token"), reader_.mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,9 +305,9 @@ final class Scanner
|
||||||
if(key.line != reader_.line || reader_.charIndex - key.charIndex > 1024)
|
if(key.line != reader_.line || reader_.charIndex - key.charIndex > 1024)
|
||||||
{
|
{
|
||||||
enforce(!key.required,
|
enforce(!key.required,
|
||||||
new ScannerException("While scanning a simple key",
|
new Error("While scanning a simple key",
|
||||||
Mark(key.line, key.column),
|
Mark(key.line, key.column),
|
||||||
"could not find expected ':'", reader_.mark));
|
"could not find expected ':'", reader_.mark));
|
||||||
levelsToRemove ~= level;
|
levelsToRemove ~= level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,10 +343,8 @@ final class Scanner
|
||||||
{
|
{
|
||||||
auto key = possibleSimpleKeys_[flowLevel_];
|
auto key = possibleSimpleKeys_[flowLevel_];
|
||||||
enforce(!key.required,
|
enforce(!key.required,
|
||||||
new ScannerException("While scanning a simple key",
|
new Error("While scanning a simple key", Mark(key.line, key.column),
|
||||||
Mark(key.line, key.column),
|
"could not find expected ':'", reader_.mark));
|
||||||
"could not find expected ':'",
|
|
||||||
reader_.mark));
|
|
||||||
possibleSimpleKeys_.remove(flowLevel_);
|
possibleSimpleKeys_.remove(flowLevel_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,8 +369,8 @@ final class Scanner
|
||||||
//restrictive than what the specification requires.
|
//restrictive than what the specification requires.
|
||||||
//if(pedantic_ && flowLevel_ > 0 && indent_ > column)
|
//if(pedantic_ && flowLevel_ > 0 && indent_ > column)
|
||||||
//{
|
//{
|
||||||
// throw new ScannerException("Invalid intendation or unclosed '[' or '{'",
|
// throw new Error("Invalid intendation or unclosed '[' or '{'",
|
||||||
// reader_.mark)
|
// reader_.mark)
|
||||||
//}
|
//}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -510,8 +510,8 @@ final class Scanner
|
||||||
void blockChecks(string type, TokenID id)()
|
void blockChecks(string type, TokenID id)()
|
||||||
{
|
{
|
||||||
//Are we allowed to start a key (not neccesarily a simple one)?
|
//Are we allowed to start a key (not neccesarily a simple one)?
|
||||||
enforce(allowSimpleKey_, new ScannerException(type ~ " keys are not allowed here",
|
enforce(allowSimpleKey_, new Error(type ~ " keys are not allowed here",
|
||||||
reader_.mark));
|
reader_.mark));
|
||||||
|
|
||||||
if(addIndent(reader_.column))
|
if(addIndent(reader_.column))
|
||||||
{
|
{
|
||||||
|
@ -585,8 +585,7 @@ final class Scanner
|
||||||
{
|
{
|
||||||
//We can start a complex value if and only if we can start a simple key.
|
//We can start a complex value if and only if we can start a simple key.
|
||||||
enforce(flowLevel_ > 0 || allowSimpleKey_,
|
enforce(flowLevel_ > 0 || allowSimpleKey_,
|
||||||
new ScannerException("Mapping values are not allowed here",
|
new Error("Mapping values are not allowed here", reader_.mark));
|
||||||
reader_.mark));
|
|
||||||
|
|
||||||
//If this value starts a new block mapping, we need to add
|
//If this value starts a new block mapping, we need to add
|
||||||
//BLOCK-MAPPING-START. It'll be detected as an error later by the parser.
|
//BLOCK-MAPPING-START. It'll be detected as an error later by the parser.
|
||||||
|
@ -777,9 +776,9 @@ final class Scanner
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(length > 0,
|
enforce(length > 0,
|
||||||
new ScannerException("While scanning " ~ name, startMark,
|
new Error("While scanning " ~ name, startMark,
|
||||||
"expected alphanumeric, - or _, but found "
|
"expected alphanumeric, - or _, but found " ~ to!string(c),
|
||||||
~ to!string(c), reader_.mark));
|
reader_.mark));
|
||||||
|
|
||||||
return reader_.get(length);
|
return reader_.get(length);
|
||||||
}
|
}
|
||||||
|
@ -856,9 +855,9 @@ final class Scanner
|
||||||
const name = scanAlphaNumeric!"a directive"(startMark);
|
const name = scanAlphaNumeric!"a directive"(startMark);
|
||||||
|
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
||||||
new ScannerException("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected alphanumeric, - or _, but found "
|
"expected alphanumeric, - or _, but found "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,17 +868,17 @@ final class Scanner
|
||||||
|
|
||||||
dstring result = scanYAMLDirectiveNumber(startMark);
|
dstring result = scanYAMLDirectiveNumber(startMark);
|
||||||
enforce(reader_.peek() == '.',
|
enforce(reader_.peek() == '.',
|
||||||
new ScannerException("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected a digit or '.', but found: "
|
"expected a digit or '.', but found: "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
//Skip the '.'.
|
//Skip the '.'.
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
|
|
||||||
result ~= '.' ~ scanYAMLDirectiveNumber(startMark);
|
result ~= '.' ~ scanYAMLDirectiveNumber(startMark);
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
||||||
new ScannerException("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected a digit or '.', but found: "
|
"expected a digit or '.', but found: "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,9 +886,9 @@ final class Scanner
|
||||||
dstring scanYAMLDirectiveNumber(in Mark startMark)
|
dstring scanYAMLDirectiveNumber(in Mark startMark)
|
||||||
{
|
{
|
||||||
enforce(isDigit(reader_.peek()),
|
enforce(isDigit(reader_.peek()),
|
||||||
new ScannerException("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected a digit, but found: " ~
|
"expected a digit, but found: " ~
|
||||||
to!string(reader_.peek()), reader_.mark));
|
to!string(reader_.peek()), reader_.mark));
|
||||||
|
|
||||||
//Already found the first digit in the enforce(), so set length to 1.
|
//Already found the first digit in the enforce(), so set length to 1.
|
||||||
uint length = 1;
|
uint length = 1;
|
||||||
|
@ -912,9 +911,9 @@ final class Scanner
|
||||||
{
|
{
|
||||||
const value = scanTagHandle("directive", startMark);
|
const value = scanTagHandle("directive", startMark);
|
||||||
enforce(reader_.peek() == ' ',
|
enforce(reader_.peek() == ' ',
|
||||||
new ScannerException("While scanning a directive handle", startMark,
|
new Error("While scanning a directive handle", startMark,
|
||||||
"expected ' ', but found: " ~
|
"expected ' ', but found: " ~ to!string(reader_.peek()),
|
||||||
to!string(reader_.peek()), reader_.mark));
|
reader_.mark));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,9 +922,9 @@ final class Scanner
|
||||||
{
|
{
|
||||||
const value = scanTagURI("directive", startMark);
|
const value = scanTagURI("directive", startMark);
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
||||||
new ScannerException("While scanning a directive prefix", startMark,
|
new Error("While scanning a directive prefix", startMark,
|
||||||
"expected ' ', but found" ~ to!string(reader_.peek()),
|
"expected ' ', but found" ~ to!string(reader_.peek()),
|
||||||
reader_.mark));
|
reader_.mark));
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -936,9 +935,9 @@ final class Scanner
|
||||||
findNextNonSpace();
|
findNextNonSpace();
|
||||||
if(reader_.peek() == '#'){scanToNextBreak();}
|
if(reader_.peek() == '#'){scanToNextBreak();}
|
||||||
enforce("\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce("\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
||||||
new ScannerException("While scanning a directive", startMark,
|
new Error("While scanning a directive", startMark,
|
||||||
"expected comment or a line break, but found"
|
"expected comment or a line break, but found"
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
scanLineBreak();
|
scanLineBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +965,7 @@ final class Scanner
|
||||||
|
|
||||||
enforce((" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()) ||
|
enforce((" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()) ||
|
||||||
("?:,]}%@").canFind(reader_.peek())),
|
("?:,]}%@").canFind(reader_.peek())),
|
||||||
new ScannerException("While scanning an " ~ (i == '*') ? "alias" : "anchor",
|
new Error("While scanning an " ~ (i == '*') ? "alias" : "anchor",
|
||||||
startMark, "expected alphanumeric, - or _, but found "~
|
startMark, "expected alphanumeric, - or _, but found "~
|
||||||
to!string(reader_.peek()), reader_.mark));
|
to!string(reader_.peek()), reader_.mark));
|
||||||
|
|
||||||
|
@ -994,9 +993,9 @@ final class Scanner
|
||||||
reader_.forward(2);
|
reader_.forward(2);
|
||||||
suffix = scanTagURI("tag", startMark);
|
suffix = scanTagURI("tag", startMark);
|
||||||
enforce(reader_.peek() == '>',
|
enforce(reader_.peek() == '>',
|
||||||
new ScannerException("While scanning a tag", startMark,
|
new Error("While scanning a tag", startMark,
|
||||||
"expected '>' but found" ~
|
"expected '>' but found" ~ to!string(reader_.peek()),
|
||||||
to!string(reader_.peek()), reader_.mark));
|
reader_.mark));
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
}
|
}
|
||||||
else if(" \t\0\n\r\u0085\u2028\u2029".canFind(c))
|
else if(" \t\0\n\r\u0085\u2028\u2029".canFind(c))
|
||||||
|
@ -1031,9 +1030,9 @@ final class Scanner
|
||||||
}
|
}
|
||||||
|
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce(" \0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
||||||
new ScannerException("While scanning a tag", startMark,
|
new Error("While scanning a tag", startMark,
|
||||||
"expected ' ' but found" ~
|
"expected ' ' but found" ~ to!string(reader_.peek()),
|
||||||
to!string(reader_.peek()), reader_.mark));
|
reader_.mark));
|
||||||
return tagToken(startMark, reader_.mark, to!string(handle ~ '\0' ~ suffix));
|
return tagToken(startMark, reader_.mark, to!string(handle ~ '\0' ~ suffix));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,9 +1140,9 @@ final class Scanner
|
||||||
if(!isDigit(c)){return false;}
|
if(!isDigit(c)){return false;}
|
||||||
increment = to!int(""d ~ c);
|
increment = to!int(""d ~ c);
|
||||||
enforce(increment != 0,
|
enforce(increment != 0,
|
||||||
new ScannerException("While scanning a block scalar", startMark,
|
new Error("While scanning a block scalar", startMark,
|
||||||
"expected indentation indicator in range 1-9, "
|
"expected indentation indicator in range 1-9, but found 0",
|
||||||
"but found 0", reader_.mark));
|
reader_.mark));
|
||||||
reader_.forward();
|
reader_.forward();
|
||||||
c = reader_.peek();
|
c = reader_.peek();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1154,9 +1153,9 @@ final class Scanner
|
||||||
else if(getIncrement()){getChomping();}
|
else if(getIncrement()){getChomping();}
|
||||||
|
|
||||||
enforce(" \0\n\r\u0085\u2028\u2029".canFind(c),
|
enforce(" \0\n\r\u0085\u2028\u2029".canFind(c),
|
||||||
new ScannerException("While scanning a block scalar", startMark,
|
new Error("While scanning a block scalar", startMark,
|
||||||
"expected chomping or indentation indicator, "
|
"expected chomping or indentation indicator, but found "
|
||||||
"but found " ~ to!string(c), reader_.mark));
|
~ to!string(c), reader_.mark));
|
||||||
|
|
||||||
return tuple(chomping, increment);
|
return tuple(chomping, increment);
|
||||||
}
|
}
|
||||||
|
@ -1168,9 +1167,9 @@ final class Scanner
|
||||||
if(reader_.peek == '#'){scanToNextBreak();}
|
if(reader_.peek == '#'){scanToNextBreak();}
|
||||||
|
|
||||||
enforce("\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
enforce("\0\n\r\u0085\u2028\u2029".canFind(reader_.peek()),
|
||||||
new ScannerException("While scanning a block scalar", startMark,
|
new Error("While scanning a block scalar", startMark,
|
||||||
"expected a comment or a line break, but found "
|
"expected a comment or a line break, but found "
|
||||||
~ to!string(reader_.peek()), reader_.mark));
|
~ to!string(reader_.peek()), reader_.mark));
|
||||||
scanLineBreak();
|
scanLineBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,7 +1299,7 @@ final class Scanner
|
||||||
foreach(i; 0 .. length)
|
foreach(i; 0 .. length)
|
||||||
{
|
{
|
||||||
enforce(isHexDigit(reader_.peek(i)),
|
enforce(isHexDigit(reader_.peek(i)),
|
||||||
new ScannerException(
|
new Error(
|
||||||
"While scanning a double qouted scalar", startMark,
|
"While scanning a double qouted scalar", startMark,
|
||||||
"expected escape sequence of " ~ to!string(length) ~
|
"expected escape sequence of " ~ to!string(length) ~
|
||||||
" hexadecimal numbers, but found " ~
|
" hexadecimal numbers, but found " ~
|
||||||
|
@ -1317,7 +1316,7 @@ final class Scanner
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ScannerException("While scanning a double quoted scalar",
|
throw new Error("While scanning a double quoted scalar",
|
||||||
startMark,
|
startMark,
|
||||||
"found unknown escape character: " ~
|
"found unknown escape character: " ~
|
||||||
to!string(c), reader_.mark);
|
to!string(c), reader_.mark);
|
||||||
|
@ -1336,8 +1335,8 @@ final class Scanner
|
||||||
|
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
enforce(c != '\0',
|
enforce(c != '\0',
|
||||||
new ScannerException("While scanning a quoted scalar", startMark,
|
new Error("While scanning a quoted scalar", startMark,
|
||||||
"found unexpected end of stream", reader_.mark));
|
"found unexpected end of stream", reader_.mark));
|
||||||
|
|
||||||
auto appender = appender!dstring();
|
auto appender = appender!dstring();
|
||||||
if("\n\r\u0085\u2028\u2029".canFind(c))
|
if("\n\r\u0085\u2028\u2029".canFind(c))
|
||||||
|
@ -1364,9 +1363,8 @@ final class Scanner
|
||||||
if((prefix == "---" || prefix == "...") &&
|
if((prefix == "---" || prefix == "...") &&
|
||||||
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(3)))
|
" \t\0\n\r\u0085\u2028\u2029".canFind(reader_.peek(3)))
|
||||||
{
|
{
|
||||||
throw new ScannerException("While scanning a quoted scalar", startMark,
|
throw new Error("While scanning a quoted scalar", startMark,
|
||||||
"found unexpected document separator",
|
"found unexpected document separator", reader_.mark);
|
||||||
reader_.mark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while(" \t".canFind(reader_.peek())){reader_.forward();}
|
while(" \t".canFind(reader_.peek())){reader_.forward();}
|
||||||
|
@ -1417,10 +1415,10 @@ final class Scanner
|
||||||
!",[]{}".canFind(reader_.peek(length + 1)))
|
!",[]{}".canFind(reader_.peek(length + 1)))
|
||||||
{
|
{
|
||||||
reader_.forward(length);
|
reader_.forward(length);
|
||||||
throw new ScannerException("While scanning a plain scalar", startMark,
|
throw new Error("While scanning a plain scalar", startMark,
|
||||||
"found unexpected ':' . Please check "
|
"found unexpected ':' . Please check "
|
||||||
"http://pyyaml.org/wiki/YAMLColonInFlowContext "
|
"http://pyyaml.org/wiki/YAMLColonInFlowContext "
|
||||||
"for details.", reader_.mark);
|
"for details.", reader_.mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(length == 0){break;}
|
if(length == 0){break;}
|
||||||
|
@ -1494,9 +1492,8 @@ final class Scanner
|
||||||
{
|
{
|
||||||
dchar c = reader_.peek();
|
dchar c = reader_.peek();
|
||||||
enforce(c == '!',
|
enforce(c == '!',
|
||||||
new ScannerException("While scanning a " ~ name, startMark,
|
new Error("While scanning a " ~ name, startMark,
|
||||||
"expected a '!', but found: " ~ to!string(c),
|
"expected a '!', but found: " ~ to!string(c), reader_.mark));
|
||||||
reader_.mark));
|
|
||||||
|
|
||||||
uint length = 1;
|
uint length = 1;
|
||||||
c = reader_.peek(length);
|
c = reader_.peek(length);
|
||||||
|
@ -1510,9 +1507,9 @@ final class Scanner
|
||||||
if(c != '!')
|
if(c != '!')
|
||||||
{
|
{
|
||||||
reader_.forward(length);
|
reader_.forward(length);
|
||||||
throw new ScannerException("While scanning a " ~ name, startMark,
|
throw new Error("While scanning a " ~ name, startMark,
|
||||||
"expected a '!', but found: " ~ to!string(c),
|
"expected a '!', but found: " ~ to!string(c),
|
||||||
reader_.mark);
|
reader_.mark);
|
||||||
}
|
}
|
||||||
++length;
|
++length;
|
||||||
}
|
}
|
||||||
|
@ -1544,9 +1541,8 @@ final class Scanner
|
||||||
length = 0;
|
length = 0;
|
||||||
}
|
}
|
||||||
enforce(appender.data.length > 0,
|
enforce(appender.data.length > 0,
|
||||||
new ScannerException("While parsing a " ~ name, startMark,
|
new Error("While parsing a " ~ name, startMark,
|
||||||
"expected URI, but found: " ~ to!string(c),
|
"expected URI, but found: " ~ to!string(c), reader_.mark));
|
||||||
reader_.mark));
|
|
||||||
|
|
||||||
return appender.data;
|
return appender.data;
|
||||||
}
|
}
|
||||||
|
@ -1567,11 +1563,11 @@ final class Scanner
|
||||||
foreach(k; 0 .. 2)
|
foreach(k; 0 .. 2)
|
||||||
{
|
{
|
||||||
dchar c = reader_.peek(k);
|
dchar c = reader_.peek(k);
|
||||||
enforce("0123456789ABCDEFabcdef".canFind(c),
|
enforce(isHexDigit(c),
|
||||||
new ScannerException("While scanning a " ~ name, startMark,
|
new Error("While scanning a " ~ name, startMark,
|
||||||
"expected URI escape sequence of "
|
"expected URI escape sequence of "
|
||||||
"2 hexadecimal numbers, but found: " ~
|
"2 hexadecimal numbers, but found: " ~
|
||||||
to!string(c), reader_.mark));
|
to!string(c), reader_.mark));
|
||||||
|
|
||||||
uint digit;
|
uint digit;
|
||||||
if(c - '0' < 10){digit = c - '0';}
|
if(c - '0' < 10){digit = c - '0';}
|
||||||
|
@ -1589,11 +1585,11 @@ final class Scanner
|
||||||
try{return to!dstring(cast(string)bytes);}
|
try{return to!dstring(cast(string)bytes);}
|
||||||
catch(ConvException e)
|
catch(ConvException e)
|
||||||
{
|
{
|
||||||
throw new ScannerException("While scanning a " ~ name, startMark, e.msg, mark);
|
throw new Error("While scanning a " ~ name, startMark, e.msg, mark);
|
||||||
}
|
}
|
||||||
catch(UtfException e)
|
catch(UtfException e)
|
||||||
{
|
{
|
||||||
throw new ScannerException("While scanning a " ~ name, startMark, e.msg, mark);
|
throw new Error("While scanning a " ~ name, startMark, e.msg, mark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
module dyaml.token;
|
module dyaml.token;
|
||||||
|
|
||||||
|
|
||||||
|
import std.conv;
|
||||||
|
|
||||||
import dyaml.encoding;
|
import dyaml.encoding;
|
||||||
import dyaml.exception;
|
import dyaml.exception;
|
||||||
import dyaml.reader;
|
import dyaml.reader;
|
||||||
|
@ -81,6 +83,9 @@ immutable struct Token
|
||||||
ScalarStyle style;
|
ScalarStyle style;
|
||||||
///Encoding, if this is a stream start token.
|
///Encoding, if this is a stream start token.
|
||||||
Encoding encoding;
|
Encoding encoding;
|
||||||
|
|
||||||
|
///Get string representation of the token ID.
|
||||||
|
@property string idString() const {return to!string(id);}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue