]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexR.cxx
1 // Scintilla source code edit control
3 ** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer).
6 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
28 using namespace Scintilla
;
31 static inline bool IsAWordChar(const int ch
) {
32 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
35 static inline bool IsAWordStart(const int ch
) {
36 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
39 static inline bool IsAnOperator(const int ch
) {
40 if (isascii(ch
) && isalnum(ch
))
42 // '.' left out as it is used to make up numbers
43 if (ch
== '-' || ch
== '+' || ch
== '!' || ch
== '~' ||
44 ch
== '?' || ch
== ':' || ch
== '*' || ch
== '/' ||
45 ch
== '^' || ch
== '<' || ch
== '>' || ch
== '=' ||
46 ch
== '&' || ch
== '|' || ch
== '$' || ch
== '(' ||
47 ch
== ')' || ch
== '}' || ch
== '{' || ch
== '[' ||
53 static void ColouriseRDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
56 WordList
&keywords
= *keywordlists
[0];
57 WordList
&keywords2
= *keywordlists
[1];
58 WordList
&keywords3
= *keywordlists
[2];
61 // Do not leak onto next line
62 if (initStyle
== SCE_R_INFIXEOL
)
63 initStyle
= SCE_R_DEFAULT
;
66 StyleContext
sc(startPos
, length
, initStyle
, styler
);
68 for (; sc
.More(); sc
.Forward()) {
70 if (sc
.atLineStart
&& (sc
.state
== SCE_R_STRING
)) {
71 // Prevent SCE_R_STRINGEOL from leaking back to previous line
72 sc
.SetState(SCE_R_STRING
);
75 // Determine if the current state should terminate.
76 if (sc
.state
== SCE_R_OPERATOR
) {
77 sc
.SetState(SCE_R_DEFAULT
);
78 } else if (sc
.state
== SCE_R_NUMBER
) {
79 if (!IsADigit(sc
.ch
) && !(sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
80 sc
.SetState(SCE_R_DEFAULT
);
82 } else if (sc
.state
== SCE_R_IDENTIFIER
) {
83 if (!IsAWordChar(sc
.ch
)) {
85 sc
.GetCurrent(s
, sizeof(s
));
86 if (keywords
.InList(s
)) {
87 sc
.ChangeState(SCE_R_KWORD
);
88 } else if (keywords2
.InList(s
)) {
89 sc
.ChangeState(SCE_R_BASEKWORD
);
90 } else if (keywords3
.InList(s
)) {
91 sc
.ChangeState(SCE_R_OTHERKWORD
);
93 sc
.SetState(SCE_R_DEFAULT
);
95 } else if (sc
.state
== SCE_R_COMMENT
) {
96 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
97 sc
.SetState(SCE_R_DEFAULT
);
99 } else if (sc
.state
== SCE_R_STRING
) {
101 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
104 } else if (sc
.ch
== '\"') {
105 sc
.ForwardSetState(SCE_R_DEFAULT
);
107 } else if (sc
.state
== SCE_R_INFIX
) {
109 sc
.ForwardSetState(SCE_R_DEFAULT
);
110 } else if (sc
.atLineEnd
) {
111 sc
.ChangeState(SCE_R_INFIXEOL
);
112 sc
.ForwardSetState(SCE_R_DEFAULT
);
114 }else if (sc
.state
== SCE_R_STRING2
) {
116 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
119 } else if (sc
.ch
== '\'') {
120 sc
.ForwardSetState(SCE_R_DEFAULT
);
124 // Determine if a new state should be entered.
125 if (sc
.state
== SCE_R_DEFAULT
) {
126 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
127 sc
.SetState(SCE_R_NUMBER
);
128 } else if (IsAWordStart(sc
.ch
) ) {
129 sc
.SetState(SCE_R_IDENTIFIER
);
130 } else if (sc
.Match('#')) {
131 sc
.SetState(SCE_R_COMMENT
);
132 } else if (sc
.ch
== '\"') {
133 sc
.SetState(SCE_R_STRING
);
134 } else if (sc
.ch
== '%') {
135 sc
.SetState(SCE_R_INFIX
);
136 } else if (sc
.ch
== '\'') {
137 sc
.SetState(SCE_R_STRING2
);
138 } else if (IsAnOperator(sc
.ch
)) {
139 sc
.SetState(SCE_R_OPERATOR
);
146 // Store both the current line's fold level and the next lines in the
147 // level store to make it easy to pick up with each increment
148 // and to make it possible to fiddle the current level for "} else {".
149 static void FoldRDoc(unsigned int startPos
, int length
, int, WordList
*[],
151 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
152 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 0) != 0;
153 unsigned int endPos
= startPos
+ length
;
154 int visibleChars
= 0;
155 int lineCurrent
= styler
.GetLine(startPos
);
156 int levelCurrent
= SC_FOLDLEVELBASE
;
158 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
159 int levelMinCurrent
= levelCurrent
;
160 int levelNext
= levelCurrent
;
161 char chNext
= styler
[startPos
];
162 int styleNext
= styler
.StyleAt(startPos
);
163 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
165 chNext
= styler
.SafeGetCharAt(i
+ 1);
166 int style
= styleNext
;
167 styleNext
= styler
.StyleAt(i
+ 1);
168 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
169 if (style
== SCE_R_OPERATOR
) {
171 // Measure the minimum before a '{' to allow
172 // folding on "} else {"
173 if (levelMinCurrent
> levelNext
) {
174 levelMinCurrent
= levelNext
;
177 } else if (ch
== '}') {
182 int levelUse
= levelCurrent
;
184 levelUse
= levelMinCurrent
;
186 int lev
= levelUse
| levelNext
<< 16;
187 if (visibleChars
== 0 && foldCompact
)
188 lev
|= SC_FOLDLEVELWHITEFLAG
;
189 if (levelUse
< levelNext
)
190 lev
|= SC_FOLDLEVELHEADERFLAG
;
191 if (lev
!= styler
.LevelAt(lineCurrent
)) {
192 styler
.SetLevel(lineCurrent
, lev
);
195 levelCurrent
= levelNext
;
196 levelMinCurrent
= levelCurrent
;
199 if (!isspacechar(ch
))
205 static const char * const RWordLists
[] = {
207 "Base / Default package function",
208 "Other Package Functions",
216 LexerModule
lmR(SCLEX_R
, ColouriseRDoc
, "r", FoldRDoc
, RWordLists
);