diff options
Diffstat (limited to 'llvm/lib/Remarks/YAMLRemarkParser.h')
-rw-r--r-- | llvm/lib/Remarks/YAMLRemarkParser.h | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/llvm/lib/Remarks/YAMLRemarkParser.h b/llvm/lib/Remarks/YAMLRemarkParser.h new file mode 100644 index 00000000000..1eb5706bfd4 --- /dev/null +++ b/llvm/lib/Remarks/YAMLRemarkParser.h @@ -0,0 +1,136 @@ +//===-- YAMLRemarkParser.h - Parser for YAML remarks ------------*- C++/-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file provides the impementation of the YAML remark parser. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_YAML_REMARK_PARSER_H +#define LLVM_REMARKS_YAML_REMARK_PARSER_H + +#include "RemarkParserImpl.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Remarks/Remark.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include <string> + +namespace llvm { +namespace remarks { +/// Parses and holds the state of the latest parsed remark. +struct YAMLRemarkParser { + /// Source manager for better error messages. + SourceMgr SM; + /// Stream for yaml parsing. + yaml::Stream Stream; + /// Storage for the error stream. + std::string ErrorString; + /// The error stream. + raw_string_ostream ErrorStream; + /// Temporary parsing buffer for the arguments. + SmallVector<Argument, 8> TmpArgs; + + /// The state used by the parser to parse a remark entry. Invalidated with + /// every call to `parseYAMLElement`. + struct ParseState { + /// Temporary parsing buffer for the arguments. + /// The parser itself is owning this buffer in order to reduce the number of + /// allocations. + SmallVectorImpl<Argument> &Args; + Remark Remark; + + ParseState(SmallVectorImpl<Argument> &Args) : Args(Args) {} + /// Use Args only as a **temporary** buffer. + ~ParseState() { Args.clear(); } + }; + + /// The current state of the parser. If the parsing didn't start yet, it will + /// not be containing any value. + Optional<ParseState> State; + + YAMLRemarkParser(StringRef Buf) + : SM(), Stream(Buf, SM), ErrorString(), ErrorStream(ErrorString), + TmpArgs() { + SM.setDiagHandler(YAMLRemarkParser::HandleDiagnostic, this); + } + + /// Parse a YAML element. + Error parseYAMLElement(yaml::Document &Remark); + +private: + /// Parse one key to a string. + /// otherwise. + Error parseKey(StringRef &Result, yaml::KeyValueNode &Node); + /// Parse one value to a string. + template <typename T> Error parseStr(T &Result, yaml::KeyValueNode &Node); + /// Parse one value to an unsigned. + template <typename T> + Error parseUnsigned(T &Result, yaml::KeyValueNode &Node); + /// Parse the type of a remark to an enum type. + Error parseType(Type &Result, yaml::MappingNode &Node); + /// Parse a debug location. + Error parseDebugLoc(Optional<RemarkLocation> &Result, + yaml::KeyValueNode &Node); + /// Parse a remark field and update the parsing state. + Error parseRemarkField(yaml::KeyValueNode &RemarkField); + /// Parse an argument. + Error parseArg(SmallVectorImpl<Argument> &TmpArgs, yaml::Node &Node); + /// Parse an entry from the contents of an argument. + Error parseArgEntry(yaml::KeyValueNode &ArgEntry, StringRef &KeyStr, + StringRef &ValueStr, Optional<RemarkLocation> &Loc); + + /// Handle a diagnostic from the YAML stream. Records the error in the + /// YAMLRemarkParser class. + static void HandleDiagnostic(const SMDiagnostic &Diag, void *Ctx); +}; + +class YAMLParseError : public ErrorInfo<YAMLParseError> { +public: + static char ID; + + YAMLParseError(StringRef Message, yaml::Node &Node) + : Message(Message), Node(Node) {} + + void log(raw_ostream &OS) const override { OS << Message; } + std::error_code convertToErrorCode() const override { + return inconvertibleErrorCode(); + } + + StringRef getMessage() const { return Message; } + yaml::Node &getNode() const { return Node; } + +private: + StringRef Message; // No need to hold a full copy of the buffer. + yaml::Node &Node; +}; + +/// Regular YAML to Remark parser. +struct YAMLParserImpl : public ParserImpl { + /// The object parsing the YAML. + YAMLRemarkParser YAMLParser; + /// Iterator in the YAML stream. + yaml::document_iterator YAMLIt; + /// Set to `true` if we had any errors during parsing. + bool HasErrors = false; + + YAMLParserImpl(StringRef Buf) + : ParserImpl{ParserImpl::Kind::YAML}, YAMLParser(Buf), + YAMLIt(YAMLParser.Stream.begin()), HasErrors(false) {} + + static bool classof(const ParserImpl *PI) { + return PI->Kind == ParserImpl::Kind::YAML; + } +}; +} // end namespace remarks +} // end namespace llvm + +#endif /* LLVM_REMARKS_YAML_REMARK_PARSER_H */ |