Skip to content

Commit

Permalink
Added support for SML (#2537)
Browse files Browse the repository at this point in the history
  • Loading branch information
RunDevelopment authored Sep 13, 2020
1 parent 3b4f14c commit cb75d9e
Show file tree
Hide file tree
Showing 18 changed files with 544 additions and 3 deletions.
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

0 comments on commit cb75d9e

Please sign in to comment.