diff options
| author | Neil <nyamatongwe@gmail.com> | 2019-03-23 21:52:04 +1100 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2019-03-23 21:52:04 +1100 | 
| commit | f45d0a5ab22f96f7ab10fbdedcf5ca144b950b0e (patch) | |
| tree | c94e4296937487aed6797173d6913a2399e5095a | |
| parent | 6f22344ec9bf01a5db1b8ff34f6cf25253d9193d (diff) | |
| download | scintilla-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.
| -rw-r--r-- | lexers/LexCPP.cxx | 96 | 
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) { | 
