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