aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lexers/LexPowerPro.cxx290
1 files changed, 158 insertions, 132 deletions
diff --git a/lexers/LexPowerPro.cxx b/lexers/LexPowerPro.cxx
index c21d0ab22..cb5773501 100644
--- a/lexers/LexPowerPro.cxx
+++ b/lexers/LexPowerPro.cxx
@@ -12,23 +12,23 @@
// 2008-10-25 - Initial release
// 2008-10-26 - Changed how <name> is hilighted in 'function <name>' so that
// local isFunction = "" and local functions = "" don't get falsely highlighted
-// 2008-12-14 - Added bounds checking for szKeyword and szDo
+// 2008-12-14 - Added bounds checking for szFirstWord and szDo
// - Replaced SetOfCharacters with CharacterSet
// - Made sure that CharacterSet::Contains is passed only positive values
// - Made sure that the return value of Accessor::SafeGetCharAt is positive before
-// passsing to functions that require positive values like isspacechar()
+// passing to functions that require positive values like isspacechar()
// - Removed unused visibleChars processing from ColourisePowerProDoc()
// - Fixed bug with folding logic where line continuations didn't end where
// they were supposed to
// - Moved all helper functions to the top of the file
-//
+// 2010-06-03 - Added onlySpaces variable to allow the @function and ;comment styles to be indented
+// - Modified HasFunction function to be a bit more robust
+// - Renamed HasFunction function to IsFunction
+// - Cleanup
// Copyright 1998-2005 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>
@@ -36,7 +36,6 @@
#include "Scintilla.h"
#include "SciLexer.h"
-#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
@@ -52,65 +51,81 @@ static inline bool IsStreamCommentStyle(int style) {
return style == SCE_POWERPRO_COMMENTBLOCK;
}
+static inline bool IsLineEndChar(unsigned char ch) {
+ return ch == 0x0a //LF
+ || ch == 0x0c //FF
+ || ch == 0x0d; //CR
+}
+
static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
{
- int nsPos = styler.LineStart(szLine);
- int nePos = styler.LineStart(szLine + 1) - 2;
- while (nsPos < nePos)
+ int startPos = styler.LineStart(szLine);
+ int endPos = styler.LineStart(szLine + 1) - 2;
+ while (startPos < endPos)
{
- int stylech = styler.StyleAt(nsPos);
+ char stylech = styler.StyleAt(startPos);
if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) {
- char ch = styler.SafeGetCharAt(nePos);
- char chPrev = styler.SafeGetCharAt(nePos-1);
- char chPrevPrev = styler.SafeGetCharAt(nePos-2);
- if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) {
- if (chPrevPrev == ';' && chPrev == ';' && ch == '+')
- return true;
- else
- return false;
+ char ch = styler.SafeGetCharAt(endPos);
+ char chPrev = styler.SafeGetCharAt(endPos - 1);
+ char chPrevPrev = styler.SafeGetCharAt(endPos - 2);
+ if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) )
+ return (chPrevPrev == ';' && chPrev == ';' && ch == '+');
}
- }
- nePos--; // skip to next char
+ endPos--; // skip to next char
}
return false;
}
// Routine to find first none space on the current line and return its Style
// needed for comment lines not starting on pos 1
-static int GetStyleFirstWord(unsigned int szLine, Accessor &styler)
+static int GetStyleFirstWord(int szLine, Accessor &styler)
{
- int nsPos = styler.LineStart(szLine);
- int nePos = styler.LineStart(szLine+1) - 1;
- char ch = styler.SafeGetCharAt(nsPos);
+ int startPos = styler.LineStart(szLine);
+ int endPos = styler.LineStart(szLine + 1) - 1;
+ char ch = styler.SafeGetCharAt(startPos);
- while (ch > 0 && isspacechar(ch) && nsPos < nePos)
+ while (ch > 0 && isspacechar(ch) && startPos < endPos)
{
- nsPos++; // skip to next char
- ch = styler.SafeGetCharAt(nsPos);
-
+ startPos++; // skip to next char
+ ch = styler.SafeGetCharAt(startPos);
}
- return styler.StyleAt(nsPos);
+ return styler.StyleAt(startPos);
}
//returns true if there is a function to highlight
//used to highlight <name> in 'function <name>'
-static bool HasFunction(Accessor &styler, unsigned int currentPos) {
-
- //check for presence of 'function '
- return (styler.SafeGetCharAt(currentPos) == ' '
- && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n'
- && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o'
- && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i'
- && tolower(styler.SafeGetCharAt(currentPos-4)) == 't'
- && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c'
- && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n'
- && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u'
- && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f'
- //only allow 'function ' to appear at the beginning of a line
- && (styler.SafeGetCharAt(currentPos-9) == '\n'
- || styler.SafeGetCharAt(currentPos-9) == '\r'
- || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line
- );
+//note:
+// sample line (without quotes): "\tfunction asdf()
+// currentPos will be the position of 'a'
+static bool IsFunction(Accessor &styler, unsigned int currentPos) {
+
+ const char function[10] = "function "; //10 includes \0
+ unsigned int numberOfCharacters = sizeof(function) - 1;
+ unsigned int position = currentPos - numberOfCharacters;
+
+ //compare each character with the letters in the function array
+ //return false if ALL don't match
+ for (unsigned int i = 0; i < numberOfCharacters; i++) {
+ char c = styler.SafeGetCharAt(position++);
+ if (c != function[i])
+ return false;
+ }
+
+ //make sure that there are only spaces (or tabs) between the beginning
+ //of the line and the function declaration
+ position = currentPos - numberOfCharacters - 1; //-1 to move to char before 'function'
+ for (unsigned int i = 0; i < 16; i++) { //check up to 16 preceeding characters
+ char c = styler.SafeGetCharAt(position--, '\0'); //if can't read char, return NUL (past beginning of document)
+ if (c <= 0) //reached beginning of document
+ return true;
+ if (c > 0 && IsLineEndChar(c))
+ return true;
+ else if (c > 0 && !IsASpaceOrTab(c))
+ return false;
+ }
+
+ //fall-through
+ return false;
}
static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
@@ -128,9 +143,11 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
StyleContext sc(startPos, length, initStyle, styler);
char s_save[100]; //for last line highlighting
+ //are there only spaces between the first letter of the line and the beginning of the line
+ bool onlySpaces = true;
+
for (; sc.More(); sc.Forward()) {
- // **********************************************
// save the total current word for eof processing
char s[100];
sc.GetCurrentLowered(s, sizeof(s));
@@ -144,8 +161,6 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
s_save[tp+1] = '\0';
}
}
- // **********************************************
- //
if (sc.atLineStart) {
if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) {
@@ -177,6 +192,7 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
+
if (keywords.InList(s)) {
sc.ChangeState(SCE_POWERPRO_WORD);
} else if (keywords2.InList(s)) {
@@ -262,7 +278,7 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
break;
case SCE_POWERPRO_FUNCTION:
- if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ' ' || sc.ch == '(') {
+ if (isspacechar(sc.ch) || sc.ch == '(') {
sc.SetState(SCE_POWERPRO_DEFAULT);
}
break;
@@ -280,9 +296,9 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
sc.SetState(SCE_POWERPRO_ALTQUOTE);
sc.Forward();
}
- } else if (HasFunction(styler, sc.currentPos)) { //highlight <name> in 'function <name>'
+ } else if (IsFunction(styler, sc.currentPos)) { //highlight <name> in 'function <name>'
sc.SetState(SCE_POWERPRO_FUNCTION);
- } else if (sc.ch == '@' && sc.atLineStart) { //alternate function definition [label]
+ } else if (onlySpaces && sc.ch == '@') { //alternate function definition [label]
sc.SetState(SCE_POWERPRO_FUNCTION);
} else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) {
sc.SetState(SCE_POWERPRO_IDENTIFIER);
@@ -293,7 +309,7 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
sc.Forward(); // Eat the * so it isn't used for the end of the comment
} else if (sc.Match('/', '/')) {
sc.SetState(SCE_POWERPRO_COMMENTLINE);
- } else if (sc.atLineStart && sc.ch == ';') { //legacy comment that can only appear at the beginning of a line
+ } else if (onlySpaces && sc.ch == ';') { //legacy comment that can only have blank space in front of it
sc.SetState(SCE_POWERPRO_COMMENTLINE);
} else if (sc.Match(";;")) {
sc.SetState(SCE_POWERPRO_COMMENTLINE);
@@ -305,6 +321,15 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl
sc.SetState(SCE_POWERPRO_OPERATOR);
}
}
+
+ //maintain a record of whether or not all the preceding characters on
+ //a line are space characters
+ if (onlySpaces && !IsASpaceOrTab(sc.ch))
+ onlySpaces = false;
+
+ //reset when starting a new line
+ if (sc.atLineEnd)
+ onlySpaces = true;
}
//*************************************
@@ -341,7 +366,9 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
- bool isFoldingAll = true; //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function)
+ //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function)
+ bool isFoldingAll = true;
+
int endPos = startPos + length;
int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly
@@ -364,31 +391,32 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
int stylePrev = 0;
// find the first previous line without continuation character at the end
- while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
- (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
+ while ((lineCurrent > 0 && IsContinuationLine(lineCurrent, styler))
+ || (lineCurrent > 1 && IsContinuationLine(lineCurrent - 1, styler))) {
lineCurrent--;
startPos = styler.LineStart(lineCurrent);
}
+
if (lineCurrent > 0) {
stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
}
+
// vars for getting first word to check for keywords
- bool FirstWordStart = false;
- bool FirstWordEnd = false;
+ bool isFirstWordStarted = false;
+ bool isFirstWordEnded = false;
- const unsigned int KEYWORD_MAX = 10;
- char szKeyword[KEYWORD_MAX]="";
- unsigned int szKeywordlen = 0;
+ const unsigned int FIRST_WORD_MAX_LEN = 10;
+ char szFirstWord[FIRST_WORD_MAX_LEN] = "";
+ unsigned int firstWordLen = 0;
char szDo[3]="";
int szDolen = 0;
- bool DoFoundLast = false;
+ bool isDoLastWord = false;
// var for indentlevel
int levelCurrent = SC_FOLDLEVELBASE;
- if (lineCurrent > 0) {
+ if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
- }
int levelNext = levelCurrent;
int visibleChars = 0;
@@ -404,52 +432,52 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
- if ((ch > 0) && setWord.Contains(ch)) {
+ if ((ch > 0) && setWord.Contains(ch))
visibleChars++;
- }
// get the syle for the current character neede to check in comment
int stylech = styler.StyleAt(i);
- // get first word for the line for indent check max 9 characters
- if (FirstWordStart && (!(FirstWordEnd))) {
- if ((ch > 0) && !setWord.Contains(ch)) {
- FirstWordEnd = true;
- }
- else if (szKeywordlen < KEYWORD_MAX - 1) {
- szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
- szKeyword[szKeywordlen] = '\0';
- }
- }
-
// start the capture of the first word
- if (!(FirstWordStart)) {
- if ((ch > 0) && (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/')) {
- FirstWordStart = true;
- if (szKeywordlen < KEYWORD_MAX - 1) {
- szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
- szKeyword[szKeywordlen] = '\0';
+ if (!isFirstWordStarted && (ch > 0)) {
+ if (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/') {
+ isFirstWordStarted = true;
+ if (firstWordLen < FIRST_WORD_MAX_LEN - 1) {
+ szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch));
+ szFirstWord[firstWordLen] = '\0';
}
}
+ } // continue capture of the first word on the line
+ else if (isFirstWordStarted && !isFirstWordEnded && (ch > 0)) {
+ if (!setWord.Contains(ch)) {
+ isFirstWordEnded = true;
+ }
+ else if (firstWordLen < (FIRST_WORD_MAX_LEN - 1)) {
+ szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch));
+ szFirstWord[firstWordLen] = '\0';
+ }
}
- // only process this logic when not in comment section
+
if (stylech != SCE_POWERPRO_COMMENTLINE) {
- if (DoFoundLast) {
- if (DoFoundLast && (ch > 0) && setWord.Contains(ch)) {
- DoFoundLast = false;
- }
- }
- // find out if the word "do" is the last on a "if" line
- if (FirstWordEnd && strcmp(szKeyword,"if") == 0) {
+
+ //reset isDoLastWord if we find a character(ignoring spaces) after 'do'
+ if (isDoLastWord && (ch > 0) && setWord.Contains(ch))
+ isDoLastWord = false;
+
+ // --find out if the word "do" is the last on a "if" line--
+ // collect each letter and put it into a buffer 2 chars long
+ // if we end up with "do" in the buffer when we reach the end of
+ // the line, "do" was the last word on the line
+ if ((ch > 0) && isFirstWordEnded && strcmp(szFirstWord, "if") == 0) {
if (szDolen == 2) {
szDo[0] = szDo[1];
szDo[1] = static_cast<char>(tolower(ch));
szDo[2] = '\0';
- if (strcmp(szDo,"do") == 0 ) {
- DoFoundLast = true;
- }
- }
- else if (szDolen < 2) {
+
+ if (strcmp(szDo, "do") == 0)
+ isDoLastWord = true;
+
+ } else if (szDolen < 2) {
szDo[szDolen++] = static_cast<char>(tolower(ch));
szDo[szDolen] = '\0';
}
@@ -457,7 +485,9 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
}
// End of Line found so process the information
- if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
+ if ((ch == '\r' && chNext != '\n') // \r\n
+ || ch == '\n' // \n
+ || i == endPos) { // end of selection
// **************************
// Folding logic for Keywords
@@ -465,24 +495,23 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
// if a keyword is found on the current line and the line doesn't end with ;;+ (continuation)
// and we are not inside a commentblock.
- if (szKeywordlen > 0 &&
- (!(chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev ==';')) &&
- ((!(IsStreamCommentStyle(style)) || foldInComment)) ) {
+ if (firstWordLen > 0
+ && chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev !=';'
+ && (!IsStreamCommentStyle(style) || foldInComment) ) {
// only fold "if" last keyword is "then" (else its a one line if)
- if (strcmp(szKeyword,"if") == 0 && DoFoundLast) {
+ if (strcmp(szFirstWord, "if") == 0 && isDoLastWord)
levelNext++;
- }
+
// create new fold for these words
- if (strcmp(szKeyword,"for") == 0) {
+ if (strcmp(szFirstWord, "for") == 0)
levelNext++;
- }
//handle folding for functions/labels
//Note: Functions and labels don't have an explicit end like [end function]
// 1. functions/labels end at the start of another function
// 2. functions/labels end at the end of the file
- if ((strcmp(szKeyword,"function") == 0) || (szKeywordlen > 0 && szKeyword[0] == '@')) {
+ if ((strcmp(szFirstWord, "function") == 0) || (firstWordLen > 0 && szFirstWord[0] == '@')) {
if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script)
if (functionCount > 0) {
@@ -498,14 +527,15 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
}
// end the fold for these words before the current line
- if (strcmp(szKeyword,"endif") == 0 || strcmp(szKeyword,"endfor") == 0) {
+ if (strcmp(szFirstWord, "endif") == 0 || strcmp(szFirstWord, "endfor") == 0) {
levelNext--;
levelCurrent--;
}
+
// end the fold for these words before the current line and Start new fold
- if (strcmp(szKeyword,"else") == 0 || strcmp(szKeyword,"elseif") == 0 ) {
+ if (strcmp(szFirstWord, "else") == 0 || strcmp(szFirstWord, "elseif") == 0 )
levelCurrent--;
- }
+
}
// Preprocessor and Comment folding
int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);
@@ -514,20 +544,19 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
// Folding logic for Comment blocks
// *********************************
if (foldComment && IsStreamCommentStyle(style)) {
+
// Start of a comment block
- if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) {
+ if (stylePrev != style && IsStreamCommentStyle(styleNext) && styleNext == style) {
levelNext++;
- }
- // fold till the last line for normal comment lines
+ } // fold till the last line for normal comment lines
else if (IsStreamCommentStyle(stylePrev)
- && !(styleNext == SCE_POWERPRO_COMMENTLINE)
+ && styleNext != SCE_POWERPRO_COMMENTLINE
&& stylePrev == SCE_POWERPRO_COMMENTLINE
&& style == SCE_POWERPRO_COMMENTLINE) {
levelNext--;
- }
- // fold till the one but last line for Blockcomment lines
+ } // fold till the one but last line for Blockcomment lines
else if (IsStreamCommentStyle(stylePrev)
- && !(styleNext == SCE_POWERPRO_COMMENTBLOCK)
+ && styleNext != SCE_POWERPRO_COMMENTBLOCK
&& style == SCE_POWERPRO_COMMENTBLOCK) {
levelNext--;
levelCurrent--;
@@ -538,12 +567,10 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
- if (levelUse < levelNext) {
+ if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
- }
- if (lev != styler.LevelAt(lineCurrent)) {
+ if (lev != styler.LevelAt(lineCurrent))
styler.SetLevel(lineCurrent, lev);
- }
// reset values for the next line
lineCurrent++;
@@ -553,18 +580,16 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
visibleChars = 0;
// if the last characters are ;;+ then don't reset since the line continues on the next line.
- if (chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev == ';') {
- //do nothing
- } else {
- szKeywordlen = 0;
+ if (chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev != ';') {
+ firstWordLen = 0;
szDolen = 0;
- FirstWordStart = false;
- FirstWordEnd = false;
- DoFoundLast = false;
- //blank out keyword
- for (unsigned int i = 0; i < KEYWORD_MAX; i++) {
- szKeyword[i] = '\0';
- }
+ isFirstWordStarted = false;
+ isFirstWordEnded = false;
+ isDoLastWord = false;
+
+ //blank out first word
+ for (unsigned int i = 0; i < FIRST_WORD_MAX_LEN; i++)
+ szFirstWord[i] = '\0';
}
}
@@ -573,7 +598,6 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[]
chPrevPrevPrev = chPrevPrev;
chPrevPrev = chPrev;
chPrev = ch;
- visibleChars++;
}
}
@@ -602,3 +626,5 @@ static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int i
}
LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists);
+
+