Skip to content

Commit af9c49a

Browse files
committed
Merge pull request #622 from Golmote/prism-nim
Add support for Nim
2 parents fdd4a3c + ca595b5 commit af9c49a

10 files changed

+531
-0
lines changed

components.js

+4
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ var components = {
266266
"title": "NASM",
267267
"owner": "rbmj"
268268
},
269+
"nim": {
270+
"title": "Nim",
271+
"owner": "Golmote"
272+
},
269273
"nsis": {
270274
"title": "NSIS",
271275
"owner": "idleberg"

components/prism-nim.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Prism.languages.nim = {
2+
'comment': /#.*/,
3+
// Double-quoted strings can be prefixed by an identifier (Generalized raw string literals)
4+
// Character literals are handled specifically to prevent issues with numeric type suffixes
5+
'string': /(?:(?:\b(?!\d)(?:\w|\\x[8-9a-fA-F][0-9a-fA-F])+)?(?:"""[\s\S]*?"""(?!")|"(?:\\[\s\S]|""|[^"\\])*")|'(?:\\(?:\d+|x[\da-fA-F]{2}|.)|[^'])')/,
6+
// The negative look ahead prevents wrong highlighting of the .. operator
7+
'number': /\b(?:0[xXoObB][\da-fA-F_]+|\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:[eE][+-]?\d[\d_]*)?)(?:'?[iuf]\d*)?/,
8+
'keyword': /\b(?:addr|as|asm|atomic|bind|block|break|case|cast|concept|const|continue|converter|defer|discard|distinct|do|elif|else|end|enum|except|export|finally|for|from|func|generic|if|import|include|interface|iterator|let|macro|method|mixin|nil|object|out|proc|ptr|raise|ref|return|static|template|try|tuple|type|using|var|when|while|with|without|yield)\b/,
9+
'function': {
10+
pattern: /(?:(?!\d)(?:\w|\\x[8-9a-fA-F][0-9a-fA-F])+|`[^`\r\n]+`)\*?(?:\[[^\]]+\])?(?=\s*\()/,
11+
inside: {
12+
'operator': /\*$/
13+
}
14+
},
15+
// We don't want to highlight operators inside backticks
16+
'ignore': {
17+
pattern: /`[^`\r\n]+`/,
18+
inside: {
19+
'punctuation': /`/
20+
}
21+
},
22+
'operator': {
23+
// Look behind and look ahead prevent wrong highlighting of punctuations [. .] {. .} (. .)
24+
// but allow the slice operator .. to take precedence over them
25+
// One can define his own operators in Nim so all combination of operators might be an operator.
26+
pattern: /(^|[({\[](?=\.\.)|(?![({\[]\.).)(?:(?:[=+\-*\/<>@$~&%|!?^:\\]|\.\.|\.(?![)}\]]))+|\b(?:and|div|of|or|in|is|isnot|mod|not|notin|shl|shr|xor)\b)/m,
27+
lookbehind: true
28+
},
29+
'punctuation': /[({\[]\.|\.[)}\]]|[`(){}\[\],:]/
30+
};

components/prism-nim.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/prism-nim.html

+235
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
<h1>Nim</h1>
2+
<p>To use this language, use the class "language-nim".</p>
3+
4+
<h2>Comments</h2>
5+
<pre><code># This is a comment</code></pre>
6+
7+
<h2>Strings</h2>
8+
<pre><code>"This is a string."
9+
"This is a string with \"quotes\" in it."
10+
"""This is
11+
a "multi-line"
12+
string."""
13+
""""A long string within quotes.""""
14+
R"This is a raw string."
15+
r"Some ""quotes"" inside a raw string."
16+
r"""Raw strings
17+
can also be multi-line."""
18+
foo"This is a generalized raw string literal."
19+
bar"""This is also
20+
a generalized raw string literal."""</code></pre>
21+
22+
<h2>Characters</h2>
23+
<pre><code>'a'
24+
'\''
25+
'\t'
26+
'\15'
27+
'\xFC'</code></pre>
28+
29+
<h2>Numbers</h2>
30+
<pre><code>42
31+
0xaf
32+
0xf_2_c
33+
0o07
34+
0b1111_0000
35+
0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64
36+
9_000'u
37+
32.
38+
32.1f32
39+
32.e-5
40+
32.2e+2
41+
2'i16
42+
2i16
43+
0xfe'f32</code></pre>
44+
45+
<h2>Full example</h2>
46+
<pre><code># Example from http://nim-by-example.github.io/oop_macro/
47+
import macros
48+
49+
macro class*(head: expr, body: stmt): stmt {.immediate.} =
50+
# The macro is immediate so that it doesn't
51+
# resolve identifiers passed to it
52+
53+
var typeName, baseName: NimNode
54+
55+
if head.kind == nnkIdent:
56+
# `head` is expression `typeName`
57+
# echo head.treeRepr
58+
# --------------------
59+
# Ident !"Animal"
60+
typeName = head
61+
62+
elif head.kind == nnkInfix and $head[0] == "of":
63+
# `head` is expression `typeName of baseClass`
64+
# echo head.treeRepr
65+
# --------------------
66+
# Infix
67+
# Ident !"of"
68+
# Ident !"Animal"
69+
# Ident !"RootObj"
70+
typeName = head[1]
71+
baseName = head[2]
72+
73+
else:
74+
quit "Invalid node: " & head.lispRepr
75+
76+
# echo treeRepr(body)
77+
# --------------------
78+
# StmtList
79+
# VarSection
80+
# IdentDefs
81+
# Ident !"name"
82+
# Ident !"string"
83+
# Empty
84+
# IdentDefs
85+
# Ident !"age"
86+
# Ident !"int"
87+
# Empty
88+
# MethodDef
89+
# Ident !"vocalize"
90+
# Empty
91+
# Empty
92+
# FormalParams
93+
# Ident !"string"
94+
# Empty
95+
# Empty
96+
# StmtList
97+
# StrLit ...
98+
# MethodDef
99+
# Ident !"age_human_yrs"
100+
# Empty
101+
# Empty
102+
# FormalParams
103+
# Ident !"int"
104+
# Empty
105+
# Empty
106+
# StmtList
107+
# DotExpr
108+
# Ident !"this"
109+
# Ident !"age"
110+
111+
# create a new stmtList for the result
112+
result = newStmtList()
113+
114+
# var declarations will be turned into object fields
115+
var recList = newNimNode(nnkRecList)
116+
117+
# Iterate over the statements, adding `this: T`
118+
# to the parameters of functions
119+
for node in body.children:
120+
case node.kind:
121+
122+
of nnkMethodDef, nnkProcDef:
123+
# inject `this: T` into the arguments
124+
let p = copyNimTree(node.params)
125+
p.insert(1, newIdentDefs(ident"this", typeName))
126+
node.params = p
127+
result.add(node)
128+
129+
of nnkVarSection:
130+
# variables get turned into fields of the type.
131+
for n in node.children:
132+
recList.add(n)
133+
134+
else:
135+
result.add(node)
136+
137+
# The following prints out the AST structure:
138+
#
139+
# import macros
140+
# dumptree:
141+
# type X = ref object of Y
142+
# z: int
143+
# --------------------
144+
# TypeSection
145+
# TypeDef
146+
# Ident !"X"
147+
# Empty
148+
# RefTy
149+
# ObjectTy
150+
# Empty
151+
# OfInherit
152+
# Ident !"Y"
153+
# RecList
154+
# IdentDefs
155+
# Ident !"z"
156+
# Ident !"int"
157+
# Empty
158+
159+
result.insert(0,
160+
if baseName == nil:
161+
quote do:
162+
type `typeName` = ref object of RootObj
163+
else:
164+
quote do:
165+
type `typeName` = ref object of `baseName`
166+
)
167+
# Inspect the tree structure:
168+
#
169+
# echo result.treeRepr
170+
# --------------------
171+
# StmtList
172+
# StmtList
173+
# TypeSection
174+
# TypeDef
175+
# Ident !"Animal"
176+
# Empty
177+
# RefTy
178+
# ObjectTy
179+
# Empty
180+
# OfInherit
181+
# Ident !"RootObj"
182+
# Empty <= We want to replace this
183+
# MethodDef
184+
# ...
185+
186+
result[0][0][0][2][0][2] = recList
187+
188+
# Lets inspect the human-readable version of the output
189+
# echo repr(result)
190+
# Output:
191+
# type
192+
# Animal = ref object of RootObj
193+
# name: string
194+
# age: int
195+
#
196+
# method vocalize(this: Animal): string =
197+
# "..."
198+
#
199+
# method age_human_yrs(this: Animal): int =
200+
# this.age
201+
202+
# ---
203+
204+
class Animal of RootObj:
205+
var name: string
206+
var age: int
207+
method vocalize: string = "..."
208+
method age_human_yrs: int = this.age # `this` is injected
209+
210+
class Dog of Animal:
211+
method vocalize: string = "woof"
212+
method age_human_yrs: int = this.age * 7
213+
214+
class Cat of Animal:
215+
method vocalize: string = "meow"
216+
217+
# ---
218+
219+
var animals: seq[Animal] = @[]
220+
animals.add(Dog(name: "Sparky", age: 10))
221+
animals.add(Cat(name: "Mitten", age: 10))
222+
223+
for a in animals:
224+
echo a.vocalize()
225+
echo a.age_human_yrs()</code></pre>
226+
227+
<h2>Known failures</h2>
228+
<p>There are certain edge cases where Prism will fail.
229+
There are always such cases in every regex-based syntax highlighter.
230+
However, Prism dares to be open and honest about them.
231+
If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug.
232+
</p>
233+
234+
<h3>Comment-like substrings</h3>
235+
<pre><code>"This # is a broken string"</code></pre>
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# Foobar
3+
4+
----------------------------------------------------
5+
6+
[
7+
["comment", "#"],
8+
["comment", "# Foobar"]
9+
]
10+
11+
----------------------------------------------------
12+
13+
Checks for comments.
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fo\x9ao(
2+
class*(
3+
takeV[T](
4+
`$`(
5+
6+
----------------------------------------------------
7+
8+
[
9+
["function", ["fo\\x9ao"]], ["punctuation", "("],
10+
["function", ["class", ["operator", "*"]]], ["punctuation", "("],
11+
["function", ["takeV[T]"]], ["punctuation", "("],
12+
["function", ["`$`"]], ["punctuation", "("]
13+
]
14+
15+
----------------------------------------------------
16+
17+
Checks for functions.

0 commit comments

Comments
 (0)