in include/llvm/Support/YAMLTraits.h [537:631]
inline bool isNumeric(StringRef S) {
const static auto skipDigits = [](StringRef Input) {
return Input.drop_front(
std::min(Input.find_first_not_of("0123456789"), Input.size()));
};
// Make S.front() and S.drop_front().front() (if S.front() is [+-]) calls
// safe.
if (S.empty() || S.equals("+") || S.equals("-"))
return false;
if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
return true;
// Infinity and decimal numbers can be prefixed with sign.
StringRef Tail = (S.front() == '-' || S.front() == '+') ? S.drop_front() : S;
// Check for infinity first, because checking for hex and oct numbers is more
// expensive.
if (Tail.equals(".inf") || Tail.equals(".Inf") || Tail.equals(".INF"))
return true;
// Section 10.3.2 Tag Resolution
// YAML 1.2 Specification prohibits Base 8 and Base 16 numbers prefixed with
// [-+], so S should be used instead of Tail.
if (S.startswith("0o"))
return S.size() > 2 &&
S.drop_front(2).find_first_not_of("01234567") == StringRef::npos;
if (S.startswith("0x"))
return S.size() > 2 && S.drop_front(2).find_first_not_of(
"0123456789abcdefABCDEF") == StringRef::npos;
// Parse float: [-+]? (\. [0-9]+ | [0-9]+ (\. [0-9]* )?) ([eE] [-+]? [0-9]+)?
S = Tail;
// Handle cases when the number starts with '.' and hence needs at least one
// digit after dot (as opposed by number which has digits before the dot), but
// doesn't have one.
if (S.startswith(".") &&
(S.equals(".") ||
(S.size() > 1 && std::strchr("0123456789", S[1]) == nullptr)))
return false;
if (S.startswith("E") || S.startswith("e"))
return false;
enum ParseState {
Default,
FoundDot,
FoundExponent,
};
ParseState State = Default;
S = skipDigits(S);
// Accept decimal integer.
if (S.empty())
return true;
if (S.front() == '.') {
State = FoundDot;
S = S.drop_front();
} else if (S.front() == 'e' || S.front() == 'E') {
State = FoundExponent;
S = S.drop_front();
} else {
return false;
}
if (State == FoundDot) {
S = skipDigits(S);
if (S.empty())
return true;
if (S.front() == 'e' || S.front() == 'E') {
State = FoundExponent;
S = S.drop_front();
} else {
return false;
}
}
assert(State == FoundExponent && "Should have found exponent at this point.");
if (S.empty())
return false;
if (S.front() == '+' || S.front() == '-') {
S = S.drop_front();
if (S.empty())
return false;
}
return skipDigits(S).empty();
}