// <special-name> ::= TV <type>
//                ::= TT <type>
//                ::= TI <type>
//                ::= TS <type>
//                ::= Tc <call-offset> <call-offset> <(base) encoding>
//                ::= GV <(object) name>
//                ::= T <call-offset> <(base) encoding>
// G++ extensions:
//                ::= TC <type> <(offset) number> _ <(base) type>
//                ::= TF <type>
//                ::= TJ <type>
//                ::= GR <name>
//                ::= GA <encoding>
//                ::= Th <call-offset> <(base) encoding>
//                ::= Tv <call-offset> <(base) encoding>
//
// Note: we don't care much about them since they don't appear in
// stack traces.  The are special data.
static bool ParseSpecialName(State *state) {
  State copy = *state;
  if (ParseChar(state, 'T') &&
      ParseCharClass(state, "VTIS") &&
      ParseType(state)) {
    return true;
  }
  *state = copy;

  if (ParseTwoChar(state, "Tc") && ParseCallOffset(state) &&
      ParseCallOffset(state) && ParseEncoding(state)) {
    return true;
  }
  *state = copy;

  if (ParseTwoChar(state, "GV") &&
      ParseName(state)) {
    return true;
  }
  *state = copy;

  if (ParseChar(state, 'T') && ParseCallOffset(state) &&
      ParseEncoding(state)) {
    return true;
  }
  *state = copy;

  // G++ extensions
  if (ParseTwoChar(state, "TC") && ParseType(state) &&
      ParseNumber(state) && ParseChar(state, '_') &&
      DisableAppend(state) &&
      ParseType(state)) {
    RestoreAppend(state, copy.append);
    return true;
  }
  *state = copy;

  if (ParseChar(state, 'T') && ParseCharClass(state, "FJ") &&
      ParseType(state)) {
    return true;
  }
  *state = copy;

  if (ParseTwoChar(state, "GR") && ParseName(state)) {
    return true;
  }
  *state = copy;

  if (ParseTwoChar(state, "GA") && ParseEncoding(state)) {
    return true;
  }
  *state = copy;

  if (ParseChar(state, 'T') && ParseCharClass(state, "hv") &&
      ParseCallOffset(state) && ParseEncoding(state)) {
    return true;
  }
  *state = copy;
  return false;
}
// <local-name> := Z <(function) encoding> E <(entity) name>
//                 [<discriminator>]
//              := Z <(function) encoding> E s [<discriminator>]
static bool ParseLocalName(State *state) {
  State copy = *state;
  if (ParseChar(state, 'Z') && ParseEncoding(state) &&
      ParseChar(state, 'E') && MaybeAppend(state, "::") &&
      ParseName(state) && Optional(ParseDiscriminator(state))) {
    return true;
  }
  *state = copy;

  if (ParseChar(state, 'Z') && ParseEncoding(state) &&
      ParseTwoChar(state, "Es") && Optional(ParseDiscriminator(state))) {
    return true;
  }
  *state = copy;
  return false;
}
// <expr-primary> ::= L <type> <(value) number> E
//                ::= L <type> <(value) float> E
//                ::= L <mangled-name> E
//                // A bug in g++'s C++ ABI version 2 (-fabi-version=2).
//                ::= LZ <encoding> E
static bool ParseExprPrimary(State *state) {
  State copy = *state;
  if (ParseChar(state, 'L') && ParseType(state) &&
      ParseNumber(state) &&
      ParseChar(state, 'E')) {
    return true;
  }
  *state = copy;

  if (ParseChar(state, 'L') && ParseType(state) &&
      ParseFloatNumber(state) &&
      ParseChar(state, 'E')) {
    return true;
  }
  *state = copy;

  if (ParseChar(state, 'L') && ParseMangledName(state) &&
      ParseChar(state, 'E')) {
    return true;
  }
  *state = copy;

  if (ParseTwoChar(state, "LZ") && ParseEncoding(state) &&
      ParseChar(state, 'E')) {
    return true;
  }
  *state = copy;

  return false;
}
//-----------------------------------------------------------------------
Ptr<InStm> FB2TOEPUB_DECL CreateInUnicodeStm(InStm *stm)
{
    // analize bit order mark to get rough encoding
    const char *fromcode = RoughEncoding(stm);

    // parse <?xml version="1.0" encoding="..."?>
    // to refine the encoding
    Ptr<InStm> tmp = new InStmUtf8(stm, fromcode);
    return new InStmUtf8(stm, ParseEncoding(tmp).c_str());
}
// <mangled-name> ::= _Z <encoding>
static bool ParseMangledName(State *state) {
  if (ParseTwoChar(state, "_Z") && ParseEncoding(state)) {
    // Append trailing version suffix if any.
    // ex. _Z3foo@@GLIBCXX_3.4
    if (state->mangled_cur < state->mangled_end &&
        state->mangled_cur[0] == '@') {
      MaybeAppend(state, state->mangled_cur);
      state->mangled_cur = state->mangled_end;
    }
    return true;
  }
  return false;
}
bool TGztParser::ParseTopLevelStatement(TGztFileDescriptorProto* file)
{
    if (TryConsume(';'))
        // empty statement; ignore
        return true;

    else if (LookingAt("import"))
        return ParseImport(file->add_dependency());

    // syntax extension: encoding used for interpreting string literals and article identifiers.
    else if (LookingAt("encoding"))
        return ParseEncoding(file->mutable_encoding());

    // syntax extension: various gzt compilation options
    else if (LookingAt("option"))
        return ParseGztFileOption(file);

    else if (LookingAtType(Tokenizer::TYPE_IDENTIFIER))
        return ParseArticleDefinition(file->add_article());
    else {
        AddError("Expected top-level statement (e.g. article definition).");
        return false;
    }
}
// <mangled-name> ::= _Z <encoding>
static bool ParseMangledName(State *state) {
  return ParseTwoCharToken(state, "_Z") && ParseEncoding(state);
}
ECharset CCommonParm::GetOutputEncoding() const {
    if (NULL != Config.Get() && Config->has_output() && Config->output().has_encoding())
        return ParseEncoding(Config->output().encoding());

    return CODES_UTF8;
}