Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,14 @@
"require": "markup-templating",
"owner": "Golmote"
},
"sml": {
"title": "SML",
"alias": "smlnj",
"aliasTitles": {
"smlnj": "SML/NJ"
},
"owner": "RunDevelopment"
},
"solidity": {
"title": "Solidity (Ethereum)",
"alias": "sol",
Expand Down
68 changes: 68 additions & 0 deletions components/prism-sml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// https://smlfamily.github.io/sml97-defn.pdf
// https://people.mpi-sws.org/~rossberg/sml.html
(function (Prism) {

var keywords = /\b(?:abstype|and|andalso|as|case|datatype|do|else|end|eqtype|exception|fn|fun|functor|handle|if|in|include|infix|infixr|let|local|nonfix|of|op|open|orelse|raise|rec|sharing|sig|signature|struct|structure|then|type|val|where|while|with|withtype)\b/i;

Prism.languages.sml = {
// allow one level of nesting
'comment': /\(\*(?:[^*(]|\*(?!\))|\((?!\*)|\(\*(?:[^*(]|\*(?!\))|\((?!\*))*\*\))*\*\)/,
'string': {
pattern: /#?"(?:[^"\\]|\\.)*"/,
greedy: true
},

'class-name': [
{
// This is only an approximation since the real grammar is context-free
//
// Why the main loop so complex?
// The main loop is approximately the same as /(?:\s*(?:[*,]|->)\s*<TERMINAL>)*/ which is, obviously, a lot
// simpler. The difference is that if a comma is the last iteration of the loop, then the terminal must be
// followed by a long identifier.
pattern: RegExp(
/((?:^|[^:]):\s*)<TERMINAL>(?:\s*(?:(?:\*|->)\s*<TERMINAL>|,\s*<TERMINAL>(?:(?=<NOT-LAST>)|(?!<NOT-LAST>)\s+<LONG-ID>)))*/.source
.replace(/<NOT-LAST>/g, function () { return /\s*(?:[*,]|->)/.source; })
.replace(/<TERMINAL>/g, function () {
return /(?:'[\w']*|<LONG-ID>|\((?:[^()]|\([^()]*\))*\)|\{(?:[^{}]|\{[^{}]*\})*\})(?:\s+<LONG-ID>)*/.source;
})
.replace(/<LONG-ID>/g, function () { return /(?!<KEYWORD>)[a-z\d_][\w'.]*/.source; })
.replace(/<KEYWORD>/g, function () { return keywords.source; }),
'i'
),
lookbehind: true,
greedy: true,
inside: null // see below
},
{
pattern: /((?:^|[^\w'])(?:datatype|exception|functor|signature|structure|type)\s+)[a-z_][\w'.]*/i,
lookbehind: true
}
],
'function': {
pattern: /((?:^|[^\w'])fun\s+)[a-z_][\w'.]*/i,
lookbehind: true
},

'keyword': keywords,
'variable': {
pattern: /(^|[^\w'])'[\w']*/,
lookbehind: true,
},

'number': /~?\b(?:\d+(?:\.\d+)?(?:e~?\d+)?|0x[\da-f]+)\b/i,
'word': {
pattern: /\b0w(?:\d+|x[\da-f]+)\b/i,
alias: 'constant'
},

'boolean': /\b(?:false|true)\b/i,
'operator': /\.\.\.|:[>=:]|=>?|->|[<>]=?|[!+\-*/^#|@~]/,
'punctuation': /[(){}\[\].:,;]/
};

Prism.languages.sml['class-name'][0].inside = Prism.languages.sml;

Prism.languages.smlnj = Prism.languages.sml;

}(Prism));
1 change: 1 addition & 0 deletions components/prism-sml.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions examples/prism-sml.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<h2>Full example</h2>
<pre><code>(* source: https://github.com/HarrisonGrodin/ml-numbers/blob/ba35c763092052e391871edf224f17474c6231b1/src/Rational.sml *)

structure Rational :> RATIONAL =
struct
type t = int * int (* (a,b) invariant: a,b coprime; b nonnegative *)

local
val rec gcd = fn
(m,0) => m
| (m,n) => gcd (n, m mod n)
in
infix 8 //
val op // = fn (x,y) => (
let
val gcd = gcd (x,y)
in
(x div gcd, y div gcd)
end
)
end

val show = Fn.id

val zero = (0,1)
val one = (1,1)

val eq : t * t -> bool = (op =)
val compare = fn ((a,b),(x,y)) => Int.compare (a * y, b * x)
val toString = fn (x,y) => Int.toString x ^ " // " ^ Int.toString y
val percent =
Fn.curry (Fn.flip (op ^)) "%"
o Int.toString
o (fn (a,b) => (100 * a) div b)

val op + = fn ((a,b),(x,y)) => (a * y + b * x) // (b * y)
val ~ = fn (a,b) => (~a,b)
val op - = fn (r1,r2) => r1 + ~r2

val op * = fn ((a,b),(x,y)) => (a * x) // (b * y)
val inv = Fn.flip (op //)
val op / = fn (r1,r2) => r1 * inv r2
end</code></pre>
1 change: 1 addition & 0 deletions plugins/autoloader/prism-autoloader.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
"rb": "ruby",
"sh-session": "shell-session",
"shellsession": "shell-session",
"smlnj": "sml",
"sol": "solidity",
"sln": "solution-file",
"rq": "sparql",
Expand Down
2 changes: 1 addition & 1 deletion plugins/autoloader/prism-autoloader.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions plugins/show-language/prism-show-language.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@
"shell-session": "Shell session",
"sh-session": "Shell session",
"shellsession": "Shell session",
"sml": "SML",
"smlnj": "SML/NJ",
"solidity": "Solidity (Ethereum)",
"sol": "Solidity (Ethereum)",
"solution-file": "Solution file",
Expand Down
Loading