diff options
author | Marek Sokolowski <mnbvmar@gmail.com> | 2017-08-28 22:58:31 +0000 |
---|---|---|
committer | Marek Sokolowski <mnbvmar@gmail.com> | 2017-08-28 22:58:31 +0000 |
commit | 7f110527415edc30c2abd027736347a80708cb98 (patch) | |
tree | e9f895228bd5f85c3fd09788de7c7d67afb5eae8 /llvm/tools/llvm-rc/ResourceScriptParser.cpp | |
parent | c07008653c109345b1446f27f2ccc72dbfe5da41 (diff) | |
download | bcm5719-llvm-7f110527415edc30c2abd027736347a80708cb98.tar.gz bcm5719-llvm-7f110527415edc30c2abd027736347a80708cb98.zip |
[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
llvm-svn: 311946
Diffstat (limited to 'llvm/tools/llvm-rc/ResourceScriptParser.cpp')
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp index e4c0f2a7f7c..8d08396e615 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp @@ -63,7 +63,9 @@ RCParser::ParseType RCParser::parseSingleResource() { 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::readIdentifier() { 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 MinCount, size_t MaxCount) { 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::parseLanguageResource() { 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); |