/// <summary> Internal parse method </summary> /// <param name="parseImplicitMappings"> /// Avoids ethernal loops while parsing implicit mappings. Implicit mappings are /// not rocognized by a leading character. So while trying to parse the key of /// something we think that could be a mapping, we're sure that if it is a mapping, /// the key of this implicit mapping is not a mapping itself. /// /// NOTE: Implicit mapping still belong to unstable code and require the UNSTABLE and /// IMPLICIT_MAPPINGS preprocessor flags. /// </param> /// <param name="stream"></param> protected static Node Parse (ParseStream stream, bool parseImplicitMappings) { // ---------------- // Skip Whitespace // ---------------- if (! stream.EOF) { // Move the firstindentation pointer after the whitespaces of this line stream.SkipSpaces (); while (stream.Char == '\n' && ! stream.EOF) { // Skip newline and next whitespaces stream.Next (); stream.SkipSpaces (); } } // ----------------- // No remaining chars (Null/empty stream) // ----------------- if (stream.EOF) return new Null (); // ----------------- // Explicit type // ----------------- #if SUPPORT_EXPLICIT_TYPES stream.BuildLookaheadBuffer (); char a = '\0', b = '\0'; a = stream.Char; stream.Next (); b = stream.Char; stream.Next (); // Starting with !! if (a == '!' && b == '!' && ! stream.EOF) { stream.DestroyLookaheadBuffer (); // Read the tagname string tag = ""; while (stream.Char != ' ' && stream.Char != '\n' && ! stream.EOF) { tag += stream.Char; stream.Next (); } // Skip Whitespace if (! stream.EOF) { stream.SkipSpaces (); while (stream.Char == '\n' && ! stream.EOF) { stream.Next (); stream.SkipSpaces (); } } // Parse Node n; switch (tag) { // Mappings and sequences // NOTE: // - sets are mappings without values // - Ordered maps are ordered sequence of key: value // pairs without duplicates. // - Pairs are ordered sequence of key: value pairs // allowing duplicates. // TODO: Create new datatypes for omap and pairs // derived from sequence with a extra duplicate // checking. case "seq": n = new Sequence (stream); break; case "map": n = new Mapping (stream); break; case "set": n = new Mapping (stream); break; case "omap": n = new Sequence (stream); break; case "pairs": n = new Sequence (stream); break; // Scalars // // TODO: do we have to move this to Scalar.cs // in order to get the following working: // // !!str "...": "..." // !!str "...": "..." case "timestamp": n = new Timestamp (stream); break; case "binary": n = new Binary (stream); break; case "null": n = new Null (stream); break; case "float": n = new Float (stream); break; case "int": n = new Integer (stream); break; case "bool": n = new Boolean (stream); break; case "str": n = new String (stream); break; // Unknown data type default: throw new Exception ("Incorrect tag '!!" + tag + "'"); } return n; } else { stream.RewindLookaheadBuffer (); stream.DestroyLookaheadBuffer (); } #endif // ----------------- // Sequence // ----------------- if (stream.Char == '-' || stream.Char == '[') return new Sequence (stream); // ----------------- // Mapping // ----------------- if (stream.Char == '?' || stream.Char == '{') return new Mapping (stream); // ----------------- // Try implicit mapping // ----------------- // This are mappings which are not preceded by a question // mark. The keys have to be scalars. #if (UNSTABLE && SUPPORT_IMPLICIT_MAPPINGS) // NOTE: This code can't be included in Mapping.cs // because of the way we are using to rewind the buffer. Node key, val; if (parseImplicitMappings) { // First Key/value pair stream.BuildLookaheadBuffer (); stream.StopAt (new char [] {':'}); // Keys of implicit mappings can't be sequences, or other mappings // just look for scalars key = Scalar.Parse (stream, false); stream.DontStop (); Console.WriteLine ("key: " + key); // Followed by a colon, so this is a real mapping if (stream.Char == ':') { stream.DestroyLookaheadBuffer (); Mapping mapping = new Mapping (); // Skip colon and spaces stream.Next (); stream.SkipSpaces (); // Parse the value Console.Write ("using buffer: " + stream.UsingBuffer ()); stream.Indent (); Console.Write ("using buffer: " + stream.UsingBuffer ()); // val = Parse (stream, false); Console.Write ("<<"); while (!stream.EOF) {Console.Write (stream.Char);stream.Next (true);} Console.Write (">>"); val = new String (stream); Console.Write ("using buffer: " + stream.UsingBuffer ()); stream.UnIndent (); Console.Write ("using buffer: " + stream.UsingBuffer ()); Console.Write ("<<"); while (!stream.EOF) {Console.Write (stream.Char);stream.Next (true);} Console.Write (">>"); Console.WriteLine ("val: " + val); mapping.AddMappingNode (key, val); // Skip possible newline // NOTE: this can't be done by the drop-newline // method since this is not the end of a block while (stream.Char == '\n') stream.Next (true); // Other key/value pairs while (! stream.EOF) { stream.StopAt (new char [] {':'} ); stream.Indent (); key = Scalar.Parse (stream); stream.UnIndent (); stream.DontStop (); Console.WriteLine ("key 2: " + key); if (stream.Char == ':') { // Skip colon and spaces stream.Next (); stream.SkipSpaces (); // Parse the value stream.Indent (); val = Parse (stream); stream.UnIndent (); Console.WriteLine ("val 2: " + val); mapping.AddMappingNode (key, val); } else // TODO: Is this an error? { // NOTE: We can't recover from this error, // the last buffer has been destroyed, so // rewinding is impossible. throw new ParseException (stream, "Implicit mapping without value node"); } // Skip possible newline while (stream.Char == '\n') stream.Next (); } return mapping; } stream.RewindLookaheadBuffer (); stream.DestroyLookaheadBuffer (); } #endif // ----------------- // No known data structure, assume this is a scalar // ----------------- Scalar scalar = Scalar.Parse (stream); // Skip trash while (! stream.EOF) stream.Next (); return scalar; }
/// <summary> Internal parse method </summary> /// <param name="parseImplicitMappings"> /// Avoids ethernal loops while parsing implicit mappings. Implicit mappings are /// not rocognized by a leading character. So while trying to parse the key of /// something we think that could be a mapping, we're sure that if it is a mapping, /// the key of this implicit mapping is not a mapping itself. /// /// NOTE: Implicit mapping still belong to unstable code and require the UNSTABLE and /// IMPLICIT_MAPPINGS preprocessor flags. /// </param> /// <param name="stream"></param> protected static Node Parse(ParseStream stream, bool parseImplicitMappings) { // ---------------- // Skip Whitespace // ---------------- if (!stream.EOF) { // Move the firstindentation pointer after the whitespaces of this line stream.SkipSpaces(); while (stream.Char == '\n' && !stream.EOF) { // Skip newline and next whitespaces stream.Next(); stream.SkipSpaces(); } } // ----------------- // No remaining chars (Null/empty stream) // ----------------- if (stream.EOF) { return(new Null()); } // ----------------- // Explicit type // ----------------- #if SUPPORT_EXPLICIT_TYPES stream.BuildLookaheadBuffer(); char a = '\0', b = '\0'; a = stream.Char; stream.Next(); b = stream.Char; stream.Next(); // Starting with !! if (a == '!' && b == '!' && !stream.EOF) { stream.DestroyLookaheadBuffer(); // Read the tagname string tag = ""; while (stream.Char != ' ' && stream.Char != '\n' && !stream.EOF) { tag += stream.Char; stream.Next(); } // Skip Whitespace if (!stream.EOF) { stream.SkipSpaces(); while (stream.Char == '\n' && !stream.EOF) { stream.Next(); stream.SkipSpaces(); } } // Parse Node n; switch (tag) { // Mappings and sequences // NOTE: // - sets are mappings without values // - Ordered maps are ordered sequence of key: value // pairs without duplicates. // - Pairs are ordered sequence of key: value pairs // allowing duplicates. // TODO: Create new datatypes for omap and pairs // derived from sequence with a extra duplicate // checking. case "seq": n = new Sequence(stream); break; case "map": n = new Mapping(stream); break; case "set": n = new Mapping(stream); break; case "omap": n = new Sequence(stream); break; case "pairs": n = new Sequence(stream); break; // Scalars // // TODO: do we have to move this to Scalar.cs // in order to get the following working: // // !!str "...": "..." // !!str "...": "..." case "timestamp": n = new Timestamp(stream); break; case "binary": n = new Binary(stream); break; case "null": n = new Null(stream); break; case "float": n = new Float(stream); break; case "int": n = new Integer(stream); break; case "bool": n = new Boolean(stream); break; case "str": n = new String(stream); break; // Unknown data type default: throw new Exception("Incorrect tag '!!" + tag + "'"); } return(n); } else { stream.RewindLookaheadBuffer(); stream.DestroyLookaheadBuffer(); } #endif // ----------------- // Sequence // ----------------- if (stream.Char == '-' || stream.Char == '[') { return(new Sequence(stream)); } // ----------------- // Mapping // ----------------- if (stream.Char == '?' || stream.Char == '{') { return(new Mapping(stream)); } // ----------------- // Try implicit mapping // ----------------- // This are mappings which are not preceded by a question // mark. The keys have to be scalars. #if (UNSTABLE && SUPPORT_IMPLICIT_MAPPINGS) // NOTE: This code can't be included in Mapping.cs // because of the way we are using to rewind the buffer. Node key, val; if (parseImplicitMappings) { // First Key/value pair stream.BuildLookaheadBuffer(); stream.StopAt(new char [] { ':' }); // Keys of implicit mappings can't be sequences, or other mappings // just look for scalars key = Scalar.Parse(stream, false); stream.DontStop(); Console.WriteLine("key: " + key); // Followed by a colon, so this is a real mapping if (stream.Char == ':') { stream.DestroyLookaheadBuffer(); Mapping mapping = new Mapping(); // Skip colon and spaces stream.Next(); stream.SkipSpaces(); // Parse the value Console.Write("using buffer: " + stream.UsingBuffer()); stream.Indent(); Console.Write("using buffer: " + stream.UsingBuffer()); // val = Parse (stream, false); Console.Write("<<"); while (!stream.EOF) { Console.Write(stream.Char); stream.Next(true); } Console.Write(">>"); val = new String(stream); Console.Write("using buffer: " + stream.UsingBuffer()); stream.UnIndent(); Console.Write("using buffer: " + stream.UsingBuffer()); Console.Write("<<"); while (!stream.EOF) { Console.Write(stream.Char); stream.Next(true); } Console.Write(">>"); Console.WriteLine("val: " + val); mapping.AddMappingNode(key, val); // Skip possible newline // NOTE: this can't be done by the drop-newline // method since this is not the end of a block while (stream.Char == '\n') { stream.Next(true); } // Other key/value pairs while (!stream.EOF) { stream.StopAt(new char [] { ':' }); stream.Indent(); key = Scalar.Parse(stream); stream.UnIndent(); stream.DontStop(); Console.WriteLine("key 2: " + key); if (stream.Char == ':') { // Skip colon and spaces stream.Next(); stream.SkipSpaces(); // Parse the value stream.Indent(); val = Parse(stream); stream.UnIndent(); Console.WriteLine("val 2: " + val); mapping.AddMappingNode(key, val); } else // TODO: Is this an error? { // NOTE: We can't recover from this error, // the last buffer has been destroyed, so // rewinding is impossible. throw new ParseException(stream, "Implicit mapping without value node"); } // Skip possible newline while (stream.Char == '\n') { stream.Next(); } } return(mapping); } stream.RewindLookaheadBuffer(); stream.DestroyLookaheadBuffer(); } #endif // ----------------- // No known data structure, assume this is a scalar // ----------------- Scalar scalar = Scalar.Parse(stream); // Skip trash while (!stream.EOF) { stream.Next(); } return(scalar); }