123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- /**
- * @param {string} value
- * @returns {RegExp}
- * */
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function source(re) {
- if (!re) return null;
- if (typeof re === "string") return re;
- return re.source;
- }
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function lookahead(re) {
- return concat('(?=', re, ')');
- }
- /**
- * @param {...(RegExp | string) } args
- * @returns {string}
- */
- function concat(...args) {
- const joined = args.map((x) => source(x)).join("");
- return joined;
- }
- /*
- Language: R
- Description: R is a free software environment for statistical computing and graphics.
- Author: Joe Cheng <joe@rstudio.org>
- Contributors: Konrad Rudolph <konrad.rudolph@gmail.com>
- Website: https://www.r-project.org
- Category: common,scientific
- */
- /** @type LanguageFn */
- function r(hljs) {
- // Identifiers in R cannot start with `_`, but they can start with `.` if it
- // is not immediately followed by a digit.
- // R also supports quoted identifiers, which are near-arbitrary sequences
- // delimited by backticks (`…`), which may contain escape sequences. These are
- // handled in a separate mode. See `test/markup/r/names.txt` for examples.
- // FIXME: Support Unicode identifiers.
- const IDENT_RE = /(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/;
- const SIMPLE_IDENT = /[a-zA-Z][a-zA-Z_0-9]*/;
- return {
- name: 'R',
- // only in Haskell, not R
- illegal: /->/,
- keywords: {
- $pattern: IDENT_RE,
- keyword:
- 'function if in break next repeat else for while',
- literal:
- 'NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 ' +
- 'NA_character_|10 NA_complex_|10',
- built_in:
- // Builtin constants
- 'LETTERS letters month.abb month.name pi T F ' +
- // Primitive functions
- // These are all the functions in `base` that are implemented as a
- // `.Primitive`, minus those functions that are also keywords.
- 'abs acos acosh all any anyNA Arg as.call as.character ' +
- 'as.complex as.double as.environment as.integer as.logical ' +
- 'as.null.default as.numeric as.raw asin asinh atan atanh attr ' +
- 'attributes baseenv browser c call ceiling class Conj cos cosh ' +
- 'cospi cummax cummin cumprod cumsum digamma dim dimnames ' +
- 'emptyenv exp expression floor forceAndCall gamma gc.time ' +
- 'globalenv Im interactive invisible is.array is.atomic is.call ' +
- 'is.character is.complex is.double is.environment is.expression ' +
- 'is.finite is.function is.infinite is.integer is.language ' +
- 'is.list is.logical is.matrix is.na is.name is.nan is.null ' +
- 'is.numeric is.object is.pairlist is.raw is.recursive is.single ' +
- 'is.symbol lazyLoadDBfetch length lgamma list log max min ' +
- 'missing Mod names nargs nzchar oldClass on.exit pos.to.env ' +
- 'proc.time prod quote range Re rep retracemem return round ' +
- 'seq_along seq_len seq.int sign signif sin sinh sinpi sqrt ' +
- 'standardGeneric substitute sum switch tan tanh tanpi tracemem ' +
- 'trigamma trunc unclass untracemem UseMethod xtfrm',
- },
- compilerExtensions: [
- // allow beforeMatch to act as a "qualifier" for the match
- // the full match begin must be [beforeMatch][begin]
- (mode, parent) => {
- if (!mode.beforeMatch) return;
- // starts conflicts with endsParent which we need to make sure the child
- // rule is not matched multiple times
- if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
- const originalMode = Object.assign({}, mode);
- Object.keys(mode).forEach((key) => { delete mode[key]; });
- mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));
- mode.starts = {
- relevance: 0,
- contains: [
- Object.assign(originalMode, { endsParent: true })
- ]
- };
- mode.relevance = 0;
- delete originalMode.beforeMatch;
- }
- ],
- contains: [
- // Roxygen comments
- hljs.COMMENT(
- /#'/,
- /$/,
- {
- contains: [
- {
- // Handle `@examples` separately to cause all subsequent code
- // until the next `@`-tag on its own line to be kept as-is,
- // preventing highlighting. This code is example R code, so nested
- // doctags shouldn’t be treated as such. See
- // `test/markup/r/roxygen.txt` for an example.
- className: 'doctag',
- begin: '@examples',
- starts: {
- contains: [
- { begin: /\n/ },
- {
- begin: /#'\s*(?=@[a-zA-Z]+)/,
- endsParent: true,
- },
- {
- begin: /#'/,
- end: /$/,
- excludeBegin: true,
- }
- ]
- }
- },
- {
- // Handle `@param` to highlight the parameter name following
- // after.
- className: 'doctag',
- begin: '@param',
- end: /$/,
- contains: [
- {
- className: 'variable',
- variants: [
- { begin: IDENT_RE },
- { begin: /`(?:\\.|[^`\\])+`/ }
- ],
- endsParent: true
- }
- ]
- },
- {
- className: 'doctag',
- begin: /@[a-zA-Z]+/
- },
- {
- className: 'meta-keyword',
- begin: /\\[a-zA-Z]+/,
- }
- ]
- }
- ),
- hljs.HASH_COMMENT_MODE,
- {
- className: 'string',
- contains: [hljs.BACKSLASH_ESCAPE],
- variants: [
- hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\(/, end: /\)(-*)"/ }),
- hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\{/, end: /\}(-*)"/ }),
- hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\[/, end: /\](-*)"/ }),
- hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\(/, end: /\)(-*)'/ }),
- hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\{/, end: /\}(-*)'/ }),
- hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\[/, end: /\](-*)'/ }),
- {begin: '"', end: '"', relevance: 0},
- {begin: "'", end: "'", relevance: 0}
- ],
- },
- {
- className: 'number',
- relevance: 0,
- beforeMatch: /([^a-zA-Z0-9._])/, // not part of an identifier
- variants: [
- // TODO: replace with negative look-behind when available
- // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/ },
- // { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/ },
- // { begin: /(?<![a-zA-Z0-9._])(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/ }
- {
- // Special case: only hexadecimal binary powers can contain fractions.
- match: /0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/,
- },
- {
- match: /0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/
- },
- {
- match: /(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/,
- }
- ],
- },
- {
- // infix operator
- begin: '%',
- end: '%'
- },
- // relevance boost for assignment
- {
- begin: concat(SIMPLE_IDENT, "\\s+<-\\s+")
- },
- {
- // escaped identifier
- begin: '`',
- end: '`',
- contains: [
- { begin: /\\./ }
- ]
- }
- ]
- };
- }
- module.exports = r;
|