Skip to content

Commit

Permalink
implement basic functionality to occasionally parse keywords as ident…
Browse files Browse the repository at this point in the history
…ifiers
  • Loading branch information
XxX-Daniil-underscore-Zaikin-XxX committed Sep 22, 2024
1 parent 4f4f903 commit 18f5f92
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 1 deletion.
24 changes: 24 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@
"value": "RelWithDebInfo"
}
}
},
{
"name": "build-debug-msvc",
"inherits": [
"base",
"vcpkg",
"x64",
"msvc"
],
"displayName": "Debug",
"description": "Debug build for testing.",
"binaryDir": "${sourceDir}/build/debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": {
"type": "STRING",
"value": "Debug"
}
}
}
],
"buildPresets": [
Expand All @@ -77,6 +95,12 @@
"displayName": "Release (MSVC)",
"configurePreset": "build-release-msvc",
"description": "Optimized release Build."
},
{
"name": "debug-msvc",
"displayName": "Debug (MSVC)",
"configurePreset": "build-debug-msvc",
"description": "Debug build for local testing."
}
]
}
7 changes: 7 additions & 0 deletions Caprica/common/CapricaReportingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ struct CapricaReportingContext final {
identifier_ref,
parentName)

// Not a base game warning, but some ubiquitous libraries fall prey to this.
DEFINE_WARNING_A1(1006,
Strict_Keyword_Identifiers,
"'{}' is a keyword (e.g. Int, Function) but is used as an identifier.",
identifier_ref,
idName)

// Warnings 2000-2199 are for engine imposed limitations.

DEFINE_WARNING_A2(2001,
Expand Down
4 changes: 4 additions & 0 deletions Caprica/main_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ bool parseCommandLineArguments(int argc, char* argv[], caprica::CapricaJobManage
"Ensure values returned from BetaOnly and DebugOnly functions don't escape, as that will cause invalid code generation.")
("disable-implicit-conversion-from-none", po::bool_switch()->default_value(false),
"Disable implicit conversion from None in most situations where the use of None likely wasn't the author's intention.")
("disable-keywords-as-identifiers", po::bool_switch()->default_value(false),
"Disable the ability to use some keywords (e.g. Switch, Parent) as identifiers in select cases.")
("skyrim-allow-unknown-events-on-non-native-class", po::value<bool>(&conf::Skyrim::skyrimAllowUnknownEventsOnNonNativeClass)->default_value(true),
"Allow unknown events to be defined on non-native classes. This is encountered with some scripts in the base game having Events that are not present on ObjectReference.");

Expand Down Expand Up @@ -560,6 +562,8 @@ bool parseCommandLineArguments(int argc, char* argv[], caprica::CapricaJobManage
conf::Warnings::warningsToHandleAsErrors.insert(1002);
} else if (vm["disable-implicit-conversion-from-none"].as<bool>()) {
conf::Warnings::warningsToHandleAsErrors.insert(1003);
} else if (vm["disable-keywords-as-identifiers"].as<bool>()) {
conf::Warnings::warningsToHandleAsErrors.insert(1006);
}

if (vm.count("disable-warning")) {
Expand Down
19 changes: 19 additions & 0 deletions Caprica/papyrus/parser/PapyrusLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,25 @@ static const caseless_unordered_identifier_ref_map<TokenType> languageExtensions
{ "to", TokenType::kTo },
};

// keywords which can never pass as identifiers
static const std::unordered_set<TokenType> nonIdentifiersSet {
TokenType::kAuto,
TokenType::kAutoReadOnly,
TokenType::kBool,
TokenType::kConst,
TokenType::kFalse,
TokenType::kFloat,
TokenType::kInt,
TokenType::kNone,
TokenType::kString,
TokenType::kStruct,
TokenType::kVar,
};

const bool keywordCanBeIdentifier(TokenType tp) {
return keywordIsInGame(tp, conf::Papyrus::game, true) && nonIdentifiersSet.find(tp) == nonIdentifiersSet.end();
}

ALWAYS_INLINE
static bool isAsciiAlphaNumeric(int c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
Expand Down
1 change: 1 addition & 0 deletions Caprica/papyrus/parser/PapyrusLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ constexpr TokenType STARFIELD_MAX_KEYWORD = TokenType::kTryGuard;
constexpr bool keywordIsLanguageExtension(TokenType tp) {
return tp >= TokenType::kBreak && tp <= TokenType::kTo;
}
const bool keywordCanBeIdentifier(TokenType tp);
constexpr bool keywordIsInGame(TokenType tp, GameID game, bool includeExtensions = false) {
if (includeExtensions && keywordIsLanguageExtension(tp))
return true;
Expand Down
22 changes: 21 additions & 1 deletion Caprica/papyrus/parser/PapyrusParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ PapyrusFunction* PapyrusParser::parseFunction(

auto param =
alloc->make<PapyrusFunctionParameter>(cur.location, func->parameters.size(), expectConsumePapyrusType());
param->name = expectConsumeIdentRef();
param->name = expectConsumeKeywordOrIdentRef();
if (maybeConsume(TokenType::Equal))
param->defaultValue = expectConsumePapyrusValue();
func->parameters.push_back(param);
Expand Down Expand Up @@ -1176,6 +1176,26 @@ expressions::PapyrusExpression* PapyrusParser::parseFuncOrIdExpression(PapyrusFu
}
}

identifier_ref PapyrusParser::expectConsumeKeywordOrIdentRef() {
if (!keywordCanBeIdentifier(cur.type)) {
reportingContext.fatal(cur.location,
"Syntax error! Expected valid identifier, got '{}'.",
cur.prettyString());
}

identifier_ref finalId;

if (cur.type != TokenType::Identifier) {
const identifier_ref typeIdentifier = identifier_ref(PapyrusLexer::Token::prettyTokenType(cur.type));
reportingContext.warning_W1006_Strict_Keyword_Identifiers(cur.location, typeIdentifier);
finalId = typeIdentifier;
} else {
finalId = cur.val.s;
}
consume();
return finalId;
}

PapyrusType PapyrusParser::expectConsumePapyrusType() {
PapyrusType tp = PapyrusType::Default();
switch (cur.type) {
Expand Down
1 change: 1 addition & 0 deletions Caprica/papyrus/parser/PapyrusParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct PapyrusParser final : private PapyrusLexer {

PapyrusType expectConsumePapyrusType();
PapyrusValue expectConsumePapyrusValue();
identifier_ref expectConsumeKeywordOrIdentRef();
PapyrusUserFlags maybeConsumeUserFlags(CapricaUserFlagsDefinition::ValidLocations location);

ALWAYS_INLINE
Expand Down

0 comments on commit 18f5f92

Please sign in to comment.