| //===-- 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 TheRemark; |
| |
| 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->ParserKind == ParserImpl::Kind::YAML; |
| } |
| }; |
| } // end namespace remarks |
| } // end namespace llvm |
| |
| #endif /* LLVM_REMARKS_YAML_REMARK_PARSER_H */ |