/**
        Check if current item is a "value" tag with the given name and if so
        consumes that item and retrive the value.

        \param[in]  name     Name of value tag to check for.
        \param[out] value    Return value.
        \param[in]  dothrow  Should this function throw an exception if current
                             item is not a value tag with the given name.

        \returns   true if current item is a value tag with the given name, else
                   false.
    */
    bool SCXFilePersistDataReader::ConsumeValue(const std::wstring& name, std::wstring& value, bool dothrow /*= false*/)
    {
        std::wstreampos pos = m_Stream->tellg();
        try
        {
            Consume(L"<");
            Consume(L"Value");
            Consume(L"Name");
            Consume(L"=");
            ConsumeString(name);
            Consume(L"Value");
            Consume(L"=");
            value = ConsumeString();
            Consume(L"/>");
        }
        catch (PersistUnexpectedDataException& e)
        {
            m_Stream->seekg(pos);
            if (dothrow)
            {
                throw e;
            }
            return false;
        }
        
        return true;
    }
    /**
        Check if current item is a "start group" tag with the given name and if so
        consumes that item.

        \param[in] name     Name of start group tag to check for.
        \param[in] dothrow  Should this function throw an exception if current
                            item is not a start group tag with the given name.
        
        \returns   true if current item is a start group tag with the given name,
                   else false.
        \throws    PersistUnexpectedDataException if next input is not the start of
                   expected group.
    */
    bool SCXFilePersistDataReader::ConsumeStartGroup(const std::wstring& name, bool dothrow /*= false*/)
    {
        std::wstreampos pos = m_Stream->tellg();
        try
        {
            Consume(L"<");
            Consume(L"Group");
            Consume(L"Name");
            Consume(L"=");
            ConsumeString(name);
            Consume(L">");
        }
        catch (PersistUnexpectedDataException& e)
        {
            m_Stream->seekg(pos);
            if (dothrow)
            {
                throw e;
            }
            return false;
        }
        
        m_StartedGroups.push_front(name);

        return true;
        
    }
    /**
        Constructor.

        \param[in]  path        Path where persisted data should be read.
    */
    SCXFilePersistDataReader::SCXFilePersistDataReader(const SCXFilePath& path) :
        m_StartedGroups()
    {
        m_Stream = SCXFile::OpenFstream(path, std::ios_base::in);

        std::wstreampos pos = m_Stream->tellg();

        try
        {
            Consume(L"<?xml");
            Consume(L"version");
            Consume(L"=");
            ConsumeString(L"1.0");
            Consume(L"encoding");
            Consume(L"=");
            Consume(L"'UTF-8'");
            Consume(L"standalone");
            Consume(L"=");
            Consume(L"'yes'");
            Consume(L"?>");

            Consume(L"<");
            Consume(L"SCXPersistedData");
            Consume(L"Version");
            Consume(L"=");
            std::wstring versionString = ConsumeString();
            Consume(L">");
            m_Version = StrToUInt(versionString);
        }
        catch (PersistUnexpectedDataException& e)
        {
            m_Stream->seekg(pos);
            throw e;
        }
        catch (SCXCoreLib::SCXNotSupportedException&)
        {
            std::wstreampos errorpos = m_Stream->tellg();
            m_Stream->seekg(pos);
            throw PersistUnexpectedDataException(L"The Version attribute should have an unsigned integer value",
                                                 errorpos, SCXSRCLOCATION);
        }
    }
