aboutsummaryrefslogtreecommitdiffhomepage
path: root/lexers/LexVerilog.cxx
diff options
context:
space:
mode:
authorJoe Mueller <unknown>2015-01-30 15:17:13 -0800
committerJoe Mueller <unknown>2015-01-30 15:17:13 -0800
commit364eb42baf15f63562497a77977a9e4f389af225 (patch)
treed960003b5ce47709811fc499467f49af696aa0c2 /lexers/LexVerilog.cxx
parentc9cf7c541e41314bbef890070f79ed17bc0515bd (diff)
downloadscintilla-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.cxx58
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);
}