-
-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathscheme.js
143 lines (141 loc) · 6.94 KB
/
scheme.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// @ts-nocheck
/**
* @import {Refractor} from '../lib/core.js'
*/
scheme.displayName = 'scheme'
scheme.aliases = []
/** @param {Refractor} Prism */
export default function scheme(Prism) {
;(function (Prism) {
Prism.languages.scheme = {
// this supports "normal" single-line comments:
// ; comment
// and (potentially nested) multiline comments:
// #| comment #| nested |# still comment |#
// (only 1 level of nesting is supported)
comment:
/;.*|#;\s*(?:\((?:[^()]|\([^()]*\))*\)|\[(?:[^\[\]]|\[[^\[\]]*\])*\])|#\|(?:[^#|]|#(?!\|)|\|(?!#)|#\|(?:[^#|]|#(?!\|)|\|(?!#))*\|#)*\|#/,
string: {
pattern: /"(?:[^"\\]|\\.)*"/,
greedy: true
},
symbol: {
pattern: /'[^()\[\]#'\s]+/,
greedy: true
},
char: {
pattern:
/#\\(?:[ux][a-fA-F\d]+\b|[-a-zA-Z]+\b|[\uD800-\uDBFF][\uDC00-\uDFFF]|\S)/,
greedy: true
},
'lambda-parameter': [
// https://www.cs.cmu.edu/Groups/AI/html/r4rs/r4rs_6.html#SEC30
{
pattern:
/((?:^|[^'`#])[(\[]lambda\s+)(?:[^|()\[\]'\s]+|\|(?:[^\\|]|\\.)*\|)/,
lookbehind: true
},
{
pattern: /((?:^|[^'`#])[(\[]lambda\s+[(\[])[^()\[\]']+/,
lookbehind: true
}
],
keyword: {
pattern:
/((?:^|[^'`#])[(\[])(?:begin|case(?:-lambda)?|cond(?:-expand)?|define(?:-library|-macro|-record-type|-syntax|-values)?|defmacro|delay(?:-force)?|do|else|except|export|guard|if|import|include(?:-ci|-library-declarations)?|lambda|let(?:rec)?(?:-syntax|-values|\*)?|let\*-values|only|parameterize|prefix|(?:quasi-?)?quote|rename|set!|syntax-(?:case|rules)|unless|unquote(?:-splicing)?|when)(?=[()\[\]\s]|$)/,
lookbehind: true
},
builtin: {
// all functions of the base library of R7RS plus some of built-ins of R5Rs
pattern:
/((?:^|[^'`#])[(\[])(?:abs|and|append|apply|assoc|ass[qv]|binary-port\?|boolean=?\?|bytevector(?:-append|-copy|-copy!|-length|-u8-ref|-u8-set!|\?)?|caar|cadr|call-with-(?:current-continuation|port|values)|call\/cc|car|cdar|cddr|cdr|ceiling|char(?:->integer|-ready\?|\?|<\?|<=\?|=\?|>\?|>=\?)|close-(?:input-port|output-port|port)|complex\?|cons|current-(?:error|input|output)-port|denominator|dynamic-wind|eof-object\??|eq\?|equal\?|eqv\?|error|error-object(?:-irritants|-message|\?)|eval|even\?|exact(?:-integer-sqrt|-integer\?|\?)?|expt|features|file-error\?|floor(?:-quotient|-remainder|\/)?|flush-output-port|for-each|gcd|get-output-(?:bytevector|string)|inexact\??|input-port(?:-open\?|\?)|integer(?:->char|\?)|lcm|length|list(?:->string|->vector|-copy|-ref|-set!|-tail|\?)?|make-(?:bytevector|list|parameter|string|vector)|map|max|member|memq|memv|min|modulo|negative\?|newline|not|null\?|number(?:->string|\?)|numerator|odd\?|open-(?:input|output)-(?:bytevector|string)|or|output-port(?:-open\?|\?)|pair\?|peek-char|peek-u8|port\?|positive\?|procedure\?|quotient|raise|raise-continuable|rational\?|rationalize|read-(?:bytevector|bytevector!|char|error\?|line|string|u8)|real\?|remainder|reverse|round|set-c[ad]r!|square|string(?:->list|->number|->symbol|->utf8|->vector|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?|<\?|<=\?|=\?|>\?|>=\?)?|substring|symbol(?:->string|\?|=\?)|syntax-error|textual-port\?|truncate(?:-quotient|-remainder|\/)?|u8-ready\?|utf8->string|values|vector(?:->list|->string|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?)?|with-exception-handler|write-(?:bytevector|char|string|u8)|zero\?)(?=[()\[\]\s]|$)/,
lookbehind: true
},
operator: {
pattern: /((?:^|[^'`#])[(\[])(?:[-+*%/]|[<>]=?|=>?)(?=[()\[\]\s]|$)/,
lookbehind: true
},
number: {
// The number pattern from [the R7RS spec](https://small.r7rs.org/attachment/r7rs.pdf).
//
// <number> := <num 2>|<num 8>|<num 10>|<num 16>
// <num R> := <prefix R><complex R>
// <complex R> := <real R>(?:@<real R>|<imaginary R>)?|<imaginary R>
// <imaginary R> := [+-](?:<ureal R>|(?:inf|nan)\.0)?i
// <real R> := [+-]?<ureal R>|[+-](?:inf|nan)\.0
// <ureal R> := <uint R>(?:\/<uint R>)?
// | <decimal R>
//
// <decimal 10> := (?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?
// <uint R> := <digit R>+
// <prefix R> := <radix R>(?:#[ei])?|(?:#[ei])?<radix R>
// <radix 2> := #b
// <radix 8> := #o
// <radix 10> := (?:#d)?
// <radix 16> := #x
// <digit 2> := [01]
// <digit 8> := [0-7]
// <digit 10> := \d
// <digit 16> := [0-9a-f]
//
// The problem with this grammar is that the resulting regex is way to complex, so we simplify by grouping all
// non-decimal bases together. This results in a decimal (dec) and combined binary, octal, and hexadecimal (box)
// pattern:
pattern: RegExp(
SortedBNF({
'<ureal dec>':
/\d+(?:\/\d+)|(?:\d+(?:\.\d*)?|\.\d+)(?:[esfdl][+-]?\d+)?/.source,
'<real dec>': /[+-]?<ureal dec>|[+-](?:inf|nan)\.0/.source,
'<imaginary dec>': /[+-](?:<ureal dec>|(?:inf|nan)\.0)?i/.source,
'<complex dec>':
/<real dec>(?:@<real dec>|<imaginary dec>)?|<imaginary dec>/
.source,
'<num dec>': /(?:#d(?:#[ei])?|#[ei](?:#d)?)?<complex dec>/.source,
'<ureal box>': /[0-9a-f]+(?:\/[0-9a-f]+)?/.source,
'<real box>': /[+-]?<ureal box>|[+-](?:inf|nan)\.0/.source,
'<imaginary box>': /[+-](?:<ureal box>|(?:inf|nan)\.0)?i/.source,
'<complex box>':
/<real box>(?:@<real box>|<imaginary box>)?|<imaginary box>/
.source,
'<num box>': /#[box](?:#[ei])?|(?:#[ei])?#[box]<complex box>/
.source,
'<number>': /(^|[()\[\]\s])(?:<num dec>|<num box>)(?=[()\[\]\s]|$)/
.source
}),
'i'
),
lookbehind: true
},
boolean: {
pattern: /(^|[()\[\]\s])#(?:[ft]|false|true)(?=[()\[\]\s]|$)/,
lookbehind: true
},
function: {
pattern:
/((?:^|[^'`#])[(\[])(?:[^|()\[\]'\s]+|\|(?:[^\\|]|\\.)*\|)(?=[()\[\]\s]|$)/,
lookbehind: true
},
identifier: {
pattern: /(^|[()\[\]\s])\|(?:[^\\|]|\\.)*\|(?=[()\[\]\s]|$)/,
lookbehind: true,
greedy: true
},
punctuation: /[()\[\]']/
}
/**
* Given a topologically sorted BNF grammar, this will return the RegExp source of last rule of the grammar.
*
* @param {Record<string, string>} grammar
* @returns {string}
*/
function SortedBNF(grammar) {
for (var key in grammar) {
grammar[key] = grammar[key].replace(/<[\w\s]+>/g, function (key) {
return '(?:' + grammar[key].trim() + ')'
})
}
// return the last item
return grammar[key]
}
})(Prism)
}