📄 lexperl.cxx
字号:
Quote.Open(ch);
} else if (ch == '$') {
if ((chNext == '{') || isspacechar(chNext)) {
styler.ColourTo(i, SCE_PL_SCALAR);
} else {
state = SCE_PL_SCALAR;
if (chNext == '`' && chNext2 == '`') {
i += 2;
ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1);
} else {
i++;
ch = chNext;
chNext = chNext2;
}
}
} else if (ch == '@') {
if (isalpha(chNext) || chNext == '#' || chNext == '$'
|| chNext == '_' || chNext == '+') {
state = SCE_PL_ARRAY;
} else if (chNext != '{' && chNext != '[') {
styler.ColourTo(i, SCE_PL_ARRAY);
i++;
ch = ' ';
} else {
styler.ColourTo(i, SCE_PL_ARRAY);
}
} else if (ch == '%') {
if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
state = SCE_PL_HASH;
} else if (chNext == '{') {
styler.ColourTo(i, SCE_PL_HASH);
} else {
styler.ColourTo(i, SCE_PL_OPERATOR);
}
} else if (ch == '*') {
if (isalpha(chNext) || chNext == '_' || chNext == '{') {
state = SCE_PL_SYMBOLTABLE;
} else {
if (chNext == '*') { // exponentiation
i++;
ch = chNext;
chNext = chNext2;
}
styler.ColourTo(i, SCE_PL_OPERATOR);
}
} else if (ch == '/') {
// Explicit backward peeking to set a consistent preferRE for
// any slash found, so no longer need to track preferRE state.
// Find first previous significant lexed element and interpret.
bool preferRE = false;
unsigned int bk = (i > 0)? i - 1: 0;
char bkch;
styler.Flush();
while ((bk > 0) && (styler.StyleAt(bk) == SCE_PL_DEFAULT ||
styler.StyleAt(bk) == SCE_PL_COMMENTLINE)) {
bk--;
}
if (bk == 0) {
// position 0 won't really be checked; rarely happens
// hard to fix due to an unsigned index i
preferRE = true;
} else {
int bkstyle = styler.StyleAt(bk);
bkch = styler.SafeGetCharAt(bk);
switch(bkstyle) {
case SCE_PL_OPERATOR:
preferRE = true;
if (bkch == ')' || bkch == ']') {
preferRE = false;
} else if (bkch == '}') {
// backtrack further, count balanced brace pairs
// if a brace pair found, see if it's a variable
int braceCount = 1;
while (--bk > 0) {
bkstyle = styler.StyleAt(bk);
if (bkstyle == SCE_PL_OPERATOR) {
bkch = styler.SafeGetCharAt(bk);
if (bkch == ';') { // early out
break;
} else if (bkch == '}') {
braceCount++;
} else if (bkch == '{') {
if (--braceCount == 0)
break;
}
}
}
if (bk == 0) {
// at beginning, true
} else if (braceCount == 0) {
// balanced { found, bk>0, skip more whitespace
if (styler.StyleAt(--bk) == SCE_PL_DEFAULT) {
while (bk > 0) {
bkstyle = styler.StyleAt(--bk);
if (bkstyle != SCE_PL_DEFAULT)
break;
}
}
bkstyle = styler.StyleAt(bk);
if (bkstyle == SCE_PL_SCALAR
|| bkstyle == SCE_PL_ARRAY
|| bkstyle == SCE_PL_HASH
|| bkstyle == SCE_PL_SYMBOLTABLE
|| bkstyle == SCE_PL_OPERATOR) {
preferRE = false;
}
}
}
break;
case SCE_PL_IDENTIFIER:
preferRE = true;
if (bkch == '>') { // inputsymbol
preferRE = false;
break;
}
// backtrack to find "->" or "::" before identifier
while (bk > 0 && styler.StyleAt(bk) == SCE_PL_IDENTIFIER) {
bk--;
}
while (bk > 0) {
bkstyle = styler.StyleAt(bk);
if (bkstyle == SCE_PL_DEFAULT ||
bkstyle == SCE_PL_COMMENTLINE) {
} else if (bkstyle == SCE_PL_OPERATOR) {
// gcc 3.2.3 bloats if more compact form used
bkch = styler.SafeGetCharAt(bk);
if (bkch == '>') { // "->"
if (styler.SafeGetCharAt(bk - 1) == '-') {
preferRE = false;
break;
}
} else if (bkch == ':') { // "::"
if (styler.SafeGetCharAt(bk - 1) == ':') {
preferRE = false;
break;
}
}
} else {// bare identifier, usually a function call but Perl
// optimizes them as pseudo-constants, then the next
// '/' will be a divide; favour divide over regex
// if there is a whitespace after the '/'
if (isspacechar(chNext)) {
preferRE = false;
}
break;
}
bk--;
}
break;
// other styles uses the default, preferRE=false
case SCE_PL_WORD:
case SCE_PL_POD:
case SCE_PL_POD_VERB:
case SCE_PL_HERE_Q:
case SCE_PL_HERE_QQ:
case SCE_PL_HERE_QX:
preferRE = true;
break;
}
}
if (preferRE) {
state = SCE_PL_REGEX;
Quote.New(1);
Quote.Open(ch);
} else {
styler.ColourTo(i, SCE_PL_OPERATOR);
}
} else if (ch == '<' && chNext == '<') {
state = SCE_PL_HERE_DELIM;
HereDoc.State = 0;
} else if (ch == '<') {
// looks forward for matching > on same line
unsigned int fw = i + 1;
while (fw < lengthDoc) {
char fwch = styler.SafeGetCharAt(fw);
if (fwch == ' ') {
if (styler.SafeGetCharAt(fw-1) != '\\' ||
styler.SafeGetCharAt(fw-2) != '\\')
break;
} else if (isEOLChar(fwch) || isspacechar(fwch)) {
break;
} else if (fwch == '>') {
if ((fw - i) == 2 && // '<=>' case
styler.SafeGetCharAt(fw-1) == '=') {
styler.ColourTo(fw, SCE_PL_OPERATOR);
} else {
styler.ColourTo(fw, SCE_PL_IDENTIFIER);
}
i = fw;
ch = fwch;
chNext = styler.SafeGetCharAt(i+1);
}
fw++;
}
styler.ColourTo(i, SCE_PL_OPERATOR);
} else if (ch == '=' // POD
&& isalpha(chNext)
&& (isEOLChar(chPrev))) {
state = SCE_PL_POD;
//sookedpos = 0;
//sooked[sookedpos] = '\0';
} else if (ch == '-' // file test operators
&& isSingleCharOp(chNext)
&& !isalnum((chNext2 = styler.SafeGetCharAt(i+2)))) {
styler.ColourTo(i + 1, SCE_PL_WORD);
state = SCE_PL_DEFAULT;
i++;
ch = chNext;
chNext = chNext2;
} else if (isPerlOperator(ch)) {
if (ch == '.' && chNext == '.') { // .. and ...
i++;
if (chNext2 == '.') { i++; }
state = SCE_PL_DEFAULT;
ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1);
}
styler.ColourTo(i, SCE_PL_OPERATOR);
} else {
// keep colouring defaults to make restart easier
styler.ColourTo(i, SCE_PL_DEFAULT);
}
} else if (state == SCE_PL_NUMBER) {
if (ch == '.') {
if (chNext == '.') {
// double dot is always an operator
goto numAtEnd;
} else if (numState == PERLNUM_NON_DEC || numState == PERLNUM_FLOAT) {
// non-decimal number or float exponent, consume next dot
styler.ColourTo(i - 1, SCE_PL_NUMBER);
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT;
} else { // decimal or vectors allows dots
dotCount++;
if (numState == PERLNUM_DECIMAL) {
if (dotCount > 1) {
if (isdigit(chNext)) { // really a vector
numState = PERLNUM_VECTOR;
} else // number then dot
goto numAtEnd;
}
} else { // vectors
if (!isdigit(chNext)) // vector then dot
goto numAtEnd;
}
}
} else if (ch == '_' && numState == PERLNUM_DECIMAL) {
if (!isdigit(chNext)) {
goto numAtEnd;
}
} else if (isalnum(ch)) {
if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
if (isalpha(ch)) {
if (dotCount == 0) { // change to word
state = SCE_PL_WORD;
} else { // vector then word
goto numAtEnd;
}
}
} else if (numState == PERLNUM_DECIMAL) {
if (ch == 'E' || ch == 'e') { // exponent
numState = PERLNUM_FLOAT;
if (chNext == '+' || chNext == '-') {
i++;
ch = chNext;
chNext = chNext2;
}
} else if (!isdigit(ch)) { // number then word
goto numAtEnd;
}
} else if (numState == PERLNUM_FLOAT) {
if (!isdigit(ch)) { // float then word
goto numAtEnd;
}
} else {// (numState == PERLNUM_NON_DEC)
// allow alphanum for bin,hex,oct for now
}
} else {
// complete current number or vector
numAtEnd:
styler.ColourTo(i - 1, actualNumStyle(numState));
state = SCE_PL_DEFAULT;
goto restartLexer;
}
} else if (state == SCE_PL_WORD) {
if ((!iswordchar(chNext) && chNext != '\'')
|| chNext == '.') {
// ".." is always an operator if preceded by a SCE_PL_WORD.
// "." never used in Perl variable names
// Archaic Perl has quotes inside names
if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")
|| isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__")) {
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else {
classifyWordPerl(styler.GetStartSegment(), i, keywords, styler);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
} else if (state == SCE_PL_IDENTIFIER) {
if ((!iswordchar(chNext) && chNext != '\'')
|| chNext == '.') {
styler.ColourTo(i, SCE_PL_IDENTIFIER);
state = SCE_PL_DEFAULT;
ch = ' ';
}
} else {
if (state == SCE_PL_COMMENTLINE) {
if (isEOLChar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
goto restartLexer;
} else if (isEOLChar(chNext)) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
}
} 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.)
// (This is deprecated, -w warns of this syntax)
// The terminating string must appear by itself (unquoted and with no
// surrounding whitespace) on the terminating line.
//
// From Bash info:
// ---------------
// Specifier format is: <<[-]WORD
// Optional '-' is for removal of leading tabs from here-doc.
// Whitespace acceptable after <<[-] operator.
//
if (HereDoc.State == 0) { // '<<' encountered
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -