123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- // Scintilla source code edit control
- /**
- * @file LexRegistry.cxx
- * @date July 26 2014
- * @brief Lexer for Windows registration files(.reg)
- * @author nkmathew
- *
- * The License.txt file describes the conditions under which this software may be
- * distributed.
- *
- */
- #include <cstdlib>
- #include <cassert>
- #include <cctype>
- #include <cstdio>
- #include <string>
- #include <vector>
- #include <map>
- #include "ILexer.h"
- #include "Scintilla.h"
- #include "SciLexer.h"
- #include "WordList.h"
- #include "LexAccessor.h"
- #include "StyleContext.h"
- #include "CharacterSet.h"
- #include "LexerModule.h"
- #include "OptionSet.h"
- #ifdef SCI_NAMESPACE
- using namespace Scintilla;
- #endif
- static const char *const RegistryWordListDesc[] = {
- 0
- };
- struct OptionsRegistry {
- bool foldCompact;
- bool fold;
- OptionsRegistry() {
- foldCompact = false;
- fold = false;
- }
- };
- struct OptionSetRegistry : public OptionSet<OptionsRegistry> {
- OptionSetRegistry() {
- DefineProperty("fold.compact", &OptionsRegistry::foldCompact);
- DefineProperty("fold", &OptionsRegistry::fold);
- DefineWordListSets(RegistryWordListDesc);
- }
- };
- class LexerRegistry : public ILexer {
- OptionsRegistry options;
- OptionSetRegistry optSetRegistry;
- static bool IsStringState(int state) {
- return (state == SCE_REG_VALUENAME || state == SCE_REG_STRING);
- }
- static bool IsKeyPathState(int state) {
- return (state == SCE_REG_ADDEDKEY || state == SCE_REG_DELETEDKEY);
- }
- static bool AtValueType(LexAccessor &styler, Sci_Position start) {
- Sci_Position i = 0;
- while (i < 10) {
- i++;
- char curr = styler.SafeGetCharAt(start+i, '\0');
- if (curr == ':') {
- return true;
- } else if (!curr) {
- return false;
- }
- }
- return false;
- }
- static bool IsNextNonWhitespace(LexAccessor &styler, Sci_Position start, char ch) {
- Sci_Position i = 0;
- while (i < 100) {
- i++;
- char curr = styler.SafeGetCharAt(start+i, '\0');
- char next = styler.SafeGetCharAt(start+i+1, '\0');
- bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n');
- if (curr == ch) {
- return true;
- } else if (!isspacechar(curr) || atEOL) {
- return false;
- }
- }
- return false;
- }
- // Looks for the equal sign at the end of the string
- static bool AtValueName(LexAccessor &styler, Sci_Position start) {
- bool atEOL = false;
- Sci_Position i = 0;
- bool escaped = false;
- while (!atEOL) {
- i++;
- char curr = styler.SafeGetCharAt(start+i, '\0');
- char next = styler.SafeGetCharAt(start+i+1, '\0');
- atEOL = (curr == '\r' && next != '\n') || (curr == '\n');
- if (escaped) {
- escaped = false;
- continue;
- }
- escaped = curr == '\\';
- if (curr == '"') {
- return IsNextNonWhitespace(styler, start+i, '=');
- } else if (!curr) {
- return false;
- }
- }
- return false;
- }
- static bool AtKeyPathEnd(LexAccessor &styler, Sci_Position start) {
- bool atEOL = false;
- Sci_Position i = 0;
- while (!atEOL) {
- i++;
- char curr = styler.SafeGetCharAt(start+i, '\0');
- char next = styler.SafeGetCharAt(start+i+1, '\0');
- atEOL = (curr == '\r' && next != '\n') || (curr == '\n');
- if (curr == ']' || !curr) {
- // There's still at least one or more square brackets ahead
- return false;
- }
- }
- return true;
- }
- static bool AtGUID(LexAccessor &styler, Sci_Position start) {
- int count = 8;
- int portion = 0;
- int offset = 1;
- char digit = '\0';
- while (portion < 5) {
- int i = 0;
- while (i < count) {
- digit = styler.SafeGetCharAt(start+offset);
- if (!(isxdigit(digit) || digit == '-')) {
- return false;
- }
- offset++;
- i++;
- }
- portion++;
- count = (portion == 4) ? 13 : 5;
- }
- digit = styler.SafeGetCharAt(start+offset);
- if (digit == '}') {
- return true;
- } else {
- return false;
- }
- }
- public:
- LexerRegistry() {}
- virtual ~LexerRegistry() {}
- virtual int SCI_METHOD Version() const {
- return lvOriginal;
- }
- virtual void SCI_METHOD Release() {
- delete this;
- }
- virtual const char *SCI_METHOD PropertyNames() {
- return optSetRegistry.PropertyNames();
- }
- virtual int SCI_METHOD PropertyType(const char *name) {
- return optSetRegistry.PropertyType(name);
- }
- virtual const char *SCI_METHOD DescribeProperty(const char *name) {
- return optSetRegistry.DescribeProperty(name);
- }
- virtual Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) {
- if (optSetRegistry.PropertySet(&options, key, val)) {
- return 0;
- }
- return -1;
- }
- virtual Sci_Position SCI_METHOD WordListSet(int, const char *) {
- return -1;
- }
- virtual void *SCI_METHOD PrivateCall(int, void *) {
- return 0;
- }
- static ILexer *LexerFactoryRegistry() {
- return new LexerRegistry;
- }
- virtual const char *SCI_METHOD DescribeWordListSets() {
- return optSetRegistry.DescribeWordListSets();
- }
- virtual void SCI_METHOD Lex(Sci_PositionU startPos,
- Sci_Position length,
- int initStyle,
- IDocument *pAccess);
- virtual void SCI_METHOD Fold(Sci_PositionU startPos,
- Sci_Position length,
- int initStyle,
- IDocument *pAccess);
- };
- void SCI_METHOD LexerRegistry::Lex(Sci_PositionU startPos,
- Sci_Position length,
- int initStyle,
- IDocument *pAccess) {
- int beforeGUID = SCE_REG_DEFAULT;
- int beforeEscape = SCE_REG_DEFAULT;
- CharacterSet setOperators = CharacterSet(CharacterSet::setNone, "-,.=:\\@()");
- LexAccessor styler(pAccess);
- StyleContext context(startPos, length, initStyle, styler);
- bool highlight = true;
- bool afterEqualSign = false;
- while (context.More()) {
- if (context.atLineStart) {
- Sci_Position currPos = static_cast<Sci_Position>(context.currentPos);
- bool continued = styler[currPos-3] == '\\';
- highlight = continued ? true : false;
- }
- switch (context.state) {
- case SCE_REG_COMMENT:
- if (context.atLineEnd) {
- context.SetState(SCE_REG_DEFAULT);
- }
- break;
- case SCE_REG_VALUENAME:
- case SCE_REG_STRING: {
- Sci_Position currPos = static_cast<Sci_Position>(context.currentPos);
- if (context.ch == '"') {
- context.ForwardSetState(SCE_REG_DEFAULT);
- } else if (context.ch == '\\') {
- beforeEscape = context.state;
- context.SetState(SCE_REG_ESCAPED);
- context.Forward();
- } else if (context.ch == '{') {
- if (AtGUID(styler, currPos)) {
- beforeGUID = context.state;
- context.SetState(SCE_REG_STRING_GUID);
- }
- }
- if (context.state == SCE_REG_STRING &&
- context.ch == '%' &&
- (isdigit(context.chNext) || context.chNext == '*')) {
- context.SetState(SCE_REG_PARAMETER);
- }
- }
- break;
- case SCE_REG_PARAMETER:
- context.ForwardSetState(SCE_REG_STRING);
- if (context.ch == '"') {
- context.ForwardSetState(SCE_REG_DEFAULT);
- }
- break;
- case SCE_REG_VALUETYPE:
- if (context.ch == ':') {
- context.SetState(SCE_REG_DEFAULT);
- afterEqualSign = false;
- }
- break;
- case SCE_REG_HEXDIGIT:
- case SCE_REG_OPERATOR:
- context.SetState(SCE_REG_DEFAULT);
- break;
- case SCE_REG_DELETEDKEY:
- case SCE_REG_ADDEDKEY: {
- Sci_Position currPos = static_cast<Sci_Position>(context.currentPos);
- if (context.ch == ']' && AtKeyPathEnd(styler, currPos)) {
- context.ForwardSetState(SCE_REG_DEFAULT);
- } else if (context.ch == '{') {
- if (AtGUID(styler, currPos)) {
- beforeGUID = context.state;
- context.SetState(SCE_REG_KEYPATH_GUID);
- }
- }
- }
- break;
- case SCE_REG_ESCAPED:
- if (context.ch == '"') {
- context.SetState(beforeEscape);
- context.ForwardSetState(SCE_REG_DEFAULT);
- } else if (context.ch == '\\') {
- context.Forward();
- } else {
- context.SetState(beforeEscape);
- beforeEscape = SCE_REG_DEFAULT;
- }
- break;
- case SCE_REG_STRING_GUID:
- case SCE_REG_KEYPATH_GUID: {
- if (context.ch == '}') {
- context.ForwardSetState(beforeGUID);
- beforeGUID = SCE_REG_DEFAULT;
- }
- Sci_Position currPos = static_cast<Sci_Position>(context.currentPos);
- if (context.ch == '"' && IsStringState(context.state)) {
- context.ForwardSetState(SCE_REG_DEFAULT);
- } else if (context.ch == ']' &&
- AtKeyPathEnd(styler, currPos) &&
- IsKeyPathState(context.state)) {
- context.ForwardSetState(SCE_REG_DEFAULT);
- } else if (context.ch == '\\' && IsStringState(context.state)) {
- beforeEscape = context.state;
- context.SetState(SCE_REG_ESCAPED);
- context.Forward();
- }
- }
- break;
- }
- // Determine if a new state should be entered.
- if (context.state == SCE_REG_DEFAULT) {
- Sci_Position currPos = static_cast<Sci_Position>(context.currentPos);
- if (context.ch == ';') {
- context.SetState(SCE_REG_COMMENT);
- } else if (context.ch == '"') {
- if (AtValueName(styler, currPos)) {
- context.SetState(SCE_REG_VALUENAME);
- } else {
- context.SetState(SCE_REG_STRING);
- }
- } else if (context.ch == '[') {
- if (IsNextNonWhitespace(styler, currPos, '-')) {
- context.SetState(SCE_REG_DELETEDKEY);
- } else {
- context.SetState(SCE_REG_ADDEDKEY);
- }
- } else if (context.ch == '=') {
- afterEqualSign = true;
- highlight = true;
- } else if (afterEqualSign) {
- bool wordStart = isalpha(context.ch) && !isalpha(context.chPrev);
- if (wordStart && AtValueType(styler, currPos)) {
- context.SetState(SCE_REG_VALUETYPE);
- }
- } else if (isxdigit(context.ch) && highlight) {
- context.SetState(SCE_REG_HEXDIGIT);
- }
- highlight = (context.ch == '@') ? true : highlight;
- if (setOperators.Contains(context.ch) && highlight) {
- context.SetState(SCE_REG_OPERATOR);
- }
- }
- context.Forward();
- }
- context.Complete();
- }
- // Folding similar to that of FoldPropsDoc in LexOthers
- void SCI_METHOD LexerRegistry::Fold(Sci_PositionU startPos,
- Sci_Position length,
- int,
- IDocument *pAccess) {
- if (!options.fold) {
- return;
- }
- LexAccessor styler(pAccess);
- Sci_Position currLine = styler.GetLine(startPos);
- int visibleChars = 0;
- Sci_PositionU endPos = startPos + length;
- bool atKeyPath = false;
- for (Sci_PositionU i = startPos; i < endPos; i++) {
- atKeyPath = IsKeyPathState(styler.StyleAt(i)) ? true : atKeyPath;
- char curr = styler.SafeGetCharAt(i);
- char next = styler.SafeGetCharAt(i+1);
- bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n');
- if (atEOL || i == (endPos-1)) {
- int level = SC_FOLDLEVELBASE;
- if (currLine > 0) {
- int prevLevel = styler.LevelAt(currLine-1);
- if (prevLevel & SC_FOLDLEVELHEADERFLAG) {
- level += 1;
- } else {
- level = prevLevel;
- }
- }
- if (!visibleChars && options.foldCompact) {
- level |= SC_FOLDLEVELWHITEFLAG;
- } else if (atKeyPath) {
- level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
- }
- if (level != styler.LevelAt(currLine)) {
- styler.SetLevel(currLine, level);
- }
- currLine++;
- visibleChars = 0;
- atKeyPath = false;
- }
- if (!isspacechar(curr)) {
- visibleChars++;
- }
- }
- // Make the folding reach the last line in the file
- int level = SC_FOLDLEVELBASE;
- if (currLine > 0) {
- int prevLevel = styler.LevelAt(currLine-1);
- if (prevLevel & SC_FOLDLEVELHEADERFLAG) {
- level += 1;
- } else {
- level = prevLevel;
- }
- }
- styler.SetLevel(currLine, level);
- }
- LexerModule lmRegistry(SCLEX_REGISTRY,
- LexerRegistry::LexerFactoryRegistry,
- "registry",
- RegistryWordListDesc);
|