/// <summary> /// /// </summary> /// <param name="reader"></param> /// <returns></returns> public static ABNF_Repetition Parse(System.IO.StringReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } /* * repetition = [repeat] element * repeat = 1*DIGIT / (*DIGIT "*" *DIGIT) * element = rulename / group / option / char-val / num-val / prose-val */ int min = 0; int max = int.MaxValue; // --- range ------------------------------------ if (char.IsDigit((char)reader.Peek())) { StringBuilder minString = new StringBuilder(); while (char.IsDigit((char)reader.Peek())) { minString.Append((char)reader.Read()); } min = Convert.ToInt32(minString.ToString()); } if (reader.Peek() == '*') { reader.Read(); } if (char.IsDigit((char)reader.Peek())) { StringBuilder maxString = new StringBuilder(); while (char.IsDigit((char)reader.Peek())) { maxString.Append((char)reader.Read()); } max = Convert.ToInt32(maxString.ToString()); } //----------------------------------------------- // End of stream reached. if (reader.Peek() == -1) { return(null); } // We have rulename. else if (char.IsLetter((char)reader.Peek())) { return(new ABNF_Repetition(min, max, ABNF_RuleName.Parse(reader))); } // We have group. else if (reader.Peek() == '(') { return(new ABNF_Repetition(min, max, ABFN_Group.Parse(reader))); } // We have option. else if (reader.Peek() == '[') { return(new ABNF_Repetition(min, max, ABNF_Option.Parse(reader))); } // We have char-val. else if (reader.Peek() == '\"') { return(new ABNF_Repetition(min, max, ABNF_CharVal.Parse(reader))); } // We have num-val. else if (reader.Peek() == '%') { // Eat '%'. reader.Read(); if (reader.Peek() == 'd') { return(new ABNF_Repetition(min, max, ABNF_DecVal.Parse(reader))); } else { throw new ParseException("Invalid 'num-val' value '" + reader.ReadToEnd() + "'."); } } // We have prose-val. else if (reader.Peek() == '<') { return(new ABNF_Repetition(min, max, ABNF_ProseVal.Parse(reader))); } return(null); }