diff options
author | nyamatongwe <devnull@localhost> | 2000-11-21 11:25:43 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2000-11-21 11:25:43 +0000 |
commit | 216b5395e9f11f4a5ae63bd08c154d72d4bb0cb4 (patch) | |
tree | 7473a6545465389e9e1c2b8c2f75c78333357db6 | |
parent | 46dcb7e7c6c68ae4a7e97ec10d1e932bb5c951ce (diff) | |
download | scintilla-mirror-216b5395e9f11f4a5ae63bd08c154d72d4bb0cb4.tar.gz |
Steffen's patch for here documents.
-rw-r--r-- | include/SciLexer.h | 6 | ||||
-rw-r--r-- | include/Scintilla.iface | 6 | ||||
-rw-r--r-- | src/LexPerl.cxx | 192 |
3 files changed, 170 insertions, 34 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h index 7edf11a4d..98b5e29a7 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -158,7 +158,7 @@ #define SCE_HPHP_COMMENTLINE 125 #define SCE_HPHP_STRINGEOL 126 #define SCE_PL_DEFAULT 0 -#define SCE_PL_HERE 1 +#define SCE_PL_ERROR 1 #define SCE_PL_COMMENTLINE 2 #define SCE_PL_POD 3 #define SCE_PL_NUMBER 4 @@ -179,6 +179,10 @@ #define SCE_PL_LONGQUOTE 19 #define SCE_PL_BACKTICKS 20 #define SCE_PL_DATASECTION 21 +#define SCE_PL_HERE_DELIM 22 +#define SCE_PL_HERE_Q 23 +#define SCE_PL_HERE_QQ 24 +#define SCE_PL_HERE_QX 25 #define SCE_L_DEFAULT 0 #define SCE_L_COMMAND 1 #define SCE_L_TAG 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 8b1791408..068798f2a 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -1259,7 +1259,7 @@ val SCE_HPHP_COMMENTLINE=125 val SCE_HPHP_STRINGEOL=126 # Lexical states for SCLEX_PERL val SCE_PL_DEFAULT=0 -val SCE_PL_HERE=1 +val SCE_PL_ERROR=1 val SCE_PL_COMMENTLINE=2 val SCE_PL_POD=3 val SCE_PL_NUMBER=4 @@ -1280,6 +1280,10 @@ val SCE_PL_REGSUBST=18 val SCE_PL_LONGQUOTE=19 val SCE_PL_BACKTICKS=20 val SCE_PL_DATASECTION=21 +val SCE_PL_HERE_DELIM=22 +val SCE_PL_HERE_Q=23 +val SCE_PL_HERE_QQ=24 +val SCE_PL_HERE_QX=25 # Lexical states for SCLEX_LATEX val SCE_L_DEFAULT=0 val SCE_L_COMMAND=1 diff --git a/src/LexPerl.cxx b/src/LexPerl.cxx index 7bc08f333..1f86267fe 100644 --- a/src/LexPerl.cxx +++ b/src/LexPerl.cxx @@ -3,11 +3,11 @@ // Copyright 1998-2000 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 <ctype.h> -#include <stdio.h> -#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> #include "Platform.h" @@ -85,9 +85,28 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, // Lexer for perl often has to backtrack to start of current style to determine // which characters are being used as quotes, how deeply nested is the // start position and what the termination string is for here documents - + WordList &keywords = *keywordlists[0]; - + + class HereDocCls + { + public: + int State; // 0: '<<' encountered + // 1: collect the delimiter + // 2: here doc text (lines after the delimiter) + char Quote; // the char after '<<' + bool Quoted; // true if Quote in ('\'','"','`') + int DelimiterLength; // strlen(Delimiter) + char Delimiter[256]; // the Delimiter, 256: sizeof PL_tokenbuf + HereDocCls() + { + State = 0; + DelimiterLength = 0; + Delimiter[0] = '\0'; + } + }; + HereDocCls HereDoc; // TODO: FIFO for stacked here-docs + char sooked[100]; int quotes = 0; char quoteDown = 'd'; @@ -98,18 +117,28 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, sooked[sookedpos] = '\0'; int state = initStyle; int lengthDoc = startPos + length; + // If in a long distance lexical state, seek to the beginning to find quote characters - if (state == SCE_PL_HERE || state == SCE_PL_REGEX || + if (state == SCE_PL_HERE_Q || state == SCE_PL_HERE_QQ || state == SCE_PL_HERE_QX) { + while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_PL_HERE_DELIM)) { + startPos--; + } + startPos = styler.LineStart(styler.GetLine(startPos)); + state = styler.StyleAt(startPos - 1); + } + if (state == SCE_PL_REGEX || state == SCE_PL_REGSUBST || state == SCE_PL_LONGQUOTE) { while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) { startPos--; } state = SCE_PL_DEFAULT; } + styler.StartAt(startPos); char chPrev = styler.SafeGetCharAt(startPos - 1); char chNext = styler[startPos]; styler.StartSegment(startPos); + for (int i = startPos; i < lengthDoc; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -121,6 +150,35 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, i += 1; continue; } + if ((chPrev == '\r' && ch == '\n')) { // skip on DOS/Windows + chPrev = ch; + continue; + } + + if (HereDoc.State == 1 && (ch == '\r' || ch == '\n')) { + // Begin of here-doc (the line after the here-doc delimiter): + HereDoc.State = 2; + styler.ColourTo(i - 1, state); + if (HereDoc.Quoted) { + if (state == SCE_PL_HERE_DELIM) { + // Missing quote at end of string! We are stricter than perl. + state = SCE_PL_ERROR; + } + else { + switch (HereDoc.Quote) { + case '\'': state = SCE_PL_HERE_Q ; break; + case '"': state = SCE_PL_HERE_QQ; break; + case '`': state = SCE_PL_HERE_QX; break; + } + } + } + else { + switch (HereDoc.Quote) { + case '\\': state = SCE_PL_HERE_Q ; break; + default : state = SCE_PL_HERE_QQ; + } + } + } if (state == SCE_PL_DEFAULT) { if (iswordstart(ch)) { @@ -221,15 +279,11 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, quoteDown = '/'; quotes = 1; quoteRep = 1; + } else if (ch == '<' && chNext == '<') { styler.ColourTo(i - 1, state); - state = SCE_PL_HERE; - i++; - ch = chNext; - chNext = chNext2; - quotes = 0; - sookedpos = 0; - sooked[sookedpos] = '\0'; + state = SCE_PL_HERE_DELIM; + HereDoc.State = 0; } else if (ch == '=' && (chPrev == '\r' || chPrev == '\n') && isalpha(chNext)) { styler.ColourTo(i - 1, state); state = SCE_PL_POD; @@ -263,10 +317,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, } else if (ch == '\'') { state = SCE_PL_CHARACTER; } else if (ch == '<' && chNext == '<') { - state = SCE_PL_HERE; - quotes = 0; - sookedpos = 0; - sooked[sookedpos] = '\0'; + state = SCE_PL_HERE_DELIM; + HereDoc.State = 0; } else if (isPerlOperator(ch)) { if (ch == ')' || ch == ']') preferRE = false; @@ -283,23 +335,96 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, styler.ColourTo(i - 1, state); state = SCE_PL_DEFAULT; } - } else if (state == SCE_PL_HERE) { - if ((isalnum(ch) || ch == '_') && quotes < 2) { - sooked[sookedpos++] = ch; - sooked[sookedpos] = '\0'; - if (quotes == 0) - quotes = 1; - } else { - quotes++; + } else if (state == SCE_PL_HERE_DELIM) { + // + // From perldata.pod: + // ------------------ + // A line-oriented form of quoting is based on the shell ``here-doc'' + // syntax. + // Following a << you specify a string to terminate the quoted material, + // and all lines following the current line down to the terminating + // string are the value of the item. + // The terminating string may be either an identifier (a word), + // or some quoted text. + // If quoted, the type of quotes you use determines the treatment of + // the text, just as in regular quoting. + // An unquoted identifier works like double quotes. + // There must be no space between the << and the identifier. + // (If you put a space it will be treated as a null identifier, + // which is valid, and matches the first empty line.) + // The terminating string must appear by itself (unquoted and with no + // surrounding whitespace) on the terminating line. + // + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.State = 1; + HereDoc.Quote = chNext; + HereDoc.Quoted = false; + HereDoc.DelimiterLength = 0; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + if (chNext == '\'' || chNext == '"' || chNext == '`') { // a quoted here-doc delimiter + i++; + ch = chNext; + chNext = chNext2; + HereDoc.Quoted = true; + } + else if (chNext == '\\') { // ref? + i++; + ch = chNext; + chNext = chNext2; + } + else if (isalnum(chNext) || chNext == '_') + { // an unquoted here-doc delimiter + } + else if (isspace(chNext)) + { // deprecated here-doc delimiter || TODO: left shift operator + } + else + { // TODO: ??? + } + } + else if (HereDoc.State == 1) { // collect the delimiter + if (HereDoc.Quoted) { // a quoted here-doc delimiter + if (ch == HereDoc.Quote) { // closing quote => end of delimiter + styler.ColourTo(i, state); + state = SCE_PL_DEFAULT; + i++; + ch = chNext; + chNext = chNext2; + } + else { + if (ch == '\\' && chNext == HereDoc.Quote) { // escaped quote + i++; + ch = chNext; + chNext = chNext2; + } + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } + } + else { // an unquoted here-doc delimiter + if (isalnum(ch) || ch == '_') { + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } + else { + styler.ColourTo(i - 1, state); + state = SCE_PL_DEFAULT; + } + } + if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) { + styler.ColourTo(i - 1, state); + state = SCE_PL_ERROR; + } } - if ((quotes > 1) && - (chPrev == '\n' || chPrev == '\r') && - isMatch(styler, lengthDoc, i, sooked)) { - i += sookedpos; + } else if (HereDoc.State == 2) { + // state == SCE_PL_HERE_Q || state == SCE_PL_HERE_QQ || state == SCE_PL_HERE_QX + if ((chPrev == '\n' || chPrev == '\r') && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { + i += HereDoc.DelimiterLength; chNext = styler.SafeGetCharAt(i); if (chNext == '\n' || chNext == '\r') { - styler.ColourTo(i - 1, SCE_PL_HERE); + styler.ColourTo(i - 1, state); state = SCE_PL_DEFAULT; + HereDoc.State = 0; } ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -510,6 +635,9 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, } } } + if (state == SCE_PL_ERROR) { + break; + } chPrev = ch; } styler.ColourTo(lengthDoc, state); |