[llvm] r311946 - [llvm-rc] Add ACCELERATORS parsing ability. (parser, pt 3/8).

Marek Sokolowski via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 28 15:58:31 PDT 2017


Author: mnbvmar
Date: Mon Aug 28 15:58:31 2017
New Revision: 311946

URL: http://llvm.org/viewvc/llvm-project?rev=311946&view=rev
Log:
[llvm-rc] Add ACCELERATORS parsing ability. (parser, pt 3/8).

This improves the current llvm-rc parser by the ability of parsing
ACCELERATORS statement.

Moreover, some small improvements to the original parsing commit
were made.

Thanks for Nico Weber for his original work in this area.

Differential Revision: https://reviews.llvm.org/D36894

Added:
    llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-flag.rc
    llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-int-or-string.rc
    llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma-2.rc
    llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma.rc
Modified:
    llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc
    llvm/trunk/test/tools/llvm-rc/parser.test
    llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp
    llvm/trunk/tools/llvm-rc/ResourceScriptParser.h
    llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp
    llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h

Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-flag.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-flag.rc?rev=311946&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-flag.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-flag.rc Mon Aug 28 15:58:31 2017
@@ -0,0 +1,3 @@
+1 ACCELERATORS {
+  5, 7, ALT, CONTROL, HELLO, WORLD
+}

Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-int-or-string.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-int-or-string.rc?rev=311946&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-int-or-string.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-bad-int-or-string.rc Mon Aug 28 15:58:31 2017
@@ -0,0 +1,3 @@
+1 ACCELERATORS {
+  NotIntOrString, 7
+}

Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma-2.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma-2.rc?rev=311946&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma-2.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma-2.rc Mon Aug 28 15:58:31 2017
@@ -0,0 +1,3 @@
+1 ACCELERATORS {
+  "^C" 10
+}

Added: llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma.rc?rev=311946&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-accelerators-no-comma.rc Mon Aug 28 15:58:31 2017
@@ -0,0 +1,3 @@
+1 ACCELERATORS {
+  5, 10, ASCII CONTROL
+}

Modified: llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc?rev=311946&r1=311945&r2=311946&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc (original)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/parser-correct-everything.rc Mon Aug 28 15:58:31 2017
@@ -16,3 +16,16 @@ STRINGTABLE BEGIN END
 
 500 HTML "index.html"
 Name Cursor "hello.ico"
+
+12 ACCELERATORS
+VERSION 5000
+LANGUAGE 0, 2
+{
+  "^C", 10
+  14, 11
+  5, 12, VIRTKEY
+  0, 0, ASCII
+  1, 1, VIRTKEY, CONTROL
+  2, 2, CONTROL, VIRTKEY
+  3, 3, ALT, CONTROL, SHIFT, NOINVERT, ASCII, VIRTKEY
+}

Modified: llvm/trunk/test/tools/llvm-rc/parser.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/parser.test?rev=311946&r1=311945&r2=311946&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/parser.test (original)
+++ llvm/trunk/test/tools/llvm-rc/parser.test Mon Aug 28 15:58:31 2017
@@ -13,6 +13,16 @@
 ; PGOOD-NEXT:  StringTable:
 ; PGOOD-NEXT:  HTML (500): "index.html"
 ; PGOOD-NEXT:  Cursor (Name): "hello.ico"
+; PGOOD-NEXT:  Accelerators (12):
+; PGOOD-NEXT:    Option: Version: 5000
+; PGOOD-NEXT:    Option: Language: 0, Sublanguage: 2
+; PGOOD-NEXT:    Accelerator: "^C" 10
+; PGOOD-NEXT:    Accelerator: 14 11
+; PGOOD-NEXT:    Accelerator: 5 12 VIRTKEY
+; PGOOD-NEXT:    Accelerator: 0 0 ASCII
+; PGOOD-NEXT:    Accelerator: 1 1 VIRTKEY CONTROL
+; PGOOD-NEXT:    Accelerator: 2 2 VIRTKEY CONTROL
+; PGOOD-NEXT:    Accelerator: 3 3 ASCII VIRTKEY NOINVERT ALT SHIFT CONTROL
 
 
 ; RUN: not llvm-rc /V %p/Inputs/parser-stringtable-no-string.rc 2>&1 | FileCheck %s --check-prefix PSTRINGTABLE1
