aboutsummaryrefslogtreecommitdiffhomepage
path: root/lexers/LexCPP.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2019-03-23 21:52:04 +1100
committerNeil <nyamatongwe@gmail.com>2019-03-23 21:52:04 +1100
commitf45d0a5ab22f96f7ab10fbdedcf5ca144b950b0e (patch)
treec94e4296937487aed6797173d6913a2399e5095a /lexers/LexCPP.cxx
parent6f22344ec9bf01a5db1b8ff34f6cf25253d9193d (diff)
downloadscintilla-mirror-f45d0a5ab22f96f7ab10fbdedcf5ca144b950b0e.tar.gz
Simplified preprocessor conditional styling code, renamed 'active' to 'inactive'
as that is more correct, added comments and helper methods, removed lines that had no effect. Behaviour unaltered.
Diffstat (limited to 'lexers/LexCPP.cxx')
-rw-r--r--lexers/LexCPP.cxx96
1 files changed, 63 insertions, 33 deletions
diff --git a/lexers/LexCPP.cxx b/lexers/LexCPP.cxx
index 1581b6826..6d3f55684 100644
--- a/lexers/LexCPP.cxx
+++ b/lexers/LexCPP.cxx
@@ -245,12 +245,24 @@ struct PPDefinition {
}
};
+const int inactiveFlag = 0x40;
+
class LinePPState {
- int state;
- int ifTaken;
- int level;
+ // Track the state of preprocessor conditionals to allow showing active and inactive
+ // code in different styles.
+ // Only works up to 31 levels of conditional nesting.
+
+ // state is a bit mask with 1 bit per level
+ // bit is 1 for level if section inactive, so any bits set = inactive style
+ int state = 0;
+ // ifTaken is a bit mask with 1 bit per level
+ // bit is 1 for level if some branch at this level has been taken
+ int ifTaken = 0;
+ // level is the nesting level of #if constructs
+ int level = -1;
+ static const int maximumNestingLevel = 31;
bool ValidLevel() const noexcept {
- return level >= 0 && level < 32;
+ return level >= 0 && level < maximumNestingLevel;
}
int maskLevel() const noexcept {
if (level >= 0) {
@@ -260,11 +272,17 @@ class LinePPState {
}
}
public:
- LinePPState() noexcept : state(0), ifTaken(0), level(-1) {
+ LinePPState() noexcept {
+ }
+ bool IsActive() const noexcept {
+ return state == 0;
}
bool IsInactive() const noexcept {
return state != 0;
}
+ int ActiveState() const noexcept {
+ return state ? inactiveFlag : 0;
+ }
bool CurrentIfTaken() const noexcept {
return (ifTaken & maskLevel()) != 0;
}
@@ -521,7 +539,6 @@ class LexerCPP : public ILexer4 {
OptionSetCPP osCPP;
EscapeSequence escapeSeq;
SparseState<std::string> rawStringTerminators;
- enum { activeFlag = 0x40 };
enum { ssIdentifier, ssDocKeyword };
SubStyles subStyles;
std::string returnBuffer;
@@ -534,7 +551,7 @@ public:
setMultOp(CharacterSet::setNone, "*/%"),
setRelOp(CharacterSet::setNone, "=!<>"),
setLogicalOp(CharacterSet::setNone, "|&"),
- subStyles(styleSubable, 0x80, 0x40, activeFlag) {
+ subStyles(styleSubable, 0x80, 0x40, inactiveFlag) {
}
// Deleted so LexerCPP objects can not be copied.
LexerCPP(const LexerCPP &) = delete;
@@ -585,8 +602,8 @@ public:
}
int SCI_METHOD StyleFromSubStyle(int subStyle) override {
const int styleBase = subStyles.BaseStyle(MaskActive(subStyle));
- const int active = subStyle & activeFlag;
- return styleBase | active;
+ const int inactive = subStyle & inactiveFlag;
+ return styleBase | inactive;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) noexcept override {
return MaskActive(style);
@@ -598,7 +615,7 @@ public:
subStyles.SetIdentifiers(style, identifiers);
}
int SCI_METHOD DistanceToSecondaryStyles() noexcept override {
- return activeFlag;
+ return inactiveFlag;
}
const char * SCI_METHOD GetSubStyleBases() noexcept override {
return styleSubable;
@@ -606,7 +623,7 @@ public:
int SCI_METHOD NamedStyles() override {
return std::max(subStyles.LastAllocated() + 1,
sizeLexicalClasses) +
- activeFlag;
+ inactiveFlag;
}
const char * SCI_METHOD NameOfStyle(int style) override {
if (style >= NamedStyles())
@@ -624,11 +641,11 @@ public:
if (firstSubStyle >= 0) {
const int lastSubStyle = subStyles.LastAllocated();
if (((style >= firstSubStyle) && (style <= (lastSubStyle))) ||
- ((style >= firstSubStyle + activeFlag) && (style <= (lastSubStyle + activeFlag)))) {
+ ((style >= firstSubStyle + inactiveFlag) && (style <= (lastSubStyle + inactiveFlag)))) {
int styleActive = style;
if (style > lastSubStyle) {
returnBuffer = "inactive ";
- styleActive -= activeFlag;
+ styleActive -= inactiveFlag;
}
const int styleMain = StyleFromSubStyle(styleActive);
returnBuffer += lexicalClasses[styleMain].tags;
@@ -637,9 +654,9 @@ public:
}
if (style < sizeLexicalClasses)
return lexicalClasses[style].tags;
- if (style >= activeFlag) {
+ if (style >= inactiveFlag) {
returnBuffer = "inactive ";
- const int styleActive = style - activeFlag;
+ const int styleActive = style - inactiveFlag;
if (styleActive < sizeLexicalClasses)
returnBuffer += lexicalClasses[styleActive].tags;
else
@@ -664,7 +681,7 @@ public:
return new LexerCPP(false);
}
constexpr static int MaskActive(int style) noexcept {
- return style & ~activeFlag;
+ return style & ~inactiveFlag;
}
void EvaluateTokens(std::vector<std::string> &tokens, const SymbolTable &preprocessorDefinitions);
std::vector<std::string> Tokenize(const std::string &expr) const;
@@ -822,7 +839,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
SparseState<std::string> rawSTNew(lineCurrent);
- int activitySet = preproc.IsInactive() ? activeFlag : 0;
+ int activitySet = preproc.ActiveState();
const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD);
@@ -849,7 +866,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
isIncludePreprocessor = false;
inRERange = false;
if (preproc.IsInactive()) {
- activitySet = activeFlag;
+ activitySet = inactiveFlag;
sc.SetState(sc.state | activitySet);
}
}
@@ -1274,6 +1291,8 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
isIncludePreprocessor = true;
} else {
if (options.trackPreprocessor) {
+ // If #if is nested too deeply (>31 levels) the active/inactive appearance
+ // will stop reflecting the code.
if (sc.Match("ifdef") || sc.Match("ifndef")) {
const bool isIfDef = sc.Match("ifdef");
const int startRest = isIfDef ? 5 : 6;
@@ -1285,41 +1304,52 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
preproc.StartSection(ifGood);
} else if (sc.Match("else")) {
+ // #else is shown as active if either preceding or following section is active
+ // as that means that it contributed to the result.
if (!preproc.CurrentIfTaken()) {
+ // Inactive, may become active if parent scope active
+ assert(sc.state == (SCE_C_PREPROCESSOR|inactiveFlag));
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
+ activitySet = preproc.ActiveState();
+ // If following is active then show "else" as active
if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
- } else if (!preproc.IsInactive()) {
+ sc.ChangeState(SCE_C_PREPROCESSOR);
+ } else if (preproc.IsActive()) {
+ // Active -> inactive
+ assert(sc.state == SCE_C_PREPROCESSOR);
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
- if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
+ activitySet = preproc.ActiveState();
+ // Continue to show "else" as active as it ends active section.
}
} else if (sc.Match("elif")) {
// Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif
+ // #elif is shown as active if either preceding or following section is active
+ // as that means that it contributed to the result.
if (!preproc.CurrentIfTaken()) {
+ // Inactive, if expression true then may become active if parent scope active
+ assert(sc.state == (SCE_C_PREPROCESSOR|inactiveFlag));
// Similar to #if
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 4, true);
const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
if (ifGood) {
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
+ activitySet = preproc.ActiveState();
if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
+ sc.ChangeState(SCE_C_PREPROCESSOR);
}
- } else if (!preproc.IsInactive()) {
+ } else if (preproc.IsActive()) {
+ // Active -> inactive
+ assert(sc.state == SCE_C_PREPROCESSOR);
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
- if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
+ activitySet = preproc.ActiveState();
+ // Continue to show "elif" as active as it ends active section.
}
} else if (sc.Match("endif")) {
preproc.EndSection();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
+ activitySet = preproc.ActiveState();
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
} else if (sc.Match("define")) {
- if (options.updatePreprocessor && !preproc.IsInactive()) {
+ if (options.updatePreprocessor && preproc.IsActive()) {
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
size_t startName = 0;
while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName]))
@@ -1357,7 +1387,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
}
} else if (sc.Match("undef")) {
- if (options.updatePreprocessor && !preproc.IsInactive()) {
+ if (options.updatePreprocessor && preproc.IsActive()) {
const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, false);
std::vector<std::string> tokens = Tokenize(restOfLine);
if (tokens.size() >= 1) {