source: node_modules/highlight.js/lib/languages/r.js@ 65b6638

main
Last change on this file since 65b6638 was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/**
2 * @param {string} value
3 * @returns {RegExp}
4 * */
5
6/**
7 * @param {RegExp | string } re
8 * @returns {string}
9 */
10function source(re) {
11 if (!re) return null;
12 if (typeof re === "string") return re;
13
14 return re.source;
15}
16
17/**
18 * @param {RegExp | string } re
19 * @returns {string}
20 */
21function lookahead(re) {
22 return concat('(?=', re, ')');
23}
24
25/**
26 * @param {...(RegExp | string) } args
27 * @returns {string}
28 */
29function concat(...args) {
30 const joined = args.map((x) => source(x)).join("");
31 return joined;
32}
33
34/*
35Language: R
36Description: R is a free software environment for statistical computing and graphics.
37Author: Joe Cheng <joe@rstudio.org>
38Contributors: Konrad Rudolph <konrad.rudolph@gmail.com>
39Website: https://www.r-project.org
40Category: common,scientific
41*/
42
43/** @type LanguageFn */
44function r(hljs) {
45 // Identifiers in R cannot start with `_`, but they can start with `.` if it
46 // is not immediately followed by a digit.
47 // R also supports quoted identifiers, which are near-arbitrary sequences
48 // delimited by backticks (`…`), which may contain escape sequences. These are
49 // handled in a separate mode. See `test/markup/r/names.txt` for examples.
50 // FIXME: Support Unicode identifiers.
51 const IDENT_RE = /(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/;
52 const SIMPLE_IDENT = /[a-zA-Z][a-zA-Z_0-9]*/;
53
54 return {
55 name: 'R',
56
57 // only in Haskell, not R
58 illegal: /->/,
59 keywords: {
60 $pattern: IDENT_RE,
61 keyword:
62 'function if in break next repeat else for while',
63 literal:
64 'NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 ' +
65 'NA_character_|10 NA_complex_|10',
66 built_in:
67 // Builtin constants
68 'LETTERS letters month.abb month.name pi T F ' +
69 // Primitive functions
70 // These are all the functions in `base` that are implemented as a
71 // `.Primitive`, minus those functions that are also keywords.
72 'abs acos acosh all any anyNA Arg as.call as.character ' +
73 'as.complex as.double as.environment as.integer as.logical ' +
74 'as.null.default as.numeric as.raw asin asinh atan atanh attr ' +
75 'attributes baseenv browser c call ceiling class Conj cos cosh ' +
76 'cospi cummax cummin cumprod cumsum digamma dim dimnames ' +
77 'emptyenv exp expression floor forceAndCall gamma gc.time ' +
78 'globalenv Im interactive invisible is.array is.atomic is.call ' +
79 'is.character is.complex is.double is.environment is.expression ' +
80 'is.finite is.function is.infinite is.integer is.language ' +
81 'is.list is.logical is.matrix is.na is.name is.nan is.null ' +
82 'is.numeric is.object is.pairlist is.raw is.recursive is.single ' +
83 'is.symbol lazyLoadDBfetch length lgamma list log max min ' +
84 'missing Mod names nargs nzchar oldClass on.exit pos.to.env ' +
85 'proc.time prod quote range Re rep retracemem return round ' +
86 'seq_along seq_len seq.int sign signif sin sinh sinpi sqrt ' +
87 'standardGeneric substitute sum switch tan tanh tanpi tracemem ' +
88 'trigamma trunc unclass untracemem UseMethod xtfrm',
89 },
90 compilerExtensions: [
91 // allow beforeMatch to act as a "qualifier" for the match
92 // the full match begin must be [beforeMatch][begin]
93 (mode, parent) => {
94 if (!mode.beforeMatch) return;
95 // starts conflicts with endsParent which we need to make sure the child
96 // rule is not matched multiple times
97 if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
98
99 const originalMode = Object.assign({}, mode);
100 Object.keys(mode).forEach((key) => { delete mode[key]; });
101
102 mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));
103 mode.starts = {
104 relevance: 0,
105 contains: [
106 Object.assign(originalMode, { endsParent: true })
107 ]
108 };
109 mode.relevance = 0;
110
111 delete originalMode.beforeMatch;
112 }
113 ],
114 contains: [
115 // Roxygen comments
116 hljs.COMMENT(
117 /#'/,
118 /$/,
119 {
120 contains: [
121 {
122 // Handle `@examples` separately to cause all subsequent code
123 // until the next `@`-tag on its own line to be kept as-is,
124 // preventing highlighting. This code is example R code, so nested
125 // doctags shouldn’t be treated as such. See
126 // `test/markup/r/roxygen.txt` for an example.
127 className: 'doctag',
128 begin: '@examples',
129 starts: {
130 contains: [
131 { begin: /\n/ },
132 {
133 begin: /#'\s*(?=@[a-zA-Z]+)/,
134 endsParent: true,
135 },
136 {
137 begin: /#'/,
138 end: /$/,
139 excludeBegin: true,
140 }
141 ]
142 }
143 },
144 {
145 // Handle `@param` to highlight the parameter name following
146 // after.
147 className: 'doctag',
148 begin: '@param',
149 end: /$/,
150 contains: [
151 {
152 className: 'variable',
153 variants: [
154 { begin: IDENT_RE },
155 { begin: /`(?:\\.|[^`\\])+`/ }
156 ],
157 endsParent: true
158 }
159 ]
160 },
161 {
162 className: 'doctag',
163 begin: /@[a-zA-Z]+/
164 },
165 {
166 className: 'meta-keyword',
167 begin: /\\[a-zA-Z]+/,
168 }
169 ]
170 }
171 ),
172
173 hljs.HASH_COMMENT_MODE,
174
175 {
176 className: 'string',
177 contains: [hljs.BACKSLASH_ESCAPE],
178 variants: [
179 hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\(/, end: /\)(-*)"/ }),
180 hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\{/, end: /\}(-*)"/ }),
181 hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\[/, end: /\](-*)"/ }),
182 hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\(/, end: /\)(-*)'/ }),
183 hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\{/, end: /\}(-*)'/ }),
184 hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\[/, end: /\](-*)'/ }),
185 {begin: '"', end: '"', relevance: 0},
186 {begin: "'", end: "'", relevance: 0}
187 ],
188 },
189 {
190 className: 'number',
191 relevance: 0,
192 beforeMatch: /([^a-zA-Z0-9._])/, // not part of an identifier
193 variants: [
194 // TODO: replace with negative look-behind when available
195 // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/ },
196 // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/ },
197 // { begin: /(?<![a-zA-Z0-9._])(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/ }
198 {
199 // Special case: only hexadecimal binary powers can contain fractions.
200 match: /0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/,
201 },
202 {
203 match: /0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/
204 },
205 {
206 match: /(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/,
207 }
208 ],
209 },
210 {
211 // infix operator
212 begin: '%',
213 end: '%'
214 },
215 // relevance boost for assignment
216 {
217 begin: concat(SIMPLE_IDENT, "\\s+<-\\s+")
218 },
219 {
220 // escaped identifier
221 begin: '`',
222 end: '`',
223 contains: [
224 { begin: /\\./ }
225 ]
226 }
227 ]
228 };
229}
230
231module.exports = r;
Note: See TracBrowser for help on using the repository browser.