1 //===-- YAMLRemarkParser.h - Parser for YAML remarks ------------*- C++/-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file provides the impementation of the YAML remark parser.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_REMARKS_YAML_REMARK_PARSER_H
14 #define LLVM_REMARKS_YAML_REMARK_PARSER_H
16 #include "RemarkParserImpl.h"
17 #include "llvm/ADT/Optional.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/Remarks/Remark.h"
20 #include "llvm/Remarks/RemarkParser.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/YAMLParser.h"
24 #include "llvm/Support/YAMLTraits.h"
25 #include "llvm/Support/raw_ostream.h"
30 /// Parses and holds the state of the latest parsed remark.
31 struct YAMLRemarkParser
{
32 /// Source manager for better error messages.
34 /// Stream for yaml parsing.
36 /// Storage for the error stream.
37 std::string ErrorString
;
39 raw_string_ostream ErrorStream
;
40 /// Temporary parsing buffer for the arguments.
41 SmallVector
<Argument
, 8> TmpArgs
;
42 /// The string table used for parsing strings.
43 Optional
<ParsedStringTable
> StrTab
;
44 /// The state used by the parser to parse a remark entry. Invalidated with
45 /// every call to `parseYAMLElement`.
47 /// Temporary parsing buffer for the arguments.
48 /// The parser itself is owning this buffer in order to reduce the number of
50 SmallVectorImpl
<Argument
> &Args
;
53 ParseState(SmallVectorImpl
<Argument
> &Args
) : Args(Args
) {}
54 /// Use Args only as a **temporary** buffer.
55 ~ParseState() { Args
.clear(); }
58 /// The current state of the parser. If the parsing didn't start yet, it will
59 /// not be containing any value.
60 Optional
<ParseState
> State
;
62 YAMLRemarkParser(StringRef Buf
, Optional
<StringRef
> StrTabBuf
= None
)
63 : SM(), Stream(Buf
, SM
), ErrorString(), ErrorStream(ErrorString
),
65 SM
.setDiagHandler(YAMLRemarkParser::HandleDiagnostic
, this);
68 StrTab
.emplace(*StrTabBuf
);
71 /// Parse a YAML element.
72 Error
parseYAMLElement(yaml::Document
&Remark
);
75 /// Parse one key to a string.
77 Error
parseKey(StringRef
&Result
, yaml::KeyValueNode
&Node
);
78 /// Parse one value to a string.
79 template <typename T
> Error
parseStr(T
&Result
, yaml::KeyValueNode
&Node
);
80 /// Parse one value to an unsigned.
82 Error
parseUnsigned(T
&Result
, yaml::KeyValueNode
&Node
);
83 /// Parse the type of a remark to an enum type.
84 Error
parseType(Type
&Result
, yaml::MappingNode
&Node
);
85 /// Parse a debug location.
86 Error
parseDebugLoc(Optional
<RemarkLocation
> &Result
,
87 yaml::KeyValueNode
&Node
);
88 /// Parse a remark field and update the parsing state.
89 Error
parseRemarkField(yaml::KeyValueNode
&RemarkField
);
90 /// Parse an argument.
91 Error
parseArg(SmallVectorImpl
<Argument
> &TmpArgs
, yaml::Node
&Node
);
92 /// Parse an entry from the contents of an argument.
93 Error
parseArgEntry(yaml::KeyValueNode
&ArgEntry
, StringRef
&KeyStr
,
94 StringRef
&ValueStr
, Optional
<RemarkLocation
> &Loc
);
96 /// Handle a diagnostic from the YAML stream. Records the error in the
97 /// YAMLRemarkParser class.
98 static void HandleDiagnostic(const SMDiagnostic
&Diag
, void *Ctx
);
101 class YAMLParseError
: public ErrorInfo
<YAMLParseError
> {
105 YAMLParseError(StringRef Message
, yaml::Node
&Node
)
106 : Message(Message
), Node(Node
) {}
108 void log(raw_ostream
&OS
) const override
{ OS
<< Message
; }
109 std::error_code
convertToErrorCode() const override
{
110 return inconvertibleErrorCode();
113 StringRef
getMessage() const { return Message
; }
114 yaml::Node
&getNode() const { return Node
; }
117 StringRef Message
; // No need to hold a full copy of the buffer.
121 /// Regular YAML to Remark parser.
122 struct YAMLParserImpl
: public ParserImpl
{
123 /// The object parsing the YAML.
124 YAMLRemarkParser YAMLParser
;
125 /// Iterator in the YAML stream.
126 yaml::document_iterator YAMLIt
;
127 /// Set to `true` if we had any errors during parsing.
128 bool HasErrors
= false;
130 YAMLParserImpl(StringRef Buf
, Optional
<StringRef
> StrTabBuf
= None
)
131 : ParserImpl
{ParserImpl::Kind::YAML
}, YAMLParser(Buf
, StrTabBuf
),
132 YAMLIt(YAMLParser
.Stream
.begin()), HasErrors(false) {}
134 static bool classof(const ParserImpl
*PI
) {
135 return PI
->ParserKind
== ParserImpl::Kind::YAML
;
138 } // end namespace remarks
139 } // end namespace llvm
141 #endif /* LLVM_REMARKS_YAML_REMARK_PARSER_H */