bool TGztParser::ParseGztFileOption(TGztFileDescriptorProto* file) {
  DO(Consume("option"));
  Stroka option_name;
  DO(ConsumeString(&option_name, "Expected an option name."));
  if (option_name == "strip-names" || option_name == "strip_names" || option_name == "strip names")
      file->set_strip_names(true);
  //else if <other option here>
  else {
      AddError(Substitute("Unrecognized option \"$0\".", option_name));
      return false;
  }
  DO(Consume(";"));
  return true;
}
bool TGztParser::ParseEncoding(Stroka* encoding_name) {
  DO(Consume("encoding"));
  DO(ConsumeString(encoding_name, "Expected a string naming the encoding to use."));
  ECharset enc = CharsetByName(encoding_name->c_str());
  if (enc == CODES_UNKNOWN) {
      AddError(Substitute("Unrecognized encoding \"$0\".", *encoding_name));
      return false;
  }
  DO(Consume(";"));

  SetEncoding(enc);

  return true;
}
bool TGztParser::ParseArticleDefinition(TArticleDescriptorProto* article)
{
  RecordLocation(article, NProtoBuf::DescriptorPool::ErrorCollector::OTHER);
  DO(ConsumeType(article->mutable_type(), "Expected article type."));

  if (LookingAt('{'))
      article->mutable_name()->clear(); // allow articles without names
  else {
      if (LookingAtType(Tokenizer::TYPE_STRING)) {
          DO(ConsumeString(article->mutable_name(), "Expected article name."));
      }
      else
          DO(ConsumeIdentifier(article->mutable_name(), "Expected article name."));
  }

  DO(ParseArticleBlock(article->mutable_field()));
  return true;
}
bool HTMLLexer::AdvanceOneToken( int &outToken, TokenList *outTokens )
{
	outToken = -1;

	if (!fLexerInput)
		return false;

	// There can be any combination of newlines and whitespaces preceeding semantic tokens,
	// so we're going to loop until we don't find either.
	while (fLexerInput->HasMoreChars())
	{
		bool consumedWhitespace = false;
		bool consumedNewLine = false;
		if (!SkipWhitespaces( consumedWhitespace, outTokens ))
			return false;

		// HTML also treats newlines as a whitespace
		while (fLexerInput->HasMoreChars() && IsLineEnding( fLexerInput->PeekAtNextChar() ))
		{
			// Eat the line ending
			ConsumeLineEnding( fLexerInput->MoveToNextChar() );
			consumedNewLine = true;
		}

		// If we're done consuming newlines and whitespaces, then we're done with this loop
		if (!consumedWhitespace && !consumedNewLine)
			break;
	}
	if (!fLexerInput->HasMoreChars())
		return false;

	// Take a peek at what sort of token we're about to deal with. 
	UniChar	uChar = fLexerInput->PeekAtNextChar();
	sLONG stringType;
	sLONG stringValue;

	if( (outToken = ConsumePossiblePunctuation(uChar, outTokens)) != 0 )
	{
	}
	else if (IsStringStart( uChar, stringType, stringValue ))
	{
		VString	vstrQuoted;
		if (!ConsumeString( &vstrQuoted, outTokens, stringType, stringValue ))
		{
			return false;
		}
		outToken = stringValue;
		fLastTokenText = vstrQuoted;
	}
	else if (IsIdentifierStart( uChar ))
	{
		// The base class assumes we've consumed the first character already for this call.  We should
		// rectify this some day, as it's very confusing.
		fLexerInput->MoveToNextChar();
		VString *vstrNAME = ConsumeIdentifier();
		if (!vstrNAME)
		{
			return false;
		}

		outToken = HTMLLexemes::TEXT;
		if (outTokens)	outTokens->push_back( new HTMLLexerToken( ILexerToken::TT_NAME, fLexerInput->GetCurrentPosition() - vstrNAME->GetLength(), vstrNAME->GetLength(), *vstrNAME, outToken ) );

		fLastTokenText = *vstrNAME;
		delete vstrNAME;
	}
	else
	{
		return false;
	}
	
	SetLastToken( outToken );
	return true;
}
bool TParserBase::ConsumeUtf8String(Stroka* output, const char* error)
{
    DO(ConsumeString(output, error));
    return RecodeToUtf8(*output);
}
bool TGztParser::ParseImport(Stroka* import_filename) {
  DO(Consume("import"));
  DO(ConsumeString(import_filename, "Expected a string naming the file to import."));
  DO(Consume(";"));
  return true;
}