//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;

namespace CommonHelpers {

//**************************************************************************************************
partial class CmdLineParametersScan {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void DoScan()
{
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   if ( !IsParamOpen ) SkipSpaces();
   if ( IsInEnd ) return;
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   char ch = CurrentChar;
   if ( !IsParamOpen )
   {
      IsParamOpen = true;
      ParameterStartPos = Pos;
      if ( IsParamQuoteCharacter( ch ) )
         QuoteCount = 1;
      else
      if ( IsSwitchCharacter( ch ) )
      {
         IsHyphenSwitch = IsSwitchCharacterHyphen( ch );
         SwitchKeyLength = 0;
      }
      goto INCREMENT_POS;
   }
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// === IsParamOpen: ===
   if ( IsParamQuoteCharacter( ch ) )
   {
      if ( HArith.IsOdd( ++QuoteCount ) && IsPreviousCharacterQuote )
         { Pos++; return; }
      if ( SwitchKeyLength >= 0 )
         if ( HasSwitchKeyFromArgsSeparator )
         {
            if ( KeyArgumentBuffer.Length > 0 && QuoteCount == 0 )
               throw CreateParseExceptionWithPos(
                  "Unexpected double quote character in switch argument. "+
                  "(You may use double quotation marks for switch argument embracement, "+
                  "in conjunction with zero or more duplicated double quotes in the content.)" );
            AppendKeyArgumentBuffer( ch );
         }
         else
            throw CreateParseExceptionWithPos(
               "Unexpected double quote character in switch keyword zone." );
      goto INCREMENT_POS;
   }
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// === IsParamOpen && !IsParamQuoteCharacter( ch ): ===
   if ( HArith.IsEven( QuoteCount ) )
   {
      if ( char.IsWhiteSpace( ch ) )
         { FlushParameter(); return; }
      if ( IsPreviousCharacterQuote )
      {
         if ( IsSwitchKeyArgumentsSeparator( ch ) )
         {
            AppendKeyArgumentListFromBuffer();
            IsKeyArgumentOpen = true;
            goto INCREMENT_POS;
         }
         throw CreateParseExceptionWithPos(
            "Whitespace or double quote character or \"end of string\" was expected." );
      }
   }
   if ( QuoteCount == 0 )
   {
      if ( IsSwitchCharacterSlash( ch ) && KeyArgumentBuffer.Length > 0 )
         throw CreateParseExceptionWithPos(
            "Slash character is permitted only at the beginning of the switch." );
      if ( IsSwitchKeyFromArgsSeparator( ch ) && SwitchKeyLength >= 0 )
      {
         if ( HasSwitchKeyFromArgsSeparator )
            throw CreateParseExceptionWithPos(
               "Repeated switch argument separator character. "+
               "(You may use quotation marks to embrace "+
               "any character as part of switch argument.)" );
         if ( !HasSwitchKeyFromArgsSeparator )
         {
            if ( SwitchKeyLength == 0 )
               throw CreateParseExceptionWithPos(
                  "Unexpected switch argument separator: Switch key is empty." );
            CheckSwitchKey();
         }
         HasSwitchKeyFromArgsSeparator = true;
         goto INCREMENT_POS;
      }
   }
   if ( SwitchKeyLength >= 0 )
      if ( !HasSwitchKeyFromArgsSeparator )
      {
         if ( IsSwitchCharacterHyphen( ch ) )
            if ( SwitchKeyLength == 0 )
               throw CreateParseExceptionWithPos(
                  "Unexpected hyphen character at the begining of switch key." );
            else
               if ( PreviousCharacter == HCmdLineParametersParser.SwitchCharacterHyphen )
                  throw CreateParseExceptionWithPos(
                     "Repeated hyphen character in switch key." );
         SwitchKeyLength++;
      }
      else
         AppendKeyArgumentBuffer( ch );
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
INCREMENT_POS:
   Pos++;
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}

//==================================================================================================

void FlushParameter()
{
   if ( !IsParamOpen ) return;

   string
      paramValue = LineOfParameters.Substring( ParameterStartPos, Pos-ParameterStartPos ),
      nakedValue = null;
   int len = paramValue.Length;
   if ( len == 0 )
      throw new InvalidOperationException(
         "Attempt to flush empty parameter in command line parameters parse." );
   if ( QuoteCount > 0 )
   {
      if ( HArith.IsOdd( QuoteCount ) )
         throw CreateParseExceptionWithPos(
            "Unclosed quotation mark in parameter encountered." );
      if ( IsParamQuoteCharacter( paramValue[ 0 ] ) )
      {
         if ( !IsParamQuoteCharacter(HString.LastChar( paramValue )) )
            throw CreateParseExceptionWithPos(
               "Leading quote character of parameter requies its pair quote at the end "+
               "of the parameter." );
         nakedValue = paramValue.Substring( 1, len - 2 );
      }
   }
   if ( nakedValue == null )
      nakedValue = paramValue;

   CheckSwitchKey();

   if ( IsKeyArgumentOpen )
   {
      if ( KeyArgumentBuffer.Length == 0 && NakedKeyArguments.Count > 0 )
         throw CreateParseExceptionWithPos(
            "Empty switch key argument must be embraced with pair quotes if used as element "+
            "of key argument list (comma separated array)." );
      AppendKeyArgumentListFromBuffer();
   }

   HCmdLineParameter parameter;
   string switchKey = SwitchKeyLength > 0 ? paramValue.Substring( 1, SwitchKeyLength ) : null;
   var keyDefinition = switchKey != null ? Parser.GetSwitchKeyDefinition( switchKey ) : null;
   try {
      parameter = new HCmdLineParameter(
         ParametersStartInFullCmdLine + ParameterStartPos, ParameterStartPos,
         paramValue, nakedValue, switchKey, IsHyphenSwitch,
         switchKey != null && HasSwitchKeyFromArgsSeparator ?
            NakedKeyArguments.ToArray() : null,
         keyDefinition != null ? keyDefinition.Duplicate() : null ); }
   catch (ArgumentException e) {
      throw CreateParseExceptionWithPos(
         "Unexpected error in \"HCmdLineParameter\" constructor:\n"+
         "{0}.", e.Message ); }

   ParamList.Add( parameter );
   ResetParamProperties();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // CmdLineParametersScan
//**************************************************************************************************

} // CommonHelpers
