static bool ParseExpression()

in absl/debugging/internal/demangle.cc [1636:1741]


static bool ParseExpression(State *state) {
  ComplexityGuard guard(state);
  if (guard.IsTooComplex()) return false;
  if (ParseTemplateParam(state) || ParseExprPrimary(state)) {
    return true;
  }

  ParseState copy = state->parse_state;

  // Object/function call expression.
  if (ParseTwoCharToken(state, "cl") && OneOrMore(ParseExpression, state) &&
      ParseOneCharToken(state, 'E')) {
    return true;
  }
  state->parse_state = copy;

  // Clang-specific "cp <simple-id> <expression>* E"
  //   https://clang.llvm.org/doxygen/ItaniumMangle_8cpp_source.html#l04338
  if (ParseTwoCharToken(state, "cp") && ParseSimpleId(state) &&
      ZeroOrMore(ParseExpression, state) && ParseOneCharToken(state, 'E')) {
    return true;
  }
  state->parse_state = copy;

  // Function-param expression (level 0).
  if (ParseTwoCharToken(state, "fp") && Optional(ParseCVQualifiers(state)) &&
      Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
    return true;
  }
  state->parse_state = copy;

  // Function-param expression (level 1+).
  if (ParseTwoCharToken(state, "fL") && Optional(ParseNumber(state, nullptr)) &&
      ParseOneCharToken(state, 'p') && Optional(ParseCVQualifiers(state)) &&
      Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
    return true;
  }
  state->parse_state = copy;

  // Parse the conversion expressions jointly to avoid re-parsing the <type> in
  // their common prefix.  Parsed as:
  // <expression> ::= cv <type> <conversion-args>
  // <conversion-args> ::= _ <expression>* E
  //                   ::= <expression>
  //
  // Also don't try ParseOperatorName after seeing "cv", since ParseOperatorName
  // also needs to accept "cv <type>" in other contexts.
  if (ParseTwoCharToken(state, "cv")) {
    if (ParseType(state)) {
      ParseState copy2 = state->parse_state;
      if (ParseOneCharToken(state, '_') && ZeroOrMore(ParseExpression, state) &&
          ParseOneCharToken(state, 'E')) {
        return true;
      }
      state->parse_state = copy2;
      if (ParseExpression(state)) {
        return true;
      }
    }
  } else {
    // Parse unary, binary, and ternary operator expressions jointly, taking
    // care not to re-parse subexpressions repeatedly. Parse like:
    //   <expression> ::= <operator-name> <expression>
    //                    [<one-to-two-expressions>]
    //   <one-to-two-expressions> ::= <expression> [<expression>]
    int arity = -1;
    if (ParseOperatorName(state, &arity) &&
        arity > 0 &&  // 0 arity => disabled.
        (arity < 3 || ParseExpression(state)) &&
        (arity < 2 || ParseExpression(state)) &&
        (arity < 1 || ParseExpression(state))) {
      return true;
    }
  }
  state->parse_state = copy;

  // sizeof type
  if (ParseTwoCharToken(state, "st") && ParseType(state)) {
    return true;
  }
  state->parse_state = copy;

  // Object and pointer member access expressions.
  if ((ParseTwoCharToken(state, "dt") || ParseTwoCharToken(state, "pt")) &&
      ParseExpression(state) && ParseType(state)) {
    return true;
  }
  state->parse_state = copy;

  // Pointer-to-member access expressions.  This parses the same as a binary
  // operator, but it's implemented separately because "ds" shouldn't be
  // accepted in other contexts that parse an operator name.
  if (ParseTwoCharToken(state, "ds") && ParseExpression(state) &&
      ParseExpression(state)) {
    return true;
  }
  state->parse_state = copy;

  // Parameter pack expansion
  if (ParseTwoCharToken(state, "sp") && ParseExpression(state)) {
    return true;
  }
  state->parse_state = copy;

  return ParseUnresolvedName(state);
}