knowledgebase_law/node_modules/refractor/lang/factor.js
2025-04-11 11:47:09 -04:00

926 lines
22 KiB
JavaScript

'use strict'
module.exports = factor
factor.displayName = 'factor'
factor.aliases = []
function factor(Prism) {
;(function (Prism) {
var comment_inside = {
function:
/\b(?:BUGS?|FIX(?:MES?)?|NOTES?|TODOS?|XX+|HACKS?|WARN(?:ING)?|\?{2,}|!{2,})\b/
}
var string_inside = {
number: /\\[^\s']|%\w/
}
var factor = {
comment: [
{
// ! single-line exclamation point comments with whitespace after/around the !
pattern: /(^|\s)(?:! .*|!$)/,
lookbehind: true,
inside: comment_inside
},
/* from basis/multiline: */
{
// /* comment */, /* comment*/
pattern: /(^|\s)\/\*\s[\s\S]*?\*\/(?=\s|$)/,
lookbehind: true,
greedy: true,
inside: comment_inside
},
{
// ![[ comment ]] , ![===[ comment]===]
pattern: /(^|\s)!\[(={0,6})\[\s[\s\S]*?\]\2\](?=\s|$)/,
lookbehind: true,
greedy: true,
inside: comment_inside
}
],
number: [
{
// basic base 10 integers 9, -9
pattern: /(^|\s)[+-]?\d+(?=\s|$)/,
lookbehind: true
},
{
// base prefix integers 0b010 0o70 0xad 0d10 0XAD -0xa9
pattern: /(^|\s)[+-]?0(?:b[01]+|o[0-7]+|d\d+|x[\dA-F]+)(?=\s|$)/i,
lookbehind: true
},
{
// fractional ratios 1/5 -1/5 and the literal float approximations 1/5. -1/5.
pattern: /(^|\s)[+-]?\d+\/\d+\.?(?=\s|$)/,
lookbehind: true
},
{
// positive mixed numbers 23+1/5 +23+1/5
pattern: /(^|\s)\+?\d+\+\d+\/\d+(?=\s|$)/,
lookbehind: true
},
{
// negative mixed numbers -23-1/5
pattern: /(^|\s)-\d+-\d+\/\d+(?=\s|$)/,
lookbehind: true
},
{
// basic decimal floats -0.01 0. .0 .1 -.1 -1. -12.13 +12.13
// and scientific notation with base 10 exponents 3e4 3e-4 .3e-4
pattern:
/(^|\s)[+-]?(?:\d*\.\d+|\d+\.\d*|\d+)(?:e[+-]?\d+)?(?=\s|$)/i,
lookbehind: true
},
{
// NAN literal syntax NAN: 80000deadbeef, NAN: a
pattern: /(^|\s)NAN:\s+[\da-fA-F]+(?=\s|$)/,
lookbehind: true
},
{
/*
base prefix floats 0x1.0p3 (8.0) 0b1.010p2 (5.0) 0x1.p1 0b1.11111111p11111...
"The normalized hex form ±0x1.MMMMMMMMMMMMM[pP]±EEEE allows any floating-point number to be specified precisely.
The values of MMMMMMMMMMMMM and EEEE map directly to the mantissa and exponent fields of the binary IEEE 754 representation."
<https://docs.factorcode.org/content/article-syntax-floats.html>
*/
pattern:
/(^|\s)[+-]?0(?:b1\.[01]*|o1\.[0-7]*|d1\.\d*|x1\.[\dA-F]*)p\d+(?=\s|$)/i,
lookbehind: true
}
],
// R/ regexp?\/\\/
regexp: {
pattern:
/(^|\s)R\/\s(?:\\\S|[^\\/])*\/(?:[idmsr]*|[idmsr]+-[idmsr]+)(?=\s|$)/,
lookbehind: true,
alias: 'number',
inside: {
variable: /\\\S/,
keyword: /[+?*\[\]^$(){}.|]/,
operator: {
pattern: /(\/)[idmsr]+(?:-[idmsr]+)?/,
lookbehind: true
}
}
},
boolean: {
pattern: /(^|\s)[tf](?=\s|$)/,
lookbehind: true
},
// SBUF" asd", URL" ://...", P" /etc/"
'custom-string': {
pattern: /(^|\s)[A-Z0-9\-]+"\s(?:\\\S|[^"\\])*"/,
lookbehind: true,
greedy: true,
alias: 'string',
inside: {
number: /\\\S|%\w|\//
}
},
'multiline-string': [
{
// STRING: name \n content \n ; -> CONSTANT: name "content" (symbol)
pattern: /(^|\s)STRING:\s+\S+(?:\n|\r\n).*(?:\n|\r\n)\s*;(?=\s|$)/,
lookbehind: true,
greedy: true,
alias: 'string',
inside: {
number: string_inside.number,
// trailing semicolon on its own line
'semicolon-or-setlocal': {
pattern: /([\r\n][ \t]*);(?=\s|$)/,
lookbehind: true,
alias: 'function'
}
}
},
{
// HEREDOC: marker \n content \n marker ; -> "content" (immediate)
pattern: /(^|\s)HEREDOC:\s+\S+(?:\n|\r\n).*(?:\n|\r\n)\s*\S+(?=\s|$)/,
lookbehind: true,
greedy: true,
alias: 'string',
inside: string_inside
},
{
// [[ string ]], [==[ string]==]
pattern: /(^|\s)\[(={0,6})\[\s[\s\S]*?\]\2\](?=\s|$)/,
lookbehind: true,
greedy: true,
alias: 'string',
inside: string_inside
}
],
'special-using': {
pattern: /(^|\s)USING:(?:\s\S+)*(?=\s+;(?:\s|$))/,
lookbehind: true,
alias: 'function',
inside: {
// this is essentially a regex for vocab names, which i don't want to specify
// but the USING: gets picked up as a vocab name
string: {
pattern: /(\s)[^:\s]+/,
lookbehind: true
}
}
},
/* this description of stack effect literal syntax is not complete and not as specific as theoretically possible
trying to do better is more work and regex-computation-time than it's worth though.
- we'd like to have the "delimiter" parts of the stack effect [ (, --, and ) ] be a different (less-important or comment-like) colour to the stack effect contents
- we'd like if nested stack effects were treated as such rather than just appearing flat (with `inside`)
- we'd like if the following variable name conventions were recognised specifically:
special row variables = ..a b..
type and stack effect annotations end with a colon = ( quot: ( a: ( -- ) -- b ) -- x ), ( x: number -- )
word throws unconditional error = *
any other word-like variable name = a ? q' etc
https://docs.factorcode.org/content/article-effects.html
these are pretty complicated to highlight properly without a real parser, and therefore out of scope
the old pattern, which may be later useful, was: (^|\s)(?:call|execute|eval)?\((?:\s+[^"\r\n\t ]\S*)*?\s+--(?:\s+[^"\n\t ]\S*)*?\s+\)(?=\s|$)
*/
// current solution is not great
'stack-effect-delimiter': [
{
// opening parenthesis
pattern: /(^|\s)(?:call|eval|execute)?\((?=\s)/,
lookbehind: true,
alias: 'operator'
},
{
// middle --
pattern: /(\s)--(?=\s)/,
lookbehind: true,
alias: 'operator'
},
{
// closing parenthesis
pattern: /(\s)\)(?=\s|$)/,
lookbehind: true,
alias: 'operator'
}
],
combinators: {
pattern: null,
lookbehind: true,
alias: 'keyword'
},
'kernel-builtin': {
pattern: null,
lookbehind: true,
alias: 'variable'
},
'sequences-builtin': {
pattern: null,
lookbehind: true,
alias: 'variable'
},
'math-builtin': {
pattern: null,
lookbehind: true,
alias: 'variable'
},
'constructor-word': {
// <array> but not <=>
pattern: /(^|\s)<(?!=+>|-+>)\S+>(?=\s|$)/,
lookbehind: true,
alias: 'keyword'
},
'other-builtin-syntax': {
pattern: null,
lookbehind: true,
alias: 'operator'
},
/*
full list of supported word naming conventions: (the convention appears outside of the [brackets])
set-[x]
change-[x]
with-[x]
new-[x]
>[string]
[base]>
[string]>[number]
+[symbol]+
[boolean-word]?
?[of]
[slot-reader]>>
>>[slot-setter]
[slot-writer]<<
([implementation-detail])
[mutater]!
[variant]*
[prettyprint].
$[help-markup]
<constructors>, SYNTAX:, etc are supported by their own patterns.
`with` and `new` from `kernel` are their own builtins.
see <https://docs.factorcode.org/content/article-conventions.html>
*/
'conventionally-named-word': {
pattern:
/(^|\s)(?!")(?:(?:change|new|set|with)-\S+|\$\S+|>[^>\s]+|[^:>\s]+>|[^>\s]+>[^>\s]+|\+[^+\s]+\+|[^?\s]+\?|\?[^?\s]+|[^>\s]+>>|>>[^>\s]+|[^<\s]+<<|\([^()\s]+\)|[^!\s]+!|[^*\s]\S*\*|[^.\s]\S*\.)(?=\s|$)/,
lookbehind: true,
alias: 'keyword'
},
'colon-syntax': {
pattern: /(^|\s)(?:[A-Z0-9\-]+#?)?:{1,2}\s+(?:;\S+|(?!;)\S+)(?=\s|$)/,
lookbehind: true,
greedy: true,
alias: 'function'
},
'semicolon-or-setlocal': {
pattern: /(\s)(?:;|:>)(?=\s|$)/,
lookbehind: true,
alias: 'function'
},
// do not highlight leading } or trailing X{ at the begin/end of the file as it's invalid syntax
'curly-brace-literal-delimiter': [
{
// opening
pattern: /(^|\s)[a-z]*\{(?=\s)/i,
lookbehind: true,
alias: 'operator'
},
{
// closing
pattern: /(\s)\}(?=\s|$)/,
lookbehind: true,
alias: 'operator'
}
],
// do not highlight leading ] or trailing [ at the begin/end of the file as it's invalid syntax
'quotation-delimiter': [
{
// opening
pattern: /(^|\s)\[(?=\s)/,
lookbehind: true,
alias: 'operator'
},
{
// closing
pattern: /(\s)\](?=\s|$)/,
lookbehind: true,
alias: 'operator'
}
],
'normal-word': {
pattern: /(^|\s)[^"\s]\S*(?=\s|$)/,
lookbehind: true
},
/*
basic first-class string "a"
with escaped double-quote "a\""
escaped backslash "\\"
and general escapes since Factor has so many "\N"
syntax that works in the reference implementation that isn't fully
supported because it's an implementation detail:
"string 1""string 2" -> 2 strings (works anyway)
"string"5 -> string, 5
"string"[ ] -> string, quotation
{ "a"} -> array<string>
the rest of those examples all properly recognise the string, but not
the other object (number, quotation, etc)
this is fine for a regex-only implementation.
*/
string: {
pattern: /"(?:\\\S|[^"\\])*"/,
greedy: true,
inside: string_inside
}
}
var escape = function (str) {
return (str + '').replace(/([.?*+\^$\[\]\\(){}|\-])/g, '\\$1')
}
var arrToWordsRegExp = function (arr) {
return new RegExp('(^|\\s)(?:' + arr.map(escape).join('|') + ')(?=\\s|$)')
}
var builtins = {
'kernel-builtin': [
'or',
'2nipd',
'4drop',
'tuck',
'wrapper',
'nip',
'wrapper?',
'callstack>array',
'die',
'dupd',
'callstack',
'callstack?',
'3dup',
'hashcode',
'pick',
'4nip',
'build',
'>boolean',
'nipd',
'clone',
'5nip',
'eq?',
'?',
'=',
'swapd',
'2over',
'clear',
'2dup',
'get-retainstack',
'not',
'tuple?',
'dup',
'3nipd',
'call',
'-rotd',
'object',
'drop',
'assert=',
'assert?',
'-rot',
'execute',
'boa',
'get-callstack',
'curried?',
'3drop',
'pickd',
'overd',
'over',
'roll',
'3nip',
'swap',
'and',
'2nip',
'rotd',
'throw',
'(clone)',
'hashcode*',
'spin',
'reach',
'4dup',
'equal?',
'get-datastack',
'assert',
'2drop',
'<wrapper>',
'boolean?',
'identity-hashcode',
'identity-tuple?',
'null',
'composed?',
'new',
'5drop',
'rot',
'-roll',
'xor',
'identity-tuple',
'boolean'
],
'other-builtin-syntax': [
// syntax
'=======',
'recursive',
'flushable',
'>>',
'<<<<<<',
'M\\',
'B',
'PRIVATE>',
'\\',
'======',
'final',
'inline',
'delimiter',
'deprecated',
'<PRIVATE',
'>>>>>>',
'<<<<<<<',
'parse-complex',
'malformed-complex',
'read-only',
'>>>>>>>',
'call-next-method',
'<<',
'foldable', // literals
'$',
'$[',
'${'
],
'sequences-builtin': [
'member-eq?',
'mismatch',
'append',
'assert-sequence=',
'longer',
'repetition',
'clone-like',
'3sequence',
'assert-sequence?',
'last-index-from',
'reversed',
'index-from',
'cut*',
'pad-tail',
'join-as',
'remove-eq!',
'concat-as',
'but-last',
'snip',
'nths',
'nth',
'sequence',
'longest',
'slice?',
'<slice>',
'remove-nth',
'tail-slice',
'empty?',
'tail*',
'member?',
'virtual-sequence?',
'set-length',
'drop-prefix',
'iota',
'unclip',
'bounds-error?',
'unclip-last-slice',
'non-negative-integer-expected',
'non-negative-integer-expected?',
'midpoint@',
'longer?',
'?set-nth',
'?first',
'rest-slice',
'prepend-as',
'prepend',
'fourth',
'sift',
'subseq-start',
'new-sequence',
'?last',
'like',
'first4',
'1sequence',
'reverse',
'slice',
'virtual@',
'repetition?',
'set-last',
'index',
'4sequence',
'max-length',
'set-second',
'immutable-sequence',
'first2',
'first3',
'supremum',
'unclip-slice',
'suffix!',
'insert-nth',
'tail',
'3append',
'short',
'suffix',
'concat',
'flip',
'immutable?',
'reverse!',
'2sequence',
'sum',
'delete-all',
'indices',
'snip-slice',
'<iota>',
'check-slice',
'sequence?',
'head',
'append-as',
'halves',
'sequence=',
'collapse-slice',
'?second',
'slice-error?',
'product',
'bounds-check?',
'bounds-check',
'immutable',
'virtual-exemplar',
'harvest',
'remove',
'pad-head',
'last',
'set-fourth',
'cartesian-product',
'remove-eq',
'shorten',
'shorter',
'reversed?',
'shorter?',
'shortest',
'head-slice',
'pop*',
'tail-slice*',
'but-last-slice',
'iota?',
'append!',
'cut-slice',
'new-resizable',
'head-slice*',
'sequence-hashcode',
'pop',
'set-nth',
'?nth',
'second',
'join',
'immutable-sequence?',
'<reversed>',
'3append-as',
'virtual-sequence',
'subseq?',
'remove-nth!',
'length',
'last-index',
'lengthen',
'assert-sequence',
'copy',
'move',
'third',
'first',
'tail?',
'set-first',
'prefix',
'bounds-error',
'<repetition>',
'exchange',
'surround',
'cut',
'min-length',
'set-third',
'push-all',
'head?',
'subseq-start-from',
'delete-slice',
'rest',
'sum-lengths',
'head*',
'infimum',
'remove!',
'glue',
'slice-error',
'subseq',
'push',
'replace-slice',
'subseq-as',
'unclip-last'
],
'math-builtin': [
'number=',
'next-power-of-2',
'?1+',
'fp-special?',
'imaginary-part',
'float>bits',
'number?',
'fp-infinity?',
'bignum?',
'fp-snan?',
'denominator',
'gcd',
'*',
'+',
'fp-bitwise=',
'-',
'u>=',
'/',
'>=',
'bitand',
'power-of-2?',
'log2-expects-positive',
'neg?',
'<',
'log2',
'>',
'integer?',
'number',
'bits>double',
'2/',
'zero?',
'bits>float',
'float?',
'shift',
'ratio?',
'rect>',
'even?',
'ratio',
'fp-sign',
'bitnot',
'>fixnum',
'complex?',
'/i',
'integer>fixnum',
'/f',
'sgn',
'>bignum',
'next-float',
'u<',
'u>',
'mod',
'recip',
'rational',
'>float',
'2^',
'integer',
'fixnum?',
'neg',
'fixnum',
'sq',
'bignum',
'>rect',
'bit?',
'fp-qnan?',
'simple-gcd',
'complex',
'<fp-nan>',
'real',
'>fraction',
'double>bits',
'bitor',
'rem',
'fp-nan-payload',
'real-part',
'log2-expects-positive?',
'prev-float',
'align',
'unordered?',
'float',
'fp-nan?',
'abs',
'bitxor',
'integer>fixnum-strict',
'u<=',
'odd?',
'<=',
'/mod',
'>integer',
'real?',
'rational?',
'numerator'
] // that's all for now
}
Object.keys(builtins).forEach(function (k) {
factor[k].pattern = arrToWordsRegExp(builtins[k])
})
var combinators = [
// kernel
'2bi',
'while',
'2tri',
'bi*',
'4dip',
'both?',
'same?',
'tri@',
'curry',
'prepose',
'3bi',
'?if',
'tri*',
'2keep',
'3keep',
'curried',
'2keepd',
'when',
'2bi*',
'2tri*',
'4keep',
'bi@',
'keepdd',
'do',
'unless*',
'tri-curry',
'if*',
'loop',
'bi-curry*',
'when*',
'2bi@',
'2tri@',
'with',
'2with',
'either?',
'bi',
'until',
'3dip',
'3curry',
'tri-curry*',
'tri-curry@',
'bi-curry',
'keepd',
'compose',
'2dip',
'if',
'3tri',
'unless',
'tuple',
'keep',
'2curry',
'tri',
'most',
'while*',
'dip',
'composed',
'bi-curry@', // sequences
'find-last-from',
'trim-head-slice',
'map-as',
'each-from',
'none?',
'trim-tail',
'partition',
'if-empty',
'accumulate*',
'reject!',
'find-from',
'accumulate-as',
'collector-for-as',
'reject',
'map',
'map-sum',
'accumulate!',
'2each-from',
'follow',
'supremum-by',
'map!',
'unless-empty',
'collector',
'padding',
'reduce-index',
'replicate-as',
'infimum-by',
'trim-tail-slice',
'count',
'find-index',
'filter',
'accumulate*!',
'reject-as',
'map-integers',
'map-find',
'reduce',
'selector',
'interleave',
'2map',
'filter-as',
'binary-reduce',
'map-index-as',
'find',
'produce',
'filter!',
'replicate',
'cartesian-map',
'cartesian-each',
'find-index-from',
'map-find-last',
'3map-as',
'3map',
'find-last',
'selector-as',
'2map-as',
'2map-reduce',
'accumulate',
'each',
'each-index',
'accumulate*-as',
'when-empty',
'all?',
'collector-as',
'push-either',
'new-like',
'collector-for',
'2selector',
'push-if',
'2all?',
'map-reduce',
'3each',
'any?',
'trim-slice',
'2reduce',
'change-nth',
'produce-as',
'2each',
'trim',
'trim-head',
'cartesian-find',
'map-index', // math
'if-zero',
'each-integer',
'unless-zero',
'(find-integer)',
'when-zero',
'find-last-integer',
'(all-integers?)',
'times',
'(each-integer)',
'find-integer',
'all-integers?', // math.combinators
'unless-negative',
'if-positive',
'when-positive',
'when-negative',
'unless-positive',
'if-negative', // combinators
'case',
'2cleave',
'cond>quot',
'case>quot',
'3cleave',
'wrong-values',
'to-fixed-point',
'alist>quot',
'cond',
'cleave',
'call-effect',
'recursive-hashcode',
'spread',
'deep-spread>quot', // combinators.short-circuit
'2||',
'0||',
'n||',
'0&&',
'2&&',
'3||',
'1||',
'1&&',
'n&&',
'3&&', // combinators.smart
'smart-unless*',
'keep-inputs',
'reduce-outputs',
'smart-when*',
'cleave>array',
'smart-with',
'smart-apply',
'smart-if',
'inputs/outputs',
'output>sequence-n',
'map-outputs',
'map-reduce-outputs',
'dropping',
'output>array',
'smart-map-reduce',
'smart-2map-reduce',
'output>array-n',
'nullary',
'input<sequence',
'append-outputs',
'drop-inputs',
'inputs',
'smart-2reduce',
'drop-outputs',
'smart-reduce',
'preserving',
'smart-when',
'outputs',
'append-outputs-as',
'smart-unless',
'smart-if*',
'sum-outputs',
'input<sequence-unsafe',
'output>sequence' // tafn
]
factor.combinators.pattern = arrToWordsRegExp(combinators)
Prism.languages.factor = factor
})(Prism)
}