mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Factor out an UpperMap for case-insensitive matching
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
@@ -115,28 +114,9 @@ struct Token {
|
||||
Token(int type_, std::string &&value_) : type(type_), value(value_) {}
|
||||
};
|
||||
|
||||
struct CaseInsensitive {
|
||||
// FNV-1a hash of an uppercased string
|
||||
size_t operator()(std::string const &str) const {
|
||||
size_t hash = 0x811C9DC5;
|
||||
|
||||
for (char const &c : str) {
|
||||
hash = (hash ^ toupper(c)) * 16777619;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Compare two strings without case-sensitivity (by converting to uppercase)
|
||||
bool operator()(std::string const &str1, std::string const &str2) const {
|
||||
return std::equal(RANGE(str1), RANGE(str2), [](char c1, char c2) {
|
||||
return toupper(c1) == toupper(c2);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// This map lists all RGBASM keywords which `yylex_NORMAL` lexes as identifiers.
|
||||
// All non-identifier tokens are lexed separately.
|
||||
static std::unordered_map<std::string, int, CaseInsensitive, CaseInsensitive> keywordDict = {
|
||||
static UpperMap<int> const keywordDict{
|
||||
{"ADC", T_(SM83_ADC) },
|
||||
{"ADD", T_(SM83_ADD) },
|
||||
{"AND", T_(SM83_AND) },
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "helpers.hpp"
|
||||
#include "parser.hpp" // Generated from parser.y
|
||||
#include "usage.hpp"
|
||||
#include "util.hpp" // UpperMap
|
||||
#include "version.hpp"
|
||||
|
||||
#include "asm/charmap.hpp"
|
||||
@@ -124,25 +125,25 @@ static std::vector<StateFeature> parseStateFeatures(char *str) {
|
||||
fatal("Empty feature for option 's'");
|
||||
}
|
||||
// Parse the `feature` and update the `features` list
|
||||
static UpperMap<StateFeature> const featureNames{
|
||||
{"EQU", STATE_EQU },
|
||||
{"VAR", STATE_VAR },
|
||||
{"EQUS", STATE_EQUS },
|
||||
{"CHAR", STATE_CHAR },
|
||||
{"MACRO", STATE_MACRO},
|
||||
};
|
||||
if (!strcasecmp(feature, "all")) {
|
||||
if (!features.empty()) {
|
||||
warnx("Redundant feature before \"%s\" for option 's'", feature);
|
||||
}
|
||||
features.assign({STATE_EQU, STATE_VAR, STATE_EQUS, STATE_CHAR, STATE_MACRO});
|
||||
} else if (auto search = featureNames.find(feature); search == featureNames.end()) {
|
||||
fatal("Invalid feature for option 's': \"%s\"", feature);
|
||||
} else if (StateFeature value = search->second;
|
||||
std::find(RANGE(features), value) != features.end()) {
|
||||
warnx("Ignoring duplicate feature for option 's': \"%s\"", feature);
|
||||
} else {
|
||||
StateFeature value = !strcasecmp(feature, "equ") ? STATE_EQU
|
||||
: !strcasecmp(feature, "var") ? STATE_VAR
|
||||
: !strcasecmp(feature, "equs") ? STATE_EQUS
|
||||
: !strcasecmp(feature, "char") ? STATE_CHAR
|
||||
: !strcasecmp(feature, "macro") ? STATE_MACRO
|
||||
: NB_STATE_FEATURES;
|
||||
if (value == NB_STATE_FEATURES) {
|
||||
fatal("Invalid feature for option 's': \"%s\"", feature);
|
||||
} else if (std::find(RANGE(features), value) != features.end()) {
|
||||
warnx("Ignoring duplicate feature for option 's': \"%s\"", feature);
|
||||
} else {
|
||||
features.push_back(value);
|
||||
}
|
||||
features.push_back(value);
|
||||
}
|
||||
feature = next;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user