Exemple #1
0
bool Scanner::tryParseTypeList(TokenStore::iterator& pos) {
  for (int parsed = 0;; parsed++) {
    if (pos->t == '+' || pos->t == '-') {
      nextLookahead(pos);
    }
    auto cpPos = pos;
    if (!tryParseNSType(cpPos)) {
      if (parsed > 0) {
        pos = cpPos;
        return true;
      } else {
        return false;
      }
    }
    pos = cpPos;

    while (pos->t == T_AS || pos->t == T_SUPER) {
      nextLookahead(pos);
      if (!tryParseNSType(pos)) {
        return false;
      }
    }
    if (pos->t != ',') return true;
    nextLookahead(pos);
  }
}
Exemple #2
0
bool Scanner::tryParseTypeList(TokenStore::iterator& pos) {
  for (;;) {
    if (!tryParseNSType(pos)) return false;
    if (pos->t == T_AS) {
      nextLookahead(pos);
      if (!tryParseNSType(pos)) return false;
    }
    if (pos->t != ',') return true;
    nextLookahead(pos);
  }
}
Exemple #3
0
bool Scanner::tryParseShapeMemberList(TokenStore::iterator& pos) {
  assert(pos->t != ')'); // already determined to be nonempty

  for (;;) {
    if (!nextIfToken(pos, T_CONSTANT_ENCAPSED_STRING) ||
        !nextIfToken(pos, T_DOUBLE_ARROW)) {
      return false;
    }
    if (!tryParseNSType(pos)) return false;
    if (pos->t == ')') return true;
    if (!nextIfToken(pos, ',')) return false;
    if (pos->t == ')') return true;
  }

  return false;
}
Exemple #4
0
bool Scanner::tryParseFuncTypeList(TokenStore::iterator& pos) {
  for (int parsed = 0;;parsed++) {
    if (pos->t == T_ELLIPSIS) {
      nextLookahead(pos);
      return true;
    }
    auto cpPos = pos;
    if (!tryParseNSType(cpPos)) {
      if (parsed > 0) {
        pos = cpPos;
        return true;
      } else {
        return false;
      }
    }
    pos = cpPos;
    if (pos->t != ',') return true;
    nextLookahead(pos);
  }
}
Exemple #5
0
bool Scanner::tryParseNonEmptyLambdaParams(TokenStore::iterator& pos) {
  for (;; nextLookahead(pos)) {
    if (pos->t != T_VARIABLE) {
      if (pos->t == T_ELLIPSIS) {
        nextLookahead(pos);
        return true;
      }
      if (!tryParseNSType(pos)) return false;
      if (pos->t == '&') {
        nextLookahead(pos);
      }
      if (pos->t != T_VARIABLE) return false;
    }
    nextLookahead(pos);
    if (pos->t == '=') {
      nextLookahead(pos);
      parseApproxParamDefVal(pos);
    }
    if (pos->t != ',') return true;
  }
}
Exemple #6
0
int Scanner::getNextToken(ScannerToken &t, Location &l) {
  int tokid;
  bool la = !m_lookahead.empty();
  tokid = fetchToken(t, l);
  if (LIKELY(!isUnresolved(tokid))) {
    // In the common case, we don't have to perform any resolution
    // and we can just return the token
    if (UNLIKELY(la)) {
      // If we pulled a lookahead token, we need to remove it from
      // the lookahead store
      m_lookahead.popFront();
    }
    return tokid;
  }

  if (!la) {
    // If this token didn't come from the lookahead store, we
    // need to stash it there
    TokenStore::iterator it = m_lookahead.appendNew();
    LookaheadToken ltd = { t, l, tokid };
    *it = ltd;
  }

  switch (tokid) {
  case T_UNRESOLVED_NEWTYPE:
  case T_UNRESOLVED_TYPE: {
    auto pos = m_lookahead.begin();
    auto typePos = pos;
    nextLookahead(pos);
    if (isValidClassConstantName(pos->t)) {
      typePos->t = tokid == T_UNRESOLVED_TYPE ? T_TYPE : T_NEWTYPE;
    } else {
      typePos->t = T_STRING;
    }
    break;
  }
  case T_UNRESOLVED_LT: {
    // Look at subsequent tokens to determine if the '<' character
    // is the start of a type list
    auto pos = m_lookahead.begin();
    auto ltPos = pos;
    nextLookahead(pos);
    ++m_lookaheadLtDepth;
    bool isTypeList = tryParseTypeList(pos);
    --m_lookaheadLtDepth;
    if (isTypeList && pos->t == '>') {
      ltPos->t = T_TYPELIST_LT;
      pos->t = T_TYPELIST_GT;
    } else {
      ltPos->t = '<';
    }
    break;
  }
  case T_UNRESOLVED_OP: {
    // Look at subsequent tokens to determine if the '(' character
    // is the start of a lambda expression
    auto pos = m_lookahead.begin();
    auto opPos = pos;
    nextLookahead(pos);
    if (pos->t != ')' && pos->t != T_LAMBDA_CP) {
      if (!tryParseNonEmptyLambdaParams(pos) || pos->t != ')') {
        opPos->t = '(';
        break;
      }
    }
    auto cpPos = pos;
    nextLookahead(pos);
    if (pos->t == ':') {
      nextLookahead(pos);
      if (!tryParseNSType(pos)) {
        opPos->t = '(';
        break;
      }
    }
    if (pos->t == T_LAMBDA_ARROW) {
      opPos->t = T_LAMBDA_OP;
      cpPos->t = T_LAMBDA_CP;
    } else {
      opPos->t = '(';
    }
    break;
  }
  default: always_assert(0);
  }

  tokid = fetchToken(t, l);
  // We pulled a lookahead token, we need to remove it from the
  // lookahead store
  m_lookahead.popFront();
  return tokid;
}
Exemple #7
0
bool
Scanner::tryParseNSType(TokenStore::iterator& pos) {
  if (pos->t == '@') {
    nextLookahead(pos);
  }
  if (pos->t == '?') {
    nextLookahead(pos);
  }
  if (pos->t == '(' || pos->t == T_UNRESOLVED_OP) {
    nextLookahead(pos);
    if (pos->t == T_FUNCTION) {
      nextLookahead(pos);
      if (pos->t != '(') return false;
      nextLookahead(pos);
      if (pos->t != ')') {
        if (!tryParseFuncTypeList(pos)) return false;
        if (pos->t != ')') return false;
      }
      nextLookahead(pos);
      if (pos->t == ')') {
        nextLookahead(pos);
        return true;
      }
      if (pos->t != ':') return false;
      nextLookahead(pos);
      if (!tryParseNSType(pos)) return false;
      if (pos->t != ')') return false;
      nextLookahead(pos);
      return true;
    }
    if (!tryParseTypeList(pos)) return false;
    if (pos->t != ')') return false;
    nextLookahead(pos);
    return true;
  }
  if (pos->t == T_NAMESPACE) {
    nextLookahead(pos);
    if (pos->t != T_NS_SEPARATOR) return false;
    nextLookahead(pos);
  } else if (pos->t == T_NS_SEPARATOR) {
    nextLookahead(pos);
  }
  for (;;) {
    switch (pos->t) {
      case T_STRING:
      case T_SUPER:
      case T_XHP_ATTRIBUTE:
      case T_XHP_CATEGORY:
      case T_XHP_CHILDREN:
      case T_XHP_REQUIRED:
      case T_ENUM:
      case T_ARRAY:
      case T_CALLABLE:
      case T_UNRESOLVED_TYPE:
      case T_UNRESOLVED_NEWTYPE:
        nextLookahead(pos);
        break;
      case T_SHAPE:
        return tryParseShapeType(pos);
      case T_XHP_LABEL:
        nextLookahead(pos);
        return true;
      default:
        return false;
    }
    if (pos->t == T_UNRESOLVED_LT) {
      TokenStore::iterator ltPos = pos;
      nextLookahead(pos);
      ++m_lookaheadLtDepth;
      bool isTypeList = tryParseTypeList(pos);
      --m_lookaheadLtDepth;
      if (!isTypeList || pos->t != '>') {
        ltPos->t = '<';
        return false;
      }
      ltPos->t = T_TYPELIST_LT;
      pos->t = T_TYPELIST_GT;
      nextLookahead(pos);
      return true;
    }
    if (pos->t != T_NS_SEPARATOR && pos->t != T_DOUBLE_COLON) {
      return true;
    }
    nextLookahead(pos);
  }
}