Index: include/llvm/Support/ParseHelper.h =================================================================== --- /dev/null +++ include/llvm/Support/ParseHelper.h @@ -0,0 +1,64 @@ +//===- ParseHelper.h - Simple parser helper class ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ParseHelper class, intended to help implement simple +// parsers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PARSEHELPER_H +#define LLVM_SUPPORT_PARSEHELPER_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +class ParseHelper +{ +public: + ParseHelper(StringRef S) + : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(nullptr) {} + + // Return true if string literal is next. + bool Next(StringRef S); + + // Return true if number is next. + // Output N only if number is next. + bool Next(unsigned &N); + + // Return true if string literal is found. + // When true, P marks begin-position of S in content. + bool Search(StringRef S, bool EnsureStartOfWord = false); + + // Return true if a CloseBrace that closes the OpenBrace at the current nest + // level is found. When true, P marks begin-position of CloseBrace. + bool SearchClosingBrace(StringRef OpenBrace, StringRef CloseBrace); + + // Advance 1-past previous next/search. + // Behavior is undefined if previous next/search failed. + bool Advance(); + + // Skip zero or more whitespace. + void SkipWhitespace(); + + // Return true if EOF reached. + bool Done(); + + const char * const Begin; // beginning of expected content + const char * const End; // end of expected content (1-past) + const char *C; // position of next char in content + const char *P; + +private: + const char *PEnd; // previous next/search subject end (1-past) +}; + +} // namespace llvm + +#endif // LLVM_SUPPORT_PARSEHELPER_H Index: lib/Support/CMakeLists.txt =================================================================== --- lib/Support/CMakeLists.txt +++ lib/Support/CMakeLists.txt @@ -72,6 +72,7 @@ MD5.cpp NativeFormatting.cpp Options.cpp + ParseHelper.cpp PluginLoader.cpp PrettyStackTrace.cpp RandomNumberGenerator.cpp Index: lib/Support/ParseHelper.cpp =================================================================== --- /dev/null +++ lib/Support/ParseHelper.cpp @@ -0,0 +1,114 @@ +//===- ParseHelper.cpp - Simple parser helper class -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ParseHelper class, intended to help implement simple +// parsers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ParseHelper.h" + +using namespace llvm; + +static bool isWhitespace(const char C) { + switch (C) { + case ' ': case '\t': case '\f': + case '\v': case '\n': case '\r': + return true; + default: + return false; + } +} + +// Return true if string literal is next. +bool ParseHelper::Next(StringRef S) { + P = C; + PEnd = C + S.size(); + if (PEnd > End) + return false; + return !memcmp(P, S.data(), S.size()); +} + +// Return true if number is next. +// Output N only if number is next. +bool ParseHelper::Next(unsigned &N) { + unsigned TMP = 0; + P = C; + for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) { + TMP *= 10; + TMP += P[0] - '0'; + } + if (P == C) + return false; + PEnd = P; + N = TMP; + return true; +} + +// Return true if string literal is found. +// When true, P marks begin-position of S in content. +bool ParseHelper::Search(StringRef S, bool EnsureStartOfWord) { + do { + P = std::search(C, End, S.begin(), S.end()); + PEnd = P + S.size(); + if (P == End) + break; + if (!EnsureStartOfWord + // Check if string literal starts a new word. + || P == Begin || isWhitespace(P[-1]) + // Or it could be preceded by the start of a comment. + || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*') + && P[-2] == '/')) + return true; + // Otherwise, skip and search again. + } while (Advance()); + return false; +} + +// Return true if a CloseBrace that closes the OpenBrace at the current nest +// level is found. When true, P marks begin-position of CloseBrace. +bool ParseHelper::SearchClosingBrace(StringRef OpenBrace, StringRef CloseBrace) { + unsigned Depth = 1; + P = C; + while (P < End) { + StringRef S(P, End - P); + if (S.startswith(OpenBrace)) { + ++Depth; + P += OpenBrace.size(); + } else if (S.startswith(CloseBrace)) { + --Depth; + if (Depth == 0) { + PEnd = P + CloseBrace.size(); + return true; + } + P += CloseBrace.size(); + } else { + ++P; + } + } + return false; +} + +// Advance 1-past previous next/search. +// Behavior is undefined if previous next/search failed. +bool ParseHelper::Advance() { + C = PEnd; + return C < End; +} + +// Skip zero or more whitespace. +void ParseHelper::SkipWhitespace() { + for (; C < End && isWhitespace(*C); ++C) + ; +} + +// Return true if EOF reached. +bool ParseHelper::Done() { + return !(C < End); +}