xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-rc/ResourceScriptParser.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
1 //===-- ResourceScriptParser.h ----------------------------------*- C++-*-===//
2 //
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
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This defines the RC scripts parser. It takes a sequence of RC tokens
10 // and then provides the method to parse the resources one by one.
11 //
12 //===---------------------------------------------------------------------===//
13 
14 #ifndef LLVM_TOOLS_LLVMRC_RESOURCESCRIPTPARSER_H
15 #define LLVM_TOOLS_LLVMRC_RESOURCESCRIPTPARSER_H
16 
17 #include "ResourceScriptStmt.h"
18 #include "ResourceScriptToken.h"
19 
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 #include <system_error>
24 #include <vector>
25 
26 namespace llvm {
27 namespace rc {
28 
29 class RCParser {
30 public:
31   using LocIter = std::vector<RCToken>::iterator;
32   using ParseType = Expected<std::unique_ptr<RCResource>>;
33   using ParseOptionType = Expected<std::unique_ptr<OptionalStmt>>;
34 
35   // Class describing a single failure of parser.
36   class ParserError : public ErrorInfo<ParserError> {
37   public:
38     ParserError(const Twine &Expected, const LocIter CurLoc, const LocIter End);
39 
log(raw_ostream & OS)40     void log(raw_ostream &OS) const override { OS << CurMessage; }
convertToErrorCode()41     std::error_code convertToErrorCode() const override {
42       return std::make_error_code(std::errc::invalid_argument);
43     }
getMessage()44     const std::string &getMessage() const { return CurMessage; }
45 
46     static char ID; // Keep llvm::Error happy.
47 
48   private:
49     std::string CurMessage;
50     LocIter ErrorLoc, FileEnd;
51   };
52 
53   explicit RCParser(std::vector<RCToken> TokenList);
54 
55   // Reads and returns a single resource definition, or error message if any
56   // occurred.
57   ParseType parseSingleResource();
58 
59   bool isEof() const;
60 
61 private:
62   using Kind = RCToken::Kind;
63 
64   // Checks if the current parser state points to the token of type TokenKind.
65   bool isNextTokenKind(Kind TokenKind) const;
66 
67   // These methods assume that the parser is not in EOF state.
68 
69   // Take a look at the current token. Do not fetch it.
70   const RCToken &look() const;
71   // Read the current token and advance the state by one token.
72   const RCToken &read();
73   // Advance the state by one token, discarding the current token.
74   void consume();
75 
76   // The following methods try to read a single token, check if it has the
77   // correct type and then parse it.
78   // Each integer can be written as an arithmetic expression producing an
79   // unsigned 32-bit integer.
80   Expected<RCInt> readInt();               // Parse an integer.
81   Expected<StringRef> readString();        // Parse a string.
82   Expected<StringRef> readIdentifier();    // Parse an identifier.
83   Expected<StringRef> readFilename();      // Parse a filename.
84   Expected<IntOrString> readIntOrString(); // Parse an integer or a string.
85   Expected<IntOrString> readTypeOrName();  // Parse an integer or an identifier.
86 
87   // Helper integer expression parsing methods.
88   Expected<IntWithNotMask> parseIntExpr1();
89   Expected<IntWithNotMask> parseIntExpr2();
90 
91   // Advance the state by one, discarding the current token.
92   // If the discarded token had an incorrect type, fail.
93   Error consumeType(Kind TokenKind);
94 
95   // Check the current token type. If it's TokenKind, discard it.
96   // Return true if the parser consumed this token successfully.
97   bool consumeOptionalType(Kind TokenKind);
98 
99   // Read at least MinCount, and at most MaxCount integers separated by
100   // commas. The parser stops reading after fetching MaxCount integers
101   // or after an error occurs. Whenever the parser reads a comma, it
102   // expects an integer to follow.
103   Expected<SmallVector<RCInt, 8>> readIntsWithCommas(size_t MinCount,
104                                                      size_t MaxCount);
105 
106   // Read an unknown number of flags preceded by commas. Each correct flag
107   // has an entry in FlagDesc array of length NumFlags. In case i-th
108   // flag (0-based) has been read, the result is OR-ed with FlagValues[i].
109   // As long as parser has a comma to read, it expects to be fed with
110   // a correct flag afterwards.
111   Expected<uint32_t> parseFlags(ArrayRef<StringRef> FlagDesc,
112                                 ArrayRef<uint32_t> FlagValues);
113 
114   // Reads a set of optional statements. These can change the behavior of
115   // a number of resource types (e.g. STRINGTABLE, MENU or DIALOG) if provided
116   // before the main block with the contents of the resource.
117   // Usually, resources use a basic set of optional statements:
118   //    CHARACTERISTICS, LANGUAGE, VERSION
119   // However, DIALOG and DIALOGEX extend this list by the following items:
120   //    CAPTION, CLASS, EXSTYLE, FONT, MENU, STYLE
121   // UseExtendedStatements flag (off by default) allows the parser to read
122   // the additional types of statements.
123   //
124   // Ref (to the list of all optional statements):
125   //    msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
126   enum class OptStmtType { BasicStmt, DialogStmt, DialogExStmt };
127 
128   uint16_t parseMemoryFlags(uint16_t DefaultFlags);
129 
130   Expected<OptionalStmtList>
131   parseOptionalStatements(OptStmtType StmtsType = OptStmtType::BasicStmt);
132 
133   // Read a single optional statement.
134   Expected<std::unique_ptr<OptionalStmt>>
135   parseSingleOptionalStatement(OptStmtType StmtsType = OptStmtType::BasicStmt);
136 
137   // Top-level resource parsers.
138   ParseType parseLanguageResource();
139   ParseType parseAcceleratorsResource();
140   ParseType parseBitmapResource();
141   ParseType parseCursorResource();
142   ParseType parseDialogResource(bool IsExtended);
143   ParseType parseIconResource();
144   ParseType parseHTMLResource();
145   ParseType parseMenuResource();
146   ParseType parseStringTableResource();
147   ParseType parseUserDefinedResource(IntOrString Type);
148   ParseType parseVersionInfoResource();
149 
150   // Helper DIALOG parser - a single control.
151   Expected<Control> parseControl();
152 
153   // Helper MENU parser.
154   Expected<MenuDefinitionList> parseMenuItemsList();
155 
156   // Helper VERSIONINFO parser - read the contents of a single BLOCK statement,
157   // from BEGIN to END.
158   Expected<std::unique_ptr<VersionInfoBlock>>
159   parseVersionInfoBlockContents(StringRef BlockName);
160   // Helper VERSIONINFO parser - read either VALUE or BLOCK statement.
161   Expected<std::unique_ptr<VersionInfoStmt>> parseVersionInfoStmt();
162   // Helper VERSIONINFO parser - read fixed VERSIONINFO statements.
163   Expected<VersionInfoResource::VersionInfoFixed> parseVersionInfoFixed();
164 
165   // Optional statement parsers.
166   ParseOptionType parseLanguageStmt();
167   ParseOptionType parseCharacteristicsStmt();
168   ParseOptionType parseVersionStmt();
169   ParseOptionType parseCaptionStmt();
170   ParseOptionType parseClassStmt();
171   ParseOptionType parseExStyleStmt();
172   ParseOptionType parseFontStmt(OptStmtType DialogType);
173   ParseOptionType parseStyleStmt();
174 
175   // Raises an error. If IsAlreadyRead = false (default), this complains about
176   // the token that couldn't be parsed. If the flag is on, this complains about
177   // the correctly read token that makes no sense (that is, the current parser
178   // state is beyond the erroneous token.)
179   Error getExpectedError(const Twine &Message, bool IsAlreadyRead = false);
180 
181   std::vector<RCToken> Tokens;
182   LocIter CurLoc;
183   const LocIter End;
184 };
185 
186 } // namespace rc
187 } // namespace llvm
188 
189 #endif
190