diff --git a/OpenRA.FileFormats/MiniYaml.cs b/OpenRA.FileFormats/MiniYaml.cs index 9a6cd8b689..1c49eb1a29 100755 --- a/OpenRA.FileFormats/MiniYaml.cs +++ b/OpenRA.FileFormats/MiniYaml.cs @@ -19,6 +19,12 @@ namespace OpenRA.FileFormats public class MiniYamlNode { + public struct SourceLocation + { + public string Filename; public int Line; + } + + public SourceLocation Location; public string Key; public MiniYaml Value; @@ -28,14 +34,25 @@ namespace OpenRA.FileFormats Value = v; } + public MiniYamlNode( string k, MiniYaml v, SourceLocation loc ) + : this( k, v ) + { + Location = loc; + } + public MiniYamlNode( string k, string v ) - : this( k, new MiniYaml( v, null ) ) + : this( k, v, null ) { } public MiniYamlNode( string k, string v, List n ) : this( k, new MiniYaml( v, n ) ) { } + + public MiniYamlNode( string k, string v, List n, SourceLocation loc ) + : this( k, new MiniYaml( v, n ), loc ) + { + } } public class MiniYaml @@ -63,13 +80,15 @@ namespace OpenRA.FileFormats return new MiniYaml( null, list.Select( x => new MiniYamlNode( x.ToString(), new MiniYaml( null ) ) ).ToList() ); } - static List FromLines(string[] lines) + static List FromLines(string[] lines, string filename) { var levels = new List>(); levels.Add(new List()); + var lineNo = 0; foreach (var line in lines) { + ++lineNo; var t = line.TrimStart(' ', '\t'); if (t.Length == 0 || t[0] == '#') continue; @@ -80,27 +99,27 @@ namespace OpenRA.FileFormats while (levels.Count > level + 1) levels.RemoveAt(levels.Count - 1); - var colon = t.IndexOf(':'); var d = new List(); - try - { - if( colon == -1 ) - levels[ level ].Add( new MiniYamlNode( t.Trim(), new MiniYaml( null, d ) ) ); - else - { - var value = t.Substring( colon + 1 ).Trim(); - if( value.Length == 0 ) - value = null; - levels[ level ].Add( new MiniYamlNode( t.Substring( 0, colon ).Trim(), new MiniYaml( value, d ) ) ); - } - } - catch (ArgumentException) { throw new InvalidDataException("Duplicate Identifier:`{0}`".F(t)); } + var rhs = SplitAtColon( ref t ); + levels[ level ].Add( new MiniYamlNode( t, rhs, d, new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo } ) ); levels.Add(d); } return levels[ 0 ]; } + static string SplitAtColon( ref string t ) + { + var colon = t.IndexOf(':'); + if( colon == -1 ) + return null; + var ret = t.Substring( colon + 1 ).Trim(); + if( ret.Length == 0 ) + ret = null; + t = t.Substring( 0, colon ).Trim(); + return ret; + } + public static List FromFileInPackage( string path ) { StreamReader reader = new StreamReader( FileSystem.Open(path) ); @@ -110,7 +129,7 @@ namespace OpenRA.FileFormats lines.Add(reader.ReadLine()); reader.Close(); - return FromLines(lines.ToArray()); + return FromLines(lines.ToArray(), path); } public static Dictionary DictFromFile( string path ) @@ -125,7 +144,7 @@ namespace OpenRA.FileFormats public static List FromFile( string path ) { - return FromLines(File.ReadAllLines( path )); + return FromLines(File.ReadAllLines( path ), path); } public static List FromStream(Stream s) @@ -136,7 +155,7 @@ namespace OpenRA.FileFormats public static List FromString(string text) { - return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)); + return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), ""); } public static List Merge( List a, List b )