@@ -68,3 +78,23 @@
 ; RUN: not llvm-rc /V %p/Inputs/parser-html-extra-comma.rc 2>&1 | FileCheck %s --check-prefix PHTML2
 
 ; PHTML2:  llvm-rc: Error parsing file: expected string, got ,
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-accelerators-bad-flag.rc 2>&1 | FileCheck %s --check-prefix PACCELERATORS1
+
+; PACCELERATORS1:  llvm-rc: Error parsing file: expected ASCII/VIRTKEY/NOINVERT/ALT/SHIFT/CONTROL, got HELLO
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-accelerators-bad-int-or-string.rc 2>&1 | FileCheck %s --check-prefix PACCELERATORS2
+
+; PACCELERATORS2:  llvm-rc: Error parsing file: expected int or string, got NotIntOrString
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-accelerators-no-comma.rc 2>&1 | FileCheck %s --check-prefix PACCELERATORS3
+
+; PACCELERATORS3:  llvm-rc: Error parsing file: expected int or string, got CONTROL
+
+
+; RUN: not llvm-rc /V %p/Inputs/parser-accelerators-no-comma-2.rc 2>&1 | FileCheck %s --check-prefix PACCELERATORS4
+
+; PACCELERATORS4:  llvm-rc: Error parsing file: expected ',', got 10

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp?rev=311946&r1=311945&r2=311946&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp Mon Aug 28 15:58:31 2017
@@ -63,7 +63,9 @@ RCParser::ParseType RCParser::parseSingl
   ParseType Result = std::unique_ptr<RCResource>();
   (void)!Result;
 
-  if (TypeToken->equalsLower("CURSOR"))
+  if (TypeToken->equalsLower("ACCELERATORS"))
+    Result = parseAcceleratorsResource();
+  else if (TypeToken->equalsLower("CURSOR"))
     Result = parseCursorResource();
   else if (TypeToken->equalsLower("ICON"))
     Result = parseIconResource();
@@ -115,17 +117,18 @@ Expected<StringRef> RCParser::readIdenti
   return read().value();
 }
 
+Expected<IntOrString> RCParser::readIntOrString() {
+  if (!isNextTokenKind(Kind::Int) && !isNextTokenKind(Kind::String))
+    return getExpectedError("int or string");
+  return IntOrString(read());
+}
+
 Expected<IntOrString> RCParser::readTypeOrName() {
   // We suggest that the correct resource name or type should be either an
   // identifier or an integer. The original RC tool is much more liberal.
   if (!isNextTokenKind(Kind::Identifier) && !isNextTokenKind(Kind::Int))
     return getExpectedError("int or identifier");
-
-  const RCToken &Tok = read();
-  if (Tok.kind() == Kind::Int)
-    return IntOrString(Tok.intValue());
-  else
-    return IntOrString(Tok.value());
+  return IntOrString(read());
 }
 
 Error RCParser::consumeType(Kind TokenKind) {
@@ -190,6 +193,32 @@ RCParser::readIntsWithCommas(size_t MinC
   return std::move(Result);
 }
 
+Expected<uint32_t> RCParser::parseFlags(ArrayRef<StringRef> FlagDesc) {
+  assert(FlagDesc.size() <= 32 && "More than 32 flags won't fit in result.");
+  assert(!FlagDesc.empty());
+
+  uint32_t Result = 0;
+  while (isNextTokenKind(Kind::Comma)) {
+    consume();
+    ASSIGN_OR_RETURN(FlagResult, readIdentifier());
+    bool FoundFlag = false;
+
+    for (size_t FlagId = 0; FlagId < FlagDesc.size(); ++FlagId) {
+      if (!FlagResult->equals_lower(FlagDesc[FlagId]))
+        continue;
+
+      Result |= (1U << FlagId);
+      FoundFlag = true;
+      break;
+    }
+
+    if (!FoundFlag)
+      return getExpectedError(join(FlagDesc, "/"), true);
+  }
+
+  return Result;
+}
+
 // As for now, we ignore the extended set of statements.
 Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) {
   OptionalStmtList Result;
@@ -223,6 +252,24 @@ RCParser::ParseType RCParser::parseLangu
   return parseLanguageStmt();
 }
 
+RCParser::ParseType RCParser::parseAcceleratorsResource() {
+  ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
+  RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
+
+  auto Accels = make_unique<AcceleratorsResource>(std::move(*OptStatements));
+
+  while (!consumeOptionalType(Kind::BlockEnd)) {
+    ASSIGN_OR_RETURN(EventResult, readIntOrString());
+    RETURN_IF_ERROR(consumeType(Kind::Comma));
+    ASSIGN_OR_RETURN(IDResult, readInt());
+    ASSIGN_OR_RETURN(FlagsResult,
+                     parseFlags(AcceleratorsResource::Accelerator::OptionsStr));
+    Accels->addAccelerator(*EventResult, *IDResult, *FlagsResult);
+  }
+
+  return std::move(Accels);
+}
+
 RCParser::ParseType RCParser::parseCursorResource() {
   ASSIGN_OR_RETURN(Arg, readString());
   return make_unique<CursorResource>(*Arg);

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptParser.h?rev=311946&r1=311945&r2=311946&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptParser.h (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptParser.h Mon Aug 28 15:58:31 2017
@@ -77,10 +77,11 @@ private:
 
   // The following methods try to read a single token, check if it has the
   // correct type and then parse it.
-  Expected<uint32_t> readInt();           // Parse an integer.
-  Expected<StringRef> readString();       // Parse a string.
-  Expected<StringRef> readIdentifier();   // Parse an identifier.
-  Expected<IntOrString> readTypeOrName(); // Parse an integer or an identifier.
+  Expected<uint32_t> readInt();            // Parse an integer.
+  Expected<StringRef> readString();        // Parse a string.
+  Expected<StringRef> readIdentifier();    // Parse an identifier.
+  Expected<IntOrString> readIntOrString(); // Parse an integer or a string.
+  Expected<IntOrString> readTypeOrName();  // Parse an integer or an identifier.
 
   // Advance the state by one, discarding the current token.
   // If the discarded token had an incorrect type, fail.
@@ -97,6 +98,13 @@ private:
   Expected<SmallVector<uint32_t, 8>> readIntsWithCommas(size_t MinCount,
                                                         size_t MaxCount);
 
+  // Read an unknown number of flags preceded by commas. Each correct flag
+  // has an entry in FlagDesc array of length NumFlags. In case i-th
+  // flag (0-based) has been read, the i-th bit of the result is set.
+  // As long as parser has a comma to read, it expects to be fed with
+  // a correct flag afterwards.
+  Expected<uint32_t> parseFlags(ArrayRef<StringRef> FlagDesc);
+
   // Reads a set of optional statements. These can change the behavior of
   // a number of resource types (e.g. STRINGTABLE, MENU or DIALOG) if provided
   // before the main block with the contents of the resource.
@@ -118,6 +126,7 @@ private:
 
   // Top-level resource parsers.
   ParseType parseLanguageResource();
+  ParseType parseAcceleratorsResource();
   ParseType parseCursorResource();
   ParseType parseIconResource();
   ParseType parseHTMLResource();

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp?rev=311946&r1=311945&r2=311946&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp Mon Aug 28 15:58:31 2017
@@ -36,6 +36,23 @@ raw_ostream &LanguageResource::log(raw_o
   return OS << "Language: " << Lang << ", Sublanguage: " << SubLang << "\n";
 }
 
+StringRef AcceleratorsResource::Accelerator::OptionsStr
+    [AcceleratorsResource::Accelerator::NumFlags] = {
+        "ASCII", "VIRTKEY", "NOINVERT", "ALT", "SHIFT", "CONTROL"};
+
+raw_ostream &AcceleratorsResource::log(raw_ostream &OS) const {
+  OS << "Accelerators (" << ResName << "): \n";
+  OptStatements.log(OS);
+  for (const auto &Acc : Accelerators) {
+    OS << "  Accelerator: " << Acc.Event << " " << Acc.Id;
+    for (size_t i = 0; i < Accelerator::NumFlags; ++i)
+      if (Acc.Flags & (1U << i))
+        OS << " " << Accelerator::OptionsStr[i];
+    OS << "\n";
+  }
+  return OS;
+}
+
 raw_ostream &CursorResource::log(raw_ostream &OS) const {
   return OS << "Cursor (" << ResName << "): " << CursorLoc << "\n";
 }

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h?rev=311946&r1=311945&r2=311946&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h Mon Aug 28 15:58:31 2017
@@ -27,7 +27,12 @@ private:
     StringRef String;
     Data(uint32_t Value) : Int(Value) {}
     Data(const StringRef Value) : String(Value) {}
-    Data(const RCToken &Token);
+    Data(const RCToken &Token) {
+      if (Token.kind() == RCToken::Kind::Int)
+        Int = Token.intValue();
+      else
+        String = Token.value();
+    }
   } Data;
   bool IsInt;
 
@@ -90,6 +95,42 @@ public:
   raw_ostream &log(raw_ostream &) const override;
 };
 
+// ACCELERATORS resource. Defines a named table of accelerators for the app.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx
+class AcceleratorsResource : public RCResource {
+public:
+  class Accelerator {
+  public:
+    IntOrString Event;
+    uint32_t Id;
+    uint8_t Flags;
+
+    enum Options {
+      ASCII = (1 << 0),
+      VIRTKEY = (1 << 1),
+      NOINVERT = (1 << 2),
+      ALT = (1 << 3),
+      SHIFT = (1 << 4),
+      CONTROL = (1 << 5)
+    };
+
+    static constexpr size_t NumFlags = 6;
+    static StringRef OptionsStr[NumFlags];
+  };
+
+  AcceleratorsResource(OptionalStmtList &&OptStmts)
+      : OptStatements(std::move(OptStmts)) {}
+  void addAccelerator(IntOrString Event, uint32_t Id, uint8_t Flags) {
+    Accelerators.push_back(Accelerator{Event, Id, Flags});
+  }
+  raw_ostream &log(raw_ostream &) const override;
+
+private:
+  std::vector<Accelerator> Accelerators;
+  OptionalStmtList OptStatements;
+};
+
 // CURSOR resource. Represents a single cursor (".cur") file.
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx




More information about the llvm-commits mailing list