@@ -18,13 +18,27 @@ export default function(hljs) {
18
18
// handled in a separate mode. See `test/markup/r/names.txt` for examples.
19
19
// FIXME: Support Unicode identifiers.
20
20
const IDENT_RE = / (?: (?: [ a - z A - Z ] | \. [ . _ a - z A - Z ] ) [ . _ a - z A - Z 0 - 9 ] * ) | \. (? ! \d ) / ;
21
- const SIMPLE_IDENT = / [ a - z A - Z ] [ a - z A - Z _ 0 - 9 ] * / ;
21
+ const NUMBER_TYPES_RE = regex . either (
22
+ // Special case: only hexadecimal binary powers can contain fractions
23
+ / 0 [ x X ] [ 0 - 9 a - f A - F ] + \. [ 0 - 9 a - f A - F ] * [ p P ] [ + - ] ? \d + i ? / ,
24
+ // Hexadecimal numbers without fraction and optional binary power
25
+ / 0 [ x X ] [ 0 - 9 a - f A - F ] + (?: [ p P ] [ + - ] ? \d + ) ? [ L i ] ? / ,
26
+ // Decimal numbers
27
+ / (?: \d + (?: \. \d * ) ? | \. \d + ) (?: [ e E ] [ + - ] ? \d + ) ? [ L i ] ? /
28
+ ) ;
29
+ const OPERATORS_RE = / [ = ! < > : ] = | \| \| | & & | : : : ? | < - | < < - | - > > | - > | \| > | [ - + * \/ ? ! $ & | : < = > @ ^ ~ ] | \* \* / ;
30
+ const PUNCTUATION_RE = regex . either (
31
+ / [ ( ) ] / ,
32
+ / [ { } ] / ,
33
+ / \[ \[ / ,
34
+ / [ [ \] ] / ,
35
+ / \\ / ,
36
+ / , /
37
+ ) ;
22
38
23
39
return {
24
40
name : 'R' ,
25
41
26
- // only in Haskell, not R
27
- illegal : / - > / ,
28
42
keywords : {
29
43
$pattern : IDENT_RE ,
30
44
keyword :
@@ -56,6 +70,7 @@ export default function(hljs) {
56
70
'standardGeneric substitute sum switch tan tanh tanpi tracemem ' +
57
71
'trigamma trunc unclass untracemem UseMethod xtfrm' ,
58
72
} ,
73
+
59
74
contains : [
60
75
// Roxygen comments
61
76
hljs . COMMENT (
@@ -69,7 +84,7 @@ export default function(hljs) {
69
84
// preventing highlighting. This code is example R code, so nested
70
85
// doctags shouldn’t be treated as such. See
71
86
// `test/markup/r/roxygen.txt` for an example.
72
- className : 'doctag' ,
87
+ scope : 'doctag' ,
73
88
begin : '@examples' ,
74
89
starts : {
75
90
contains : [
@@ -89,12 +104,12 @@ export default function(hljs) {
89
104
{
90
105
// Handle `@param` to highlight the parameter name following
91
106
// after.
92
- className : 'doctag' ,
107
+ scope : 'doctag' ,
93
108
begin : '@param' ,
94
109
end : / $ / ,
95
110
contains : [
96
111
{
97
- className : 'variable' ,
112
+ scope : 'variable' ,
98
113
variants : [
99
114
{ begin : IDENT_RE } ,
100
115
{ begin : / ` (?: \\ .| [ ^ ` \\ ] ) + ` / }
@@ -104,11 +119,11 @@ export default function(hljs) {
104
119
]
105
120
} ,
106
121
{
107
- className : 'doctag' ,
122
+ scope : 'doctag' ,
108
123
begin : / @ [ a - z A - Z ] + /
109
124
} ,
110
125
{
111
- className : 'keyword' ,
126
+ scope : 'keyword' ,
112
127
begin : / \\ [ a - z A - Z ] + / ,
113
128
}
114
129
]
@@ -118,7 +133,7 @@ export default function(hljs) {
118
133
hljs . HASH_COMMENT_MODE ,
119
134
120
135
{
121
- className : 'string' ,
136
+ scope : 'string' ,
122
137
contains : [ hljs . BACKSLASH_ESCAPE ] ,
123
138
variants : [
124
139
hljs . END_SAME_AS_BEGIN ( { begin : / [ r R ] " ( - * ) \( / , end : / \) ( - * ) " / } ) ,
@@ -131,48 +146,88 @@ export default function(hljs) {
131
146
{ begin : "'" , end : "'" , relevance : 0 }
132
147
] ,
133
148
} ,
149
+
150
+ // Matching numbers immediately following punctuation and operators is
151
+ // tricky since we need to look at the character ahead of a number to
152
+ // ensure the number is not part of an identifier, and we cannot use
153
+ // negative look-behind assertions. So instead we explicitly handle all
154
+ // possible combinations of (operator|punctuation), number.
155
+ // TODO: replace with negative look-behind when available
156
+ // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/ },
157
+ // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/ },
158
+ // { begin: /(?<![a-zA-Z0-9._])(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/ }
134
159
{
135
160
relevance : 0 ,
136
- className : {
137
- 2 : "number"
138
- } ,
139
161
variants : [
140
- // TODO: replace with negative look-behind when available
141
- // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/ },
142
- // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/ },
143
- // { begin: /(?<![a-zA-Z0-9._])(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/ }
144
162
{
145
- // Special case: only hexadecimal binary powers can contain fractions.
163
+ scope : {
164
+ 1 : 'operator' ,
165
+ 2 : 'number'
166
+ } ,
167
+ match : [
168
+ OPERATORS_RE ,
169
+ NUMBER_TYPES_RE
170
+ ]
171
+ } ,
172
+ {
173
+ scope : {
174
+ 1 : 'operator' ,
175
+ 2 : 'number'
176
+ } ,
146
177
match : [
147
- / [ ^ a - z A - Z 0 - 9 . _ ] / , // not part of an identifier
148
- / 0 [ x X ] [ 0 - 9 a - f A - F ] + \. [ 0 - 9 a - f A - F ] * [ p P ] [ + - ] ? \d + i ? /
178
+ / % [ ^ % ] * % / ,
179
+ NUMBER_TYPES_RE
149
180
]
150
181
} ,
151
182
{
183
+ scope : {
184
+ 1 : 'punctuation' ,
185
+ 2 : 'number'
186
+ } ,
152
187
match : [
153
- / [ ^ a - z A - Z 0 - 9 . _ ] / , // not part of an identifier
154
- / 0 [ x X ] [ 0 - 9 a - f A - F ] + (?: [ p P ] [ + - ] ? \d + ) ? [ L i ] ? /
188
+ PUNCTUATION_RE ,
189
+ NUMBER_TYPES_RE
155
190
]
156
191
} ,
157
192
{
193
+ scope : { 2 : 'number' } ,
158
194
match : [
159
- / [ ^ a - z A - Z 0 - 9 . _ ] / , // not part of an identifier
160
- / (?: \d + (?: \. \d * ) ? | \. \d + ) (?: [ e E ] [ + - ] ? \d + ) ? [ L i ] ? /
195
+ / [ ^ a - z A - Z 0 - 9 . _ ] | ^ / , // not part of an identifier, or start of document
196
+ NUMBER_TYPES_RE
161
197
]
162
198
}
163
199
]
164
200
} ,
201
+
202
+ // Operators/punctuation when they're not directly followed by numbers
203
+ {
204
+ // Relevance boost for the most common assignment form.
205
+ scope : { 3 : 'operator' } ,
206
+ match : [
207
+ IDENT_RE ,
208
+ / \s + / ,
209
+ / < - / ,
210
+ / \s + /
211
+ ]
212
+ } ,
213
+
165
214
{
166
- // infix operator
167
- begin : '%' ,
168
- end : '%'
215
+ scope : 'operator' ,
216
+ relevance : 0 ,
217
+ variants : [
218
+ { match : OPERATORS_RE } ,
219
+ { match : / % [ ^ % ] * % / }
220
+ ]
169
221
} ,
170
- // relevance boost for assignment
222
+
171
223
{
172
- begin : regex . concat ( SIMPLE_IDENT , "\\s+<-\\s+" )
224
+ scope : 'punctuation' ,
225
+ relevance : 0 ,
226
+ match : PUNCTUATION_RE
173
227
} ,
228
+
174
229
{
175
- // escaped identifier
230
+ // Escaped identifier
176
231
begin : '`' ,
177
232
end : '`' ,
178
233
contains : [
0 commit comments