diff options
| author | nyamatongwe <unknown> | 2003-08-02 04:39:46 +0000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2003-08-02 04:39:46 +0000 | 
| commit | 971e57f07383439f17e0f5c044a8a216a25ef99b (patch) | |
| tree | 54d6f15b498f9388ce4a655ccfb20963cf5603da /src | |
| parent | aebf3ee9c7a9a41cf76fefd9b39c022c243b64fe (diff) | |
| download | scintilla-mirror-971e57f07383439f17e0f5c044a8a216a25ef99b.tar.gz | |
New lexer from Philippe Lhoste replaces previous lexer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/LexPOV.cxx | 257 | 
1 files changed, 170 insertions, 87 deletions
| diff --git a/src/LexPOV.cxx b/src/LexPOV.cxx index 1e44450bb..33ba6a490 100644 --- a/src/LexPOV.cxx +++ b/src/LexPOV.cxx @@ -1,10 +1,19 @@  // Scintilla source code edit control  /** @file LexPOV.cxx - ** Lexer for POV-Ray, based on lexer for C++. + ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language). + ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP...   **/ -// Copyright 2003 by Steven te Brinke <steven.t.b@zonnet.nl> +// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>  // The License.txt file describes the conditions under which this software may be distributed. +// Some points that distinguish from a simple C lexer: +// Identifiers start only by a character. +// No line continuation character. +// Strings are limited to 256 characters. +// Directives are similar to preprocessor commands, +// but we match directive keywords and colorize incorrect ones. +// Block comments can be nested (code stolen from my code in LexLua). +  #include <stdlib.h>  #include <string.h>  #include <ctype.h> @@ -20,90 +29,119 @@  #include "Scintilla.h"  #include "SciLexer.h" -#define KEYWORD_BOXHEADER 1 -#define KEYWORD_FOLDCONTRACTED 2 -  static inline bool IsAWordChar(const int ch) { -	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(const int ch) { -	return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsStateComment(const int state) { -	return ((state == SCE_POV_COMMENT) || -	        (state == SCE_POV_COMMENTLINE) || -	        (state == SCE_POV_COMMENTDOC)); +	return ch < 0x80 && (isalnum(ch) || ch == '_');  } -static inline bool IsStateString(const int state) { -	return ((state == SCE_POV_STRING)); +inline bool IsAWordStart(const int ch) { +	return ch < 0x80 && isalpha(ch);  } -static void ColourisePOVDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], -                            Accessor &styler) { +static void ColourisePovDoc( +	unsigned int startPos, +	int length, +	int initStyle, +	WordList *keywordlists[], +    Accessor &styler) { -	WordList &keywords = *keywordlists[0]; +	WordList &keywords1 = *keywordlists[0];  	WordList &keywords2 = *keywordlists[1]; +	WordList &keywords3 = *keywordlists[2]; +	WordList &keywords4 = *keywordlists[3]; +	WordList &keywords5 = *keywordlists[4]; +	WordList &keywords6 = *keywordlists[5]; +	WordList &keywords7 = *keywordlists[6]; +	WordList &keywords8 = *keywordlists[7]; + +	int currentLine = styler.GetLine(startPos); +	// Initialize the block comment /* */ nesting level, if we are inside such a comment. +	int blockCommentLevel = 0; +	if (initStyle == SCE_POV_COMMENT) { +		blockCommentLevel = styler.GetLineState(currentLine - 1); +	}  	// Do not leak onto next line -	/*if (initStyle == SCE_POV_STRINGEOL) -		initStyle = SCE_POV_DEFAULT;*/ +	if (initStyle == SCE_POV_STRINGEOL) { +		initStyle = SCE_POV_DEFAULT; +	}  	StyleContext sc(startPos, length, initStyle, styler); - -	bool caseSensitive = styler.GetPropertyInt("pov.case.sensitive", 1) != 0; +	short stringLen = 0;  	for (; sc.More(); sc.Forward()) { +		if (sc.atLineEnd) { +			// Update the line state, so it can be seen by next line +			currentLine = styler.GetLine(sc.currentPos); +			if (sc.state == SCE_POV_COMMENT) { +				// Inside a block comment, we set the line state +				styler.SetLineState(currentLine, blockCommentLevel); +			} else { +				// Reset the line state +				styler.SetLineState(currentLine, 0); +			} +		} -		/*if (sc.atLineStart && (sc.state == SCE_POV_STRING)) { +		if (sc.atLineStart && (sc.state == SCE_POV_STRING)) {  			// Prevent SCE_POV_STRINGEOL from leaking back to previous line  			sc.SetState(SCE_POV_STRING); -		}*/ - -		// Handle line continuation generically. -		if (sc.ch == '\\') { -			if (sc.chNext == '\n' || sc.chNext == '\r') { -				sc.Forward(); -				if (sc.ch == '\r' && sc.chNext == '\n') { -					sc.Forward(); -				} -				continue; -			}  		}  		// Determine if the current state should terminate. -		if (sc.state == SCE_POV_OPERATOR || sc.state == SCE_POV_BRACE) { +		if (sc.state == SCE_POV_OPERATOR) {  			sc.SetState(SCE_POV_DEFAULT);  		} else if (sc.state == SCE_POV_NUMBER) { -			if (!IsADigit(sc.ch) || sc.ch != '.') { -				sc.SetState(SCE_POV_DEFAULT); +			// We stop the number definition on non-numerical non-dot non-eE non-sign char +			if (!(isdigit(sc.ch) || sc.ch == '.' || +				  toupper(sc.ch) == 'E' || sc.ch == '-' || sc.ch == '+')) { +					// Not exactly following number definition (several dots are seen as OK, etc.) +					// but probably enough in most cases. +					sc.SetState(SCE_POV_DEFAULT);  			}  		} else if (sc.state == SCE_POV_IDENTIFIER) { -			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { +			if (!IsAWordChar(sc.ch)) {  				char s[100]; -				if (caseSensitive) { -					sc.GetCurrent(s, sizeof(s)); -				} else { -					sc.GetCurrentLowered(s, sizeof(s)); -				} -				if (keywords.InList(s)) { -					sc.ChangeState(SCE_POV_WORD); -				} else if (keywords2.InList(s)) { +				sc.GetCurrent(s, sizeof(s)); +				if (keywords2.InList(s)) {  					sc.ChangeState(SCE_POV_WORD2); +				} else if (keywords3.InList(s)) { +					sc.ChangeState(SCE_POV_WORD3); +				} else if (keywords4.InList(s)) { +					sc.ChangeState(SCE_POV_WORD4); +				} else if (keywords5.InList(s)) { +					sc.ChangeState(SCE_POV_WORD5); +				} else if (keywords6.InList(s)) { +					sc.ChangeState(SCE_POV_WORD6); +				} else if (keywords7.InList(s)) { +					sc.ChangeState(SCE_POV_WORD7); +				} else if (keywords8.InList(s)) { +					sc.ChangeState(SCE_POV_WORD8); +				} +				sc.SetState(SCE_POV_DEFAULT); +			} +		} else if (sc.state == SCE_POV_DIRECTIVE) { +			if (!IsAWordChar(sc.ch)) { +				char s[100], *p; +				sc.GetCurrent(s, sizeof(s)); +				p = s; +				// Skip # and whitespace between # and directive word +				do { +					p++; +				} while ((*p == ' ' || *p == '\t') && *p != '\0'); +				if (!keywords1.InList(p)) { +					sc.ChangeState(SCE_POV_BADDIRECTIVE);  				}  				sc.SetState(SCE_POV_DEFAULT);  			}  		} else if (sc.state == SCE_POV_COMMENT) { -			if (sc.Match('*', '/')) { +			if (sc.Match('/', '*')) { +				blockCommentLevel++;  				sc.Forward(); -				sc.ForwardSetState(SCE_POV_DEFAULT); -			} -		} else if (sc.state == SCE_POV_COMMENTDOC) { -			if (sc.Match('*', '/')) { +			} else if (sc.Match('*', '/') && blockCommentLevel > 0) { +				blockCommentLevel--;  				sc.Forward(); -				sc.ForwardSetState(SCE_POV_DEFAULT); +				if (blockCommentLevel == 0) { +					sc.ForwardSetState(SCE_POV_DEFAULT); +				}  			}  		} else if (sc.state == SCE_POV_COMMENTLINE) {  			if (sc.atLineEnd) { @@ -111,10 +149,32 @@ static void ColourisePOVDoc(unsigned int startPos, int length, int initStyle, Wo  			}  		} else if (sc.state == SCE_POV_STRING) {  			if (sc.ch == '\\') { +				stringLen++; +				if (strchr("abfnrtuv0'\"", sc.chNext)) { +					// Compound characters are counted as one. +					// Note: for Unicode chars \u, we shouldn't count the next 4 digits... +					sc.Forward(); +				} +			} else if (sc.ch == '\"') { +				sc.ForwardSetState(SCE_POV_DEFAULT); +			} else if (sc.atLineEnd) { +				sc.ChangeState(SCE_POV_STRINGEOL); +				sc.ForwardSetState(SCE_POV_DEFAULT); +			} else { +				stringLen++; +			} +			if (stringLen > 256) { +				// Strings are limited to 256 chars +				sc.SetState(SCE_POV_STRINGEOL); +			} +		} else if (sc.state == SCE_POV_STRINGEOL) { +			if (sc.ch == '\\') {  				if (sc.chNext == '\"' || sc.chNext == '\\') {  					sc.Forward();  				}  			} else if (sc.ch == '\"') { +				sc.ForwardSetState(SCE_C_DEFAULT); +			} else if (sc.atLineEnd) {  				sc.ForwardSetState(SCE_POV_DEFAULT);  			}  		} @@ -123,35 +183,43 @@ static void ColourisePOVDoc(unsigned int startPos, int length, int initStyle, Wo  		if (sc.state == SCE_POV_DEFAULT) {  			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {  				sc.SetState(SCE_POV_NUMBER); -			} else if (IsAWordStart(sc.ch) || (sc.ch == '#')) { +			} else if (IsAWordStart(sc.ch)) {  				sc.SetState(SCE_POV_IDENTIFIER);  			} else if (sc.Match('/', '*')) { +				blockCommentLevel = 1;  				sc.SetState(SCE_POV_COMMENT);  				sc.Forward();	// Eat the * so it isn't used for the end of the comment  			} else if (sc.Match('/', '/')) {  				sc.SetState(SCE_POV_COMMENTLINE);  			} else if (sc.ch == '\"') {  				sc.SetState(SCE_POV_STRING); -				//} else if (isoperator(static_cast<char>(sc.ch))) { -			} else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') { +				stringLen = 0; +			} else if (sc.ch == '#') { +				sc.SetState(SCE_POV_DIRECTIVE); +				// Skip whitespace between # and directive word +				do { +					sc.Forward(); +				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); +				if (sc.atLineEnd) { +					sc.SetState(SCE_POV_DEFAULT); +				} +			} else if (isoperator(static_cast<char>(sc.ch))) {  				sc.SetState(SCE_POV_OPERATOR); -			} else if (sc.ch == '{' || sc.ch == '}') { -				sc.SetState(SCE_POV_BRACE);  			}  		} -  	}  	sc.Complete();  } -static bool IsStreamCommentStyle(int style) { -	return style == SCE_POV_COMMENT || -	       style == SCE_POV_COMMENTDOC; -} +static void FoldPovDoc( +	unsigned int startPos, +	int length, +	int initStyle, +	WordList *[], +	Accessor &styler) { -static void FoldNoBoxPOVDoc(unsigned int startPos, int length, int initStyle, -                            Accessor &styler) { -	bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0; +	bool foldComment = styler.GetPropertyInt("fold.comment") != 0; +	bool foldDirective = styler.GetPropertyInt("fold.directive") != 0;  	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;  	unsigned int endPos = startPos + length;  	int visibleChars = 0; @@ -168,15 +236,33 @@ static void FoldNoBoxPOVDoc(unsigned int startPos, int length, int initStyle,  		style = styleNext;  		styleNext = styler.StyleAt(i + 1);  		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); -		if (foldComment && IsStreamCommentStyle(style)) { -			if (!IsStreamCommentStyle(stylePrev)) { +		if (foldComment && (style == SCE_POV_COMMENT)) { +			if (stylePrev != SCE_POV_COMMENT) {  				levelCurrent++; -			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) { +			} else if ((styleNext != SCE_POV_COMMENT) && !atEOL) {  				// Comments don't end at end of line and the next character may be unstyled.  				levelCurrent--;  			}  		} -		if (style == SCE_POV_BRACE) { +		if (foldComment && (style == SCE_POV_COMMENTLINE)) { +			if ((ch == '/') && (chNext == '/')) { +				char chNext2 = styler.SafeGetCharAt(i + 2); +				if (chNext2 == '{') { +					levelCurrent++; +				} else if (chNext2 == '}') { +					levelCurrent--; +				} +			} +		} +		if (foldDirective && (style == SCE_POV_DIRECTIVE)) { +			if (ch == '#') { +				unsigned int j=i+1; +				while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { +					j++; +				} +			} +		} +		if (style == SCE_POV_OPERATOR) {  			if (ch == '{') {  				levelCurrent++;  			} else if (ch == '}') { @@ -204,19 +290,16 @@ static void FoldNoBoxPOVDoc(unsigned int startPos, int length, int initStyle,  	styler.SetLevel(lineCurrent, levelPrev | flagsNext);  } -static void FoldPOVDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { -	FoldNoBoxPOVDoc(startPos, length, initStyle, styler); -} - -static const char * const POVWordLists[] = { -            "Primary keywords and identifiers", -            "Secondary keywords and identifiers", -            0, -        }; - -static void ColourisePOVDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], -                                     Accessor &styler) { -	ColourisePOVDoc(startPos, length, initStyle, keywordlists, styler); -} +static const char * const povWordLists[] = { +	"Language directives", +	"Objects & CSG & Appearance", +	"Types & Modifiers & Items", +	"Predefined Identifiers", +	"Predefined Functions", +	"User defined 1", +	"User defined 2", +	"User defined 3", +	0, +}; -LexerModule lmPOV(SCLEX_POV, ColourisePOVDocSensitive, "pov", FoldPOVDoc, POVWordLists); +LexerModule lmPOV(SCLEX_POV, ColourisePovDoc, "pov", FoldPovDoc, povWordLists); | 
