diff options
author | Joe Mueller <unknown> | 2015-01-30 15:17:13 -0800 |
---|---|---|
committer | Joe Mueller <unknown> | 2015-01-30 15:17:13 -0800 |
commit | 364eb42baf15f63562497a77977a9e4f389af225 (patch) | |
tree | d960003b5ce47709811fc499467f49af696aa0c2 /lexers/LexVerilog.cxx | |
parent | c9cf7c541e41314bbef890070f79ed17bc0515bd (diff) | |
download | scintilla-mirror-364eb42baf15f63562497a77977a9e4f389af225.tar.gz |
fix folding bugs with extern and pure virtual functions/tasks. fix folding bugs with wait fork and disable fork statements.
Diffstat (limited to 'lexers/LexVerilog.cxx')
-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); } |