diff options
Diffstat (limited to 'lexers/LexVerilog.cxx')
-rw-r--r-- | lexers/LexVerilog.cxx | 1081 |
1 files changed, 0 insertions, 1081 deletions
diff --git a/lexers/LexVerilog.cxx b/lexers/LexVerilog.cxx deleted file mode 100644 index ac5859e93..000000000 --- a/lexers/LexVerilog.cxx +++ /dev/null @@ -1,1081 +0,0 @@ -// Scintilla source code edit control -/** @file LexVerilog.cxx - ** Lexer for Verilog. - ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson - **/ -// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <assert.h> -#include <ctype.h> - -#include <string> -#include <vector> -#include <map> -#include <algorithm> - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "CharacterSet.h" -#include "LexerModule.h" - -#include "OptionSet.h" -#include "SubStyles.h" -#include "DefaultLexer.h" - -using namespace Scintilla; - -namespace { - // Use an unnamed namespace to protect the functions and classes from name conflicts - -struct PPDefinition { - Sci_Position line; - std::string key; - std::string value; - bool isUndef; - std::string arguments; - PPDefinition(Sci_Position line_, const std::string &key_, const std::string &value_, bool isUndef_ = false, std::string arguments_="") : - line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) { - } -}; - -class LinePPState { - int state; - int ifTaken; - int level; - bool ValidLevel() const { - return level >= 0 && level < 32; - } - int maskLevel() const { - if (level >= 0) { - return 1 << level; - } else { - return 1; - } - } -public: - LinePPState() : state(0), ifTaken(0), level(-1) { - } - bool IsInactive() const { - return state != 0; - } - bool CurrentIfTaken() const { - return (ifTaken & maskLevel()) != 0; - } - void StartSection(bool on) { - level++; - if (ValidLevel()) { - if (on) { - state &= ~maskLevel(); - ifTaken |= maskLevel(); - } else { - state |= maskLevel(); - ifTaken &= ~maskLevel(); - } - } - } - void EndSection() { - if (ValidLevel()) { - state &= ~maskLevel(); - ifTaken &= ~maskLevel(); - } - level--; - } - void InvertCurrentLevel() { - if (ValidLevel()) { - state ^= maskLevel(); - ifTaken |= maskLevel(); - } - } -}; - -// Hold the preprocessor state for each line seen. -// Currently one entry per line but could become sparse with just one entry per preprocessor line. -class PPStates { - std::vector<LinePPState> vlls; -public: - LinePPState ForLine(Sci_Position line) const { - if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) { - return vlls[line]; - } else { - return LinePPState(); - } - } - void Add(Sci_Position line, LinePPState lls) { - vlls.resize(line+1); - vlls[line] = lls; - } -}; - -// Options used for LexerVerilog -struct OptionsVerilog { - bool foldComment; - bool foldPreprocessor; - bool foldPreprocessorElse; - bool foldCompact; - bool foldAtElse; - bool foldAtModule; - bool trackPreprocessor; - bool updatePreprocessor; - bool portStyling; - bool allUppercaseDocKeyword; - OptionsVerilog() { - foldComment = false; - foldPreprocessor = false; - foldPreprocessorElse = false; - foldCompact = false; - foldAtElse = false; - foldAtModule = false; - // for backwards compatibility, preprocessor functionality is disabled by default - trackPreprocessor = false; - updatePreprocessor = false; - // for backwards compatibility, treat input/output/inout as regular keywords - portStyling = false; - // for backwards compatibility, don't treat all uppercase identifiers as documentation keywords - allUppercaseDocKeyword = false; - } -}; - -struct OptionSetVerilog : public OptionSet<OptionsVerilog> { - OptionSetVerilog() { - DefineProperty("fold.comment", &OptionsVerilog::foldComment, - "This option enables folding multi-line comments when using the Verilog lexer."); - DefineProperty("fold.preprocessor", &OptionsVerilog::foldPreprocessor, - "This option enables folding preprocessor directives when using the Verilog lexer."); - DefineProperty("fold.compact", &OptionsVerilog::foldCompact); - DefineProperty("fold.at.else", &OptionsVerilog::foldAtElse, - "This option enables folding on the else line of an if statement."); - DefineProperty("fold.verilog.flags", &OptionsVerilog::foldAtModule, - "This option enables folding module definitions. Typically source files " - "contain only one module definition so this option is somewhat useless."); - DefineProperty("lexer.verilog.track.preprocessor", &OptionsVerilog::trackPreprocessor, - "Set to 1 to interpret `if/`else/`endif to grey out code that is not active."); - DefineProperty("lexer.verilog.update.preprocessor", &OptionsVerilog::updatePreprocessor, - "Set to 1 to update preprocessor definitions when `define, `undef, or `undefineall found."); - DefineProperty("lexer.verilog.portstyling", &OptionsVerilog::portStyling, - "Set to 1 to style input, output, and inout ports differently from regular keywords."); - DefineProperty("lexer.verilog.allupperkeywords", &OptionsVerilog::allUppercaseDocKeyword, - "Set to 1 to style identifiers that are all uppercase as documentation keyword."); - DefineProperty("lexer.verilog.fold.preprocessor.else", &OptionsVerilog::foldPreprocessorElse, - "This option enables folding on `else and `elsif preprocessor directives."); - } -}; - -const char styleSubable[] = {0}; - -} - -class LexerVerilog : public DefaultLexer { - CharacterSet setWord; - WordList keywords; - WordList keywords2; - WordList keywords3; - WordList keywords4; - WordList keywords5; - WordList ppDefinitions; - PPStates vlls; - std::vector<PPDefinition> ppDefineHistory; - struct SymbolValue { - std::string value; - std::string arguments; - SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) { - } - SymbolValue &operator = (const std::string &value_) { - value = value_; - arguments.clear(); - return *this; - } - bool IsMacro() const { - return !arguments.empty(); - } - }; - typedef std::map<std::string, SymbolValue> SymbolTable; - SymbolTable preprocessorDefinitionsStart; - OptionsVerilog options; - 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 ';' - // foldWaitDisableFlag: EOL while parsing wait or disable statement, terminated by "fork" or '(' - // typdefFlag: EOL while parsing typedef statement, terminated by ';' - enum {foldExternFlag = 0x01, foldWaitDisableFlag = 0x02, typedefFlag = 0x04, protectedFlag = 0x08}; - // map using line number as key to store fold state information - std::map<Sci_Position, int> foldState; - -public: - LexerVerilog() : - DefaultLexer("verilog", SCLEX_VERILOG), - setWord(CharacterSet::setAlphaNum, "._", 0x80, true), - subStyles(styleSubable, 0x80, 0x40, activeFlag) { - } - virtual ~LexerVerilog() {} - int SCI_METHOD Version() const override { - return lvRelease5; - } - void SCI_METHOD Release() override { - delete this; - } - const char* SCI_METHOD PropertyNames() override { - return osVerilog.PropertyNames(); - } - int SCI_METHOD PropertyType(const char* name) override { - return osVerilog.PropertyType(name); - } - const char* SCI_METHOD DescribeProperty(const char* name) override { - return osVerilog.DescribeProperty(name); - } - Sci_Position SCI_METHOD PropertySet(const char* key, const char* val) override { - return osVerilog.PropertySet(&options, key, val); - } - const char * SCI_METHOD PropertyGet(const char *key) override { - return osVerilog.PropertyGet(key); - } - const char* SCI_METHOD DescribeWordListSets() override { - return osVerilog.DescribeWordListSets(); - } - Sci_Position SCI_METHOD WordListSet(int n, const char* wl) override; - void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; - void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; - void* SCI_METHOD PrivateCall(int, void*) override { - return 0; - } - int SCI_METHOD LineEndTypesSupported() override { - return SC_LINE_END_TYPE_UNICODE; - } - int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { - return subStyles.Allocate(styleBase, numberStyles); - } - int SCI_METHOD SubStylesStart(int styleBase) override { - return subStyles.Start(styleBase); - } - int SCI_METHOD SubStylesLength(int styleBase) override { - return subStyles.Length(styleBase); - } - int SCI_METHOD StyleFromSubStyle(int subStyle) override { - int styleBase = subStyles.BaseStyle(MaskActive(subStyle)); - int active = subStyle & activeFlag; - return styleBase | active; - } - int SCI_METHOD PrimaryStyleFromStyle(int style) override { - return MaskActive(style); - } - void SCI_METHOD FreeSubStyles() override { - subStyles.Free(); - } - void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { - subStyles.SetIdentifiers(style, identifiers); - } - int SCI_METHOD DistanceToSecondaryStyles() override { - return activeFlag; - } - const char * SCI_METHOD GetSubStyleBases() override { - return styleSubable; - } - static ILexer5* LexerFactoryVerilog() { - return new LexerVerilog(); - } - static int MaskActive(int style) { - return style & ~activeFlag; - } - std::vector<std::string> Tokenize(const std::string &expr) const; -}; - -Sci_Position SCI_METHOD LexerVerilog::WordListSet(int n, const char *wl) { - WordList *wordListN = 0; - switch (n) { - case 0: - wordListN = &keywords; - break; - case 1: - wordListN = &keywords2; - break; - case 2: - wordListN = &keywords3; - break; - case 3: - wordListN = &keywords4; - break; - case 4: - wordListN = &keywords5; - break; - case 5: - wordListN = &ppDefinitions; - break; - } - Sci_Position firstModification = -1; - if (wordListN) { - WordList wlNew; - wlNew.Set(wl); - if (*wordListN != wlNew) { - wordListN->Set(wl); - firstModification = 0; - if (n == 5) { - // Rebuild preprocessorDefinitions - preprocessorDefinitionsStart.clear(); - for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) { - const char *cpDefinition = ppDefinitions.WordAt(nDefinition); - const char *cpEquals = strchr(cpDefinition, '='); - if (cpEquals) { - std::string name(cpDefinition, cpEquals - cpDefinition); - std::string val(cpEquals+1); - size_t bracket = name.find('('); - size_t bracketEnd = name.find(')'); - if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) { - // Macro - std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1); - name = name.substr(0, bracket); - preprocessorDefinitionsStart[name] = SymbolValue(val, args); - } else { - preprocessorDefinitionsStart[name] = val; - } - } else { - std::string name(cpDefinition); - std::string val("1"); - preprocessorDefinitionsStart[name] = val; - } - } - } - } - } - return firstModification; -} - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\''|| ch == '$'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$'); -} - -static inline bool AllUpperCase(const char *a) { - while (*a) { - if (*a >= 'a' && *a <= 'z') return false; - a++; - } - return true; -} - -// Functor used to truncate history -struct After { - Sci_Position line; - explicit After(Sci_Position line_) : line(line_) {} - bool operator()(PPDefinition &p) const { - return p.line > line; - } -}; - -static std::string GetRestOfLine(LexAccessor &styler, Sci_Position start, bool allowSpace) { - std::string restOfLine; - Sci_Position i =0; - char ch = styler.SafeGetCharAt(start, '\n'); - Sci_Position endLine = styler.LineEnd(styler.GetLine(start)); - while (((start+i) < endLine) && (ch != '\r')) { - char chNext = styler.SafeGetCharAt(start + i + 1, '\n'); - if (ch == '/' && (chNext == '/' || chNext == '*')) - break; - if (allowSpace || (ch != ' ')) - restOfLine += ch; - i++; - ch = chNext; - } - return restOfLine; -} - -static bool IsSpaceOrTab(int ch) { - return ch == ' ' || ch == '\t'; -} - -void SCI_METHOD LexerVerilog::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) -{ - LexAccessor styler(pAccess); - - const int kwOther=0, kwDot=0x100, kwInput=0x200, kwOutput=0x300, kwInout=0x400, kwProtected=0x800; - int lineState = kwOther; - bool continuationLine = false; - - Sci_Position curLine = styler.GetLine(startPos); - if (curLine > 0) lineState = styler.GetLineState(curLine - 1); - - // Do not leak onto next line - if (initStyle == SCE_V_STRINGEOL) - initStyle = SCE_V_DEFAULT; - - if ((MaskActive(initStyle) == SCE_V_PREPROCESSOR) || - (MaskActive(initStyle) == SCE_V_COMMENTLINE) || - (MaskActive(initStyle) == SCE_V_COMMENTLINEBANG)) { - // Set continuationLine if last character of previous line is '\' - if (curLine > 0) { - Sci_Position endLinePrevious = styler.LineEnd(curLine - 1); - if (endLinePrevious > 0) { - continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\'; - } - } - } - - StyleContext sc(startPos, length, initStyle, styler); - LinePPState preproc = vlls.ForLine(curLine); - - bool definitionsChanged = false; - - // Truncate ppDefineHistory before current line - - if (!options.updatePreprocessor) - ppDefineHistory.clear(); - - std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(curLine-1)); - if (itInvalid != ppDefineHistory.end()) { - ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); - definitionsChanged = true; - } - - SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart; - for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { - if (itDef->isUndef) - preprocessorDefinitions.erase(itDef->key); - else - preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments); - } - - int activitySet = preproc.IsInactive() ? activeFlag : 0; - Sci_Position lineEndNext = styler.LineEnd(curLine); - bool isEscapedId = false; // true when parsing an escaped Identifier - bool isProtected = (lineState&kwProtected) != 0; // true when parsing a protected region - - for (; sc.More(); sc.Forward()) { - if (sc.atLineStart) { - if (sc.state == SCE_V_STRING) { - // Prevent SCE_V_STRINGEOL from leaking back to previous line - sc.SetState(SCE_V_STRING); - } - if ((MaskActive(sc.state) == SCE_V_PREPROCESSOR) && (!continuationLine)) { - sc.SetState(SCE_V_DEFAULT|activitySet); - } - if (preproc.IsInactive()) { - activitySet = activeFlag; - sc.SetState(sc.state | activitySet); - } - } - - if (sc.atLineEnd) { - curLine++; - lineEndNext = styler.LineEnd(curLine); - vlls.Add(curLine, preproc); - // Update the line state, so it can be seen by next line - styler.SetLineState(curLine, lineState); - isEscapedId = false; // EOL terminates an escaped Identifier - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (static_cast<Sci_Position>((sc.currentPos+1)) >= lineEndNext) { - curLine++; - lineEndNext = styler.LineEnd(curLine); - vlls.Add(curLine, preproc); - // Update the line state, so it can be seen by next line - styler.SetLineState(curLine, lineState); - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - // Even in UTF-8, \r and \n are separate - sc.Forward(); - } - continuationLine = true; - sc.Forward(); - continue; - } - } - - // for comment keyword - if (MaskActive(sc.state) == SCE_V_COMMENT_WORD && !IsAWordChar(sc.ch)) { - char s[100]; - int state = lineState & 0xff; - sc.GetCurrent(s, sizeof(s)); - if (keywords5.InList(s)) { - sc.ChangeState(SCE_V_COMMENT_WORD|activitySet); - } else { - sc.ChangeState(state|activitySet); - } - sc.SetState(state|activitySet); - } - - const bool atLineEndBeforeSwitch = sc.atLineEnd; - - // Determine if the current state should terminate. - switch (MaskActive(sc.state)) { - case SCE_V_OPERATOR: - sc.SetState(SCE_V_DEFAULT|activitySet); - break; - case SCE_V_NUMBER: - if (!(IsAWordChar(sc.ch) || (sc.ch == '?'))) { - sc.SetState(SCE_V_DEFAULT|activitySet); - } - break; - case SCE_V_IDENTIFIER: - if (!isEscapedId &&(!IsAWordChar(sc.ch) || (sc.ch == '.'))) { - char s[100]; - lineState &= 0xff00; - sc.GetCurrent(s, sizeof(s)); - if (options.portStyling && (strcmp(s, "input") == 0)) { - lineState = kwInput; - sc.ChangeState(SCE_V_INPUT|activitySet); - } else if (options.portStyling && (strcmp(s, "output") == 0)) { - lineState = kwOutput; - sc.ChangeState(SCE_V_OUTPUT|activitySet); - } else if (options.portStyling && (strcmp(s, "inout") == 0)) { - lineState = kwInout; - sc.ChangeState(SCE_V_INOUT|activitySet); - } else if (lineState == kwInput) { - sc.ChangeState(SCE_V_INPUT|activitySet); - } else if (lineState == kwOutput) { - sc.ChangeState(SCE_V_OUTPUT|activitySet); - } else if (lineState == kwInout) { - sc.ChangeState(SCE_V_INOUT|activitySet); - } else if (lineState == kwDot) { - lineState = kwOther; - if (options.portStyling) - sc.ChangeState(SCE_V_PORT_CONNECT|activitySet); - } else if (keywords.InList(s)) { - sc.ChangeState(SCE_V_WORD|activitySet); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_V_WORD2|activitySet); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_V_WORD3|activitySet); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_V_USER|activitySet); - } else if (options.allUppercaseDocKeyword && AllUpperCase(s)) { - sc.ChangeState(SCE_V_USER|activitySet); - } - sc.SetState(SCE_V_DEFAULT|activitySet); - } - break; - case SCE_V_PREPROCESSOR: - if (!IsAWordChar(sc.ch) || sc.atLineEnd) { - sc.SetState(SCE_V_DEFAULT|activitySet); - } - break; - case SCE_V_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_V_DEFAULT|activitySet); - } else if (IsAWordStart(sc.ch)) { - lineState = sc.state | (lineState & 0xff00); - sc.SetState(SCE_V_COMMENT_WORD|activitySet); - } - break; - case SCE_V_COMMENTLINE: - case SCE_V_COMMENTLINEBANG: - if (sc.atLineStart) { - sc.SetState(SCE_V_DEFAULT|activitySet); - } else if (IsAWordStart(sc.ch)) { - lineState = sc.state | (lineState & 0xff00); - sc.SetState(SCE_V_COMMENT_WORD|activitySet); - } - break; - case SCE_V_STRING: - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_V_DEFAULT|activitySet); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_V_STRINGEOL|activitySet); - sc.ForwardSetState(SCE_V_DEFAULT|activitySet); - } - break; - } - - if (sc.atLineEnd && !atLineEndBeforeSwitch) { - // State exit processing consumed characters up to end of line. - curLine++; - lineEndNext = styler.LineEnd(curLine); - vlls.Add(curLine, preproc); - // Update the line state, so it can be seen by next line - styler.SetLineState(curLine, lineState); - isEscapedId = false; // EOL terminates an escaped Identifier - } - - // Determine if a new state should be entered. - if (MaskActive(sc.state) == SCE_V_DEFAULT) { - if (sc.ch == '`') { - sc.SetState(SCE_V_PREPROCESSOR|activitySet); - // Skip whitespace between ` and preprocessor word - do { - sc.Forward(); - } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); - if (sc.atLineEnd) { - sc.SetState(SCE_V_DEFAULT|activitySet); - styler.SetLineState(curLine, lineState); - } else { - if (sc.Match("protected")) { - isProtected = true; - lineState |= kwProtected; - styler.SetLineState(curLine, lineState); - } else if (sc.Match("endprotected")) { - isProtected = false; - lineState &= ~kwProtected; - styler.SetLineState(curLine, lineState); - } else if (!isProtected && options.trackPreprocessor) { - if (sc.Match("ifdef") || sc.Match("ifndef")) { - bool isIfDef = sc.Match("ifdef"); - int i = isIfDef ? 5 : 6; - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false); - bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); - preproc.StartSection(isIfDef == foundDef); - } else if (sc.Match("else")) { - if (!preproc.CurrentIfTaken()) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) { - sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); - } - } else if (!preproc.IsInactive()) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) { - sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); - } - } - } else if (sc.Match("elsif")) { - // Ensure only one chosen out of `if .. `elsif .. `elsif .. `else .. `endif - if (!preproc.CurrentIfTaken()) { - // Similar to `ifdef - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); - bool ifGood = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); - if (ifGood) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) - sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); - } - } else if (!preproc.IsInactive()) { - preproc.InvertCurrentLevel(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - if (!activitySet) - sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); - } - } else if (sc.Match("endif")) { - preproc.EndSection(); - activitySet = preproc.IsInactive() ? activeFlag : 0; - sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); - } else if (sc.Match("define")) { - if (options.updatePreprocessor && !preproc.IsInactive()) { - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); - size_t startName = 0; - while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName])) - startName++; - size_t endName = startName; - while ((endName < restOfLine.length()) && setWord.Contains(static_cast<unsigned char>(restOfLine[endName]))) - endName++; - std::string key = restOfLine.substr(startName, endName-startName); - if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) { - // Macro - size_t endArgs = endName; - while ((endArgs < restOfLine.length()) && (restOfLine[endArgs] != ')')) - endArgs++; - std::string args = restOfLine.substr(endName + 1, endArgs - endName - 1); - size_t startValue = endArgs+1; - while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) - startValue++; - std::string value; - if (startValue < restOfLine.length()) - value = restOfLine.substr(startValue); - preprocessorDefinitions[key] = SymbolValue(value, args); - ppDefineHistory.push_back(PPDefinition(curLine, key, value, false, args)); - definitionsChanged = true; - } else { - // Value - size_t startValue = endName; - while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) - startValue++; - std::string value = restOfLine.substr(startValue); - preprocessorDefinitions[key] = value; - ppDefineHistory.push_back(PPDefinition(curLine, key, value)); - definitionsChanged = true; - } - } - } else if (sc.Match("undefineall")) { - if (options.updatePreprocessor && !preproc.IsInactive()) { - // remove all preprocessor definitions - std::map<std::string, SymbolValue>::iterator itDef; - for(itDef = preprocessorDefinitions.begin(); itDef != preprocessorDefinitions.end(); ++itDef) { - ppDefineHistory.push_back(PPDefinition(curLine, itDef->first, "", true)); - } - preprocessorDefinitions.clear(); - definitionsChanged = true; - } - } else if (sc.Match("undef")) { - if (options.updatePreprocessor && !preproc.IsInactive()) { - std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true); - std::vector<std::string> tokens = Tokenize(restOfLine); - std::string key; - if (tokens.size() >= 1) { - key = tokens[0]; - preprocessorDefinitions.erase(key); - ppDefineHistory.push_back(PPDefinition(curLine, key, "", true)); - definitionsChanged = true; - } - } - } - } - } - } else if (!isProtected) { - if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_V_NUMBER|activitySet); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_V_IDENTIFIER|activitySet); - } else if (sc.Match('/', '*')) { - sc.SetState(SCE_V_COMMENT|activitySet); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('/', '/')) { - if (sc.Match("//!")) // Nice to have a different comment style - sc.SetState(SCE_V_COMMENTLINEBANG|activitySet); - else - sc.SetState(SCE_V_COMMENTLINE|activitySet); - } else if (sc.ch == '\"') { - sc.SetState(SCE_V_STRING|activitySet); - } else if (sc.ch == '\\') { - // escaped identifier, everything is ok up to whitespace - isEscapedId = true; - sc.SetState(SCE_V_IDENTIFIER|activitySet); - } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') { - sc.SetState(SCE_V_OPERATOR|activitySet); - if (sc.ch == '.') lineState = kwDot; - if (sc.ch == ';') lineState = kwOther; - } - } - } - if (isEscapedId && isspacechar(sc.ch)) { - isEscapedId = false; - } - } - if (definitionsChanged) { - styler.ChangeLexerState(startPos, startPos + length); - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_V_COMMENT; -} - -static bool IsCommentLine(Sci_Position line, LexAccessor &styler) { - Sci_Position pos = styler.LineStart(line); - Sci_Position eolPos = styler.LineStart(line + 1) - 1; - for (Sci_Position i = pos; i < eolPos; i++) { - char ch = styler[i]; - char chNext = styler.SafeGetCharAt(i + 1); - int style = styler.StyleAt(i); - if (ch == '/' && chNext == '/' && - (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) { - return true; - } else if (!IsASpaceOrTab(ch)) { - return false; - } - } - return false; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment -// and to make it possible to fiddle the current level for "} else {". -void SCI_METHOD LexerVerilog::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) -{ - LexAccessor styler(pAccess); - bool foldAtBrace = 1; - bool foldAtParenthese = 1; - - Sci_Position lineCurrent = styler.GetLine(startPos); - // Move back one line to be compatible with LexerModule::Fold behavior, fixes problem with foldComment behavior - if (lineCurrent > 0) { - lineCurrent--; - Sci_Position newStartPos = styler.LineStart(lineCurrent); - length += startPos - newStartPos; - startPos = newStartPos; - initStyle = 0; - if (startPos > 0) { - initStyle = styler.StyleAt(startPos - 1); - } - } - Sci_PositionU endPos = startPos + length; - int visibleChars = 0; - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) - levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - int levelMinCurrent = levelCurrent; - int levelNext = levelCurrent; - 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<Sci_Position,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 (Sci_PositionU i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = MaskActive(styler.StyleAt(i + 1)); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (!(stateCurrent & protectedFlag)) { - if (options.foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { - if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) - levelNext++; - else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent+1, styler)) - levelNext--; - } - if (options.foldComment && (style == SCE_V_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelNext++; - } else if (chNext2 == '}') { - levelNext--; - } - } - } - } - if (ch == '`') { - Sci_PositionU j = i + 1; - while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { - j++; - } - if (styler.Match(j, "protected")) { - stateCurrent |= protectedFlag; - levelNext++; - } else if (styler.Match(j, "endprotected")) { - stateCurrent &= ~protectedFlag; - levelNext--; - } else if (!(stateCurrent & protectedFlag) && options.foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { - if (styler.Match(j, "if")) { - if (options.foldPreprocessorElse) { - // Measure the minimum before a begin to allow - // folding on "end else begin" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - } - levelNext++; - } else if (options.foldPreprocessorElse && styler.Match(j, "else")) { - levelNext--; - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (options.foldPreprocessorElse && styler.Match(j, "elsif")) { - levelNext--; - // Measure the minimum before a begin to allow - // folding on "end else begin" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (styler.Match(j, "endif")) { - levelNext--; - } - } - } - if (style == SCE_V_OPERATOR) { - if (foldAtParenthese) { - if (ch == '(') { - levelNext++; - } else if (ch == ')') { - 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; - } - // typedef statements terminated by semicolon - if (stateCurrent & typedefFlag) { - stateCurrent &= ~typedefFlag; - } - } - // 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) { - if (ch == '{') { - levelNext++; - } else if (ch == '}') { - levelNext--; - } - } - } - if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { - Sci_PositionU j = i; - if (styler.Match(j, "case") || - styler.Match(j, "casex") || - styler.Match(j, "casez") || - styler.Match(j, "covergroup") || - styler.Match(j, "function") || - styler.Match(j, "generate") || - styler.Match(j, "interface") || - styler.Match(j, "package") || - styler.Match(j, "primitive") || - styler.Match(j, "program") || - styler.Match(j, "sequence") || - styler.Match(j, "specify") || - styler.Match(j, "table") || - styler.Match(j, "task") || - (styler.Match(j, "module") && options.foldAtModule)) { - levelNext++; - } else if (styler.Match(j, "begin")) { - // Measure the minimum before a begin to allow - // folding on "end else begin" - if (levelMinCurrent > levelNext) { - levelMinCurrent = levelNext; - } - levelNext++; - } else if (styler.Match(j, "class")) { - // class does not introduce a block when used in a typedef statement - if (!(stateCurrent & typedefFlag)) - 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") || - styler.Match(j, "endgenerate") || - styler.Match(j, "endgroup") || - styler.Match(j, "endinterface") || - styler.Match(j, "endpackage") || - styler.Match(j, "endprimitive") || - styler.Match(j, "endprogram") || - styler.Match(j, "endsequence") || - styler.Match(j, "endspecify") || - styler.Match(j, "endtable") || - styler.Match(j, "endtask") || - styler.Match(j, "join") || - styler.Match(j, "join_any") || - styler.Match(j, "join_none") || - (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; - } else if (styler.Match(j, "typedef")) { - stateCurrent |= typedefFlag; - } - } - if (atEOL) { - int levelUse = levelCurrent; - if (options.foldAtElse||options.foldPreprocessorElse) { - levelUse = levelMinCurrent; - } - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && options.foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (stateCurrent) { - foldState[lineCurrent] = stateCurrent; - } - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - levelMinCurrent = levelCurrent; - visibleChars = 0; - } - if (!isspacechar(ch)) - visibleChars++; - } -} - -std::vector<std::string> LexerVerilog::Tokenize(const std::string &expr) const { - // Break into tokens - std::vector<std::string> tokens; - const char *cp = expr.c_str(); - while (*cp) { - std::string word; - if (setWord.Contains(static_cast<unsigned char>(*cp))) { - // Identifiers and numbers - while (setWord.Contains(static_cast<unsigned char>(*cp))) { - word += *cp; - cp++; - } - } else if (IsSpaceOrTab(*cp)) { - while (IsSpaceOrTab(*cp)) { - cp++; - } - continue; - } else { - // Should handle strings, characters, and comments here - word += *cp; - cp++; - } - tokens.push_back(word); - } - return tokens; -} - -static const char * const verilogWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "System Tasks", - "User defined tasks and identifiers", - "Documentation comment keywords", - "Preprocessor definitions", - 0, - }; - -LexerModule lmVerilog(SCLEX_VERILOG, LexerVerilog::LexerFactoryVerilog, "verilog", verilogWordLists); |