|
using System;
using System.Collections.Generic;
using System.Text;
namespace LumiSoft.Net.ABNF
{
/// <summary>
/// This class represent ABNF "repetition". Defined in RFC 5234 4.
/// </summary>
public class ABNF_Repetition
{
private int m_Min = 0;
private int m_Max = int.MaxValue;
private ABNF_Element m_pElement = null;
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="min">Minimum repetitions.</param>
/// <param name="max">Maximum repetitions.</param>
/// <param name="element">Repeated element.</param>
/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
/// <exception cref="ArgumentNullException">Is raised when <b>element</b> is null reference.</exception>
public ABNF_Repetition(int min,int max,ABNF_Element element)
{
if(min < 0){
throw new ArgumentException("Argument 'min' value must be >= 0.");
}
if(max < 0){
throw new ArgumentException("Argument 'max' value must be >= 0.");
}
if(min > max){
throw new ArgumentException("Argument 'min' value must be <= argument 'max' value.");
}
if(element == null){
throw new ArgumentNullException("element");
}
m_Min = min;
m_Max = max;
m_pElement = element;
}
/// <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;
}
#region Properties implementation
/// <summary>
/// Gets minimum repetitions.
/// </summary>
public int Min
{
get{ return m_Min; }
}
/// <summary>
/// Gets maximum repetitions.
/// </summary>
public int Max
{
get{ return m_Max; }
}
/// <summary>
/// Gets repeated element.
/// </summary>
public ABNF_Element Element
{
get{ return m_pElement; }
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.