diff options
| -rw-r--r-- | lexers/LexVerilog.cxx | 58 | 
1 files changed, 57 insertions, 1 deletions
| diff --git a/lexers/LexVerilog.cxx b/lexers/LexVerilog.cxx index fdafbddc3..05922d22d 100644 --- a/lexers/LexVerilog.cxx +++ b/lexers/LexVerilog.cxx @@ -198,6 +198,14 @@ class LexerVerilog : public ILexerWithSubStyles {  	OptionSetVerilog osVerilog;  	enum { activeFlag = 0x40 };  	SubStyles subStyles; + +	// states at end of line (EOL) during fold operations: +	//		foldExternFlag: EOL while parsing an extern function/task declaration terminated by ';' +	//		foldWaitDisable: EOL while parsing wait or disable statement, terminated by "fork" or '(' +	enum {foldExternFlag = 0x01, foldWaitDisableFlag = 0x02}; +	// map using line number as key to store fold state information +	std::map<int, int> foldState; +  public:  	LexerVerilog() :  		setWord(CharacterSet::setAlphaNum, "._", 0x80, true), @@ -778,6 +786,20 @@ void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initSt  	char chNext = styler[startPos];  	int styleNext = MaskActive(styler.StyleAt(startPos));  	int style = MaskActive(initStyle); + +	// restore fold state (if it exists) for prior line +	int stateCurrent = 0; +	std::map<int,int>::iterator foldStateIterator = foldState.find(lineCurrent-1); +	if (foldStateIterator != foldState.end()) { +		stateCurrent = foldStateIterator->second; +	} + +	// remove all foldState entries after lineCurrent-1 +	foldStateIterator = foldState.upper_bound(lineCurrent-1); +	if (foldStateIterator != foldState.end()) { +		foldState.erase(foldStateIterator, foldState.end()); +	} +  	for (unsigned int i = startPos; i < endPos; i++) {  		char ch = chNext;  		chNext = styler.SafeGetCharAt(i + 1); @@ -833,6 +855,24 @@ void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initSt  					levelNext--;  				}  			} +			// semicolons terminate external declarations +			if (ch == ';') { +				// extern and pure virtual declarations terminated by semicolon +				if (stateCurrent & foldExternFlag) { +					levelNext--; +					stateCurrent &= ~foldExternFlag; +				} +				// wait and disable statements terminated by semicolon +				if (stateCurrent & foldWaitDisableFlag) { +					stateCurrent &= ~foldWaitDisableFlag; +				} +			} +			// wait and disable statements containing '(' will not contain "fork" keyword, special processing is not needed +			if (ch == '(') { +				if (stateCurrent & foldWaitDisableFlag) { +					stateCurrent &= ~foldWaitDisableFlag; +				} +			}  		}  		if (style == SCE_V_OPERATOR) {  			if (foldAtBrace) { @@ -859,10 +899,15 @@ void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initSt  				styler.Match(j, "specify") ||  				styler.Match(j, "table") ||  				styler.Match(j, "task") || -				styler.Match(j, "fork") ||  				(styler.Match(j, "module") && options.foldAtModule) ||  				styler.Match(j, "begin")) {  				levelNext++; +			} else if (styler.Match(j, "fork")) { +				// fork does not introduce a block when used in a wait or disable statement +				if (stateCurrent & foldWaitDisableFlag) { +					stateCurrent &= ~foldWaitDisableFlag; +				} else +					levelNext++;  			} else if (styler.Match(j, "endcase") ||  				styler.Match(j, "endclass") ||  				styler.Match(j, "endfunction") || @@ -881,6 +926,14 @@ void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initSt  				(styler.Match(j, "endmodule") && options.foldAtModule) ||  				(styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j + 3)))) {  				levelNext--; +			} else if (styler.Match(j, "extern") || +				styler.Match(j, "pure")) { +				// extern and pure virtual functions/tasks are terminated by ';' not endfunction/endtask +				stateCurrent |= foldExternFlag; +			} else if (styler.Match(j, "disable") || +				styler.Match(j, "wait")) { +				// fork does not introduce a block when used in a wait or disable statement +				stateCurrent |= foldWaitDisableFlag;  			}  		}  		if (atEOL) { @@ -893,6 +946,9 @@ void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initSt  				lev |= SC_FOLDLEVELWHITEFLAG;  			if (levelUse < levelNext)  				lev |= SC_FOLDLEVELHEADERFLAG; +			if (stateCurrent) { +				foldState[lineCurrent] = stateCurrent; +			}  			if (lev != styler.LevelAt(lineCurrent)) {  				styler.SetLevel(lineCurrent, lev);  			} | 
