Skip to content

Commit

Permalink
Merge pull request #622 from Golmote/prism-nim
Browse files Browse the repository at this point in the history
Add support for Nim
  • Loading branch information
Golmote committed Sep 7, 2015
2 parents fdd4a3c + ca595b5 commit af9c49a
Show file tree
Hide file tree
Showing 10 changed files with 531 additions and 0 deletions.
4 changes: 4 additions & 0 deletions components.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ var components = {
"title": "NASM",
"owner": "rbmj"
},
"nim": {
"title": "Nim",
"owner": "Golmote"
},
"nsis": {
"title": "NSIS",
"owner": "idleberg"
Expand Down
30 changes: 30 additions & 0 deletions components/prism-nim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Prism.languages.nim = {
'comment': /#.*/,
// Double-quoted strings can be prefixed by an identifier (Generalized raw string literals)
// Character literals are handled specifically to prevent issues with numeric type suffixes
'string': /(?:(?:\b(?!\d)(?:\w|\\x[8-9a-fA-F][0-9a-fA-F])+)?(?:"""[\s\S]*?"""(?!")|"(?:\\[\s\S]|""|[^"\\])*")|'(?:\\(?:\d+|x[\da-fA-F]{2}|.)|[^'])')/,
// The negative look ahead prevents wrong highlighting of the .. operator
'number': /\b(?:0[xXoObB][\da-fA-F_]+|\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:[eE][+-]?\d[\d_]*)?)(?:'?[iuf]\d*)?/,
'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/,
'function': {
pattern: /(?:(?!\d)(?:\w|\\x[8-9a-fA-F][0-9a-fA-F])+|`[^`\r\n]+`)\*?(?:\[[^\]]+\])?(?=\s*\()/,
inside: {
'operator': /\*$/
}
},
// We don't want to highlight operators inside backticks
'ignore': {
pattern: /`[^`\r\n]+`/,
inside: {
'punctuation': /`/
}
},
'operator': {
// Look behind and look ahead prevent wrong highlighting of punctuations [. .] {. .} (. .)
// but allow the slice operator .. to take precedence over them
// One can define his own operators in Nim so all combination of operators might be an operator.
pattern: /(^|[({\[](?=\.\.)|(?![({\[]\.).)(?:(?:[=+\-*\/<>@$~&%|!?^:\\]|\.\.|\.(?![)}\]]))+|\b(?:and|div|of|or|in|is|isnot|mod|not|notin|shl|shr|xor)\b)/m,
lookbehind: true
},
'punctuation': /[({\[]\.|\.[)}\]]|[`(){}\[\],:]/
};
1 change: 1 addition & 0 deletions components/prism-nim.min.js

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

235 changes: 235 additions & 0 deletions examples/prism-nim.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
<h1>Nim</h1>
<p>To use this language, use the class "language-nim".</p>

<h2>Comments</h2>
<pre><code># This is a comment</code></pre>

<h2>Strings</h2>
<pre><code>"This is a string."
"This is a string with \"quotes\" in it."
"""This is
a "multi-line"
string."""
""""A long string within quotes.""""
R"This is a raw string."
r"Some ""quotes"" inside a raw string."
r"""Raw strings
can also be multi-line."""
foo"This is a generalized raw string literal."
bar"""This is also
a generalized raw string literal."""</code></pre>

<h2>Characters</h2>
<pre><code>'a'
'\''
'\t'
'\15'
'\xFC'</code></pre>

<h2>Numbers</h2>
<pre><code>42
0xaf
0xf_2_c
0o07
0b1111_0000
0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64
9_000'u
32.
32.1f32
32.e-5
32.2e+2
2'i16
2i16
0xfe'f32</code></pre>

<h2>Full example</h2>
<pre><code># Example from http://nim-by-example.github.io/oop_macro/
import macros

macro class*(head: expr, body: stmt): stmt {.immediate.} =
# The macro is immediate so that it doesn't
# resolve identifiers passed to it

var typeName, baseName: NimNode

if head.kind == nnkIdent:
# `head` is expression `typeName`
# echo head.treeRepr
# --------------------
# Ident !"Animal"
typeName = head

elif head.kind == nnkInfix and $head[0] == "of":
# `head` is expression `typeName of baseClass`
# echo head.treeRepr
# --------------------
# Infix
# Ident !"of"
# Ident !"Animal"
# Ident !"RootObj"
typeName = head[1]
baseName = head[2]

else:
quit "Invalid node: " & head.lispRepr

# echo treeRepr(body)
# --------------------
# StmtList
# VarSection
# IdentDefs
# Ident !"name"
# Ident !"string"
# Empty
# IdentDefs
# Ident !"age"
# Ident !"int"
# Empty
# MethodDef
# Ident !"vocalize"
# Empty
# Empty
# FormalParams
# Ident !"string"
# Empty
# Empty
# StmtList
# StrLit ...
# MethodDef
# Ident !"age_human_yrs"
# Empty
# Empty
# FormalParams
# Ident !"int"
# Empty
# Empty
# StmtList
# DotExpr
# Ident !"this"
# Ident !"age"

# create a new stmtList for the result
result = newStmtList()

# var declarations will be turned into object fields
var recList = newNimNode(nnkRecList)

# Iterate over the statements, adding `this: T`
# to the parameters of functions
for node in body.children:
case node.kind:

of nnkMethodDef, nnkProcDef:
# inject `this: T` into the arguments
let p = copyNimTree(node.params)
p.insert(1, newIdentDefs(ident"this", typeName))
node.params = p
result.add(node)

of nnkVarSection:
# variables get turned into fields of the type.
for n in node.children:
recList.add(n)

else:
result.add(node)

# The following prints out the AST structure:
#
# import macros
# dumptree:
# type X = ref object of Y
# z: int
# --------------------
# TypeSection
# TypeDef
# Ident !"X"
# Empty
# RefTy
# ObjectTy
# Empty
# OfInherit
# Ident !"Y"
# RecList
# IdentDefs
# Ident !"z"
# Ident !"int"
# Empty

result.insert(0,
if baseName == nil:
quote do:
type `typeName` = ref object of RootObj
else:
quote do:
type `typeName` = ref object of `baseName`
)
# Inspect the tree structure:
#
# echo result.treeRepr
# --------------------
# StmtList
# StmtList
# TypeSection
# TypeDef
# Ident !"Animal"
# Empty
# RefTy
# ObjectTy
# Empty
# OfInherit
# Ident !"RootObj"
# Empty <= We want to replace this
# MethodDef
# ...

result[0][0][0][2][0][2] = recList

# Lets inspect the human-readable version of the output
# echo repr(result)
# Output:
# type
# Animal = ref object of RootObj
# name: string
# age: int
#
# method vocalize(this: Animal): string =
# "..."
#
# method age_human_yrs(this: Animal): int =
# this.age

# ---

class Animal of RootObj:
var name: string
var age: int
method vocalize: string = "..."
method age_human_yrs: int = this.age # `this` is injected

class Dog of Animal:
method vocalize: string = "woof"
method age_human_yrs: int = this.age * 7

class Cat of Animal:
method vocalize: string = "meow"

# ---

var animals: seq[Animal] = @[]
animals.add(Dog(name: "Sparky", age: 10))
animals.add(Cat(name: "Mitten", age: 10))

for a in animals:
echo a.vocalize()
echo a.age_human_yrs()</code></pre>

<h2>Known failures</h2>
<p>There are certain edge cases where Prism will fail.
There are always such cases in every regex-based syntax highlighter.
However, Prism dares to be open and honest about them.
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.
</p>

<h3>Comment-like substrings</h3>
<pre><code>"This # is a broken string"</code></pre>
13 changes: 13 additions & 0 deletions tests/languages/nim/comment_feature.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# Foobar

----------------------------------------------------

[
["comment", "#"],
["comment", "# Foobar"]
]

----------------------------------------------------

Checks for comments.
17 changes: 17 additions & 0 deletions tests/languages/nim/function_feature.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
fo\x9ao(
class*(
takeV[T](
`$`(

----------------------------------------------------

[
["function", ["fo\\x9ao"]], ["punctuation", "("],
["function", ["class", ["operator", "*"]]], ["punctuation", "("],
["function", ["takeV[T]"]], ["punctuation", "("],
["function", ["`$`"]], ["punctuation", "("]
]

----------------------------------------------------

Checks for functions.
Loading

0 comments on commit af9c49a

Please sign in to comment.