Add support for Lisp (#1297)

* add emacs

* rename to elisp

* add elisp to components

* add comment test

* add heading test

* WIP string test

* update string tests

* test symbols in strings

* test arguments

* test quoted symbol

* lisp-property test

* splice test

* add keyword test

* test for declare

* test interactive

* boolean test

* test numbers

* test defvar

* fix greedy defun regex

* test defun

* test lambda

* test car

* test punctuation

* use var instead of const

* remove arrow functions

* flatten language structure

* remove unnecessary escaping

* add lisp and emacs

* add lisp

* fix template strings

* minify lisp

* add example elisp file

* simplify number

* don't mark other def as keywords

* dont mark other def as keyword in defun

* make lambda a keyword only at the beginning

* restore single quotes in components

* double quote in elisp

* minify elisp

* quote keys in components

* rename punctuation test

* add semicolons elisp

* undo prettier changes to components.js

* add lisp to components.json

* rename elisp to lisp

* fix components.json

* add minified lisp file

* rename example lisp file

* move lisp to first position

* explain null initialized properties in lisp file

* remove trailing commas

* put lisp first in example file

* add ifee for lisp file

* update lisp min file

* update show language assets

* add components index min file

* add emacs-lisp alias

* change title of lisp example file

* undo theme change

* combine regex for parens

* remove min index

* remove unneeded example html

* remove doubled string test

* capitalize lisp in components

* change string theme to match master

* build assets after adding lisp
This commit is contained in:
Juan Caicedo 2018-04-05 12:24:22 -05:00 committed by Golmote
parent 689227ba1a
commit 46468f84f4
21 changed files with 591 additions and 1 deletions

File diff suppressed because one or more lines are too long

View File

@ -373,6 +373,11 @@
"title": "Liquid",
"owner": "cinhtau"
},
"lisp": {
"title": "Lisp",
"owner": "JuanCaicedo",
"alias": ["emacs", "elisp", "emacs-lisp"]
},
"livescript": {
"title": "LiveScript",
"owner": "Golmote"

197
components/prism-lisp.js Normal file
View File

@ -0,0 +1,197 @@
(function (Prism) {
// Functions to construct regular expressions
// simple form
// e.g. (interactive ... or (interactive)
function simple_form(name) {
return new RegExp('(\\()' + name + '(?=[\\s\\)])');
}
// booleans and numbers
function primitive(pattern) {
return new RegExp('([\\s([])' + pattern + '(?=[\\s)])');
}
// Patterns in regular expressions
// Symbol name. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html
// & and : are excluded as they are usually used for special purposes
var symbol = '[-+*/_~!@$%^=<>{}\\w]+';
// symbol starting with & used in function arguments
var marker = '&' + symbol;
// Open parenthesis for look-behind
var par = '(\\()';
var endpar = '(?=\\))';
// End the pattern with look-ahead space
var space = '(?=\\s)';
var language = {
// Three or four semicolons are considered a heading.
// See https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html
heading: {
pattern: /;;;.*/,
alias: ['comment', 'title']
},
comment: /;.*/,
string: {
pattern: /"(?:[^"\\]*|\\.)*"/,
greedy: true,
inside: {
argument: /[-A-Z]+(?=[.,\s])/,
symbol: new RegExp('`' + symbol + "'")
}
},
'quoted-symbol': {
pattern: new RegExp("#?'" + symbol),
alias: ['variable', 'symbol']
},
'lisp-property': {
pattern: new RegExp(':' + symbol),
alias: 'property'
},
splice: {
pattern: new RegExp(',@?' + symbol),
alias: ['symbol', 'variable']
},
keyword: [
{
pattern: new RegExp(
par +
'(?:(?:lexical-)?let\\*?|(?:cl-)?letf|if|when|while|unless|cons|cl-loop|and|or|not|cond|setq|error|message|null|require|provide|use-package)' +
space
),
lookbehind: true
},
{
pattern: new RegExp(
par + '(?:for|do|collect|return|finally|append|concat|in|by)' + space
),
lookbehind: true
},
],
declare: {
pattern: simple_form('declare'),
lookbehind: true,
alias: 'keyword'
},
interactive: {
pattern: simple_form('interactive'),
lookbehind: true,
alias: 'keyword'
},
boolean: {
pattern: primitive('(?:t|nil)'),
lookbehind: true
},
number: {
pattern: primitive('[-+]?\\d+(?:\\.\\d*)?'),
lookbehind: true
},
defvar: {
pattern: new RegExp(par + 'def(?:var|const|custom|group)\\s+' + symbol),
lookbehind: true,
inside: {
keyword: /^def[a-z]+/,
variable: new RegExp(symbol)
}
},
defun: {
pattern: new RegExp(
par +
'(?:cl-)?(?:defun\\*?|defmacro)\\s+' +
symbol +
'\\s+\\([\\s\\S]*?\\)'
),
lookbehind: true,
inside: {
keyword: /^(?:cl-)?def\S+/,
// See below, this property needs to be defined later so that it can
// reference the language object.
arguments: null,
function: {
pattern: new RegExp('(^\\s)' + symbol),
lookbehind: true
},
punctuation: /[()]/
}
},
lambda: {
pattern: new RegExp(par + 'lambda\\s+\\((?:&?' + symbol + '\\s*)*\\)'),
lookbehind: true,
inside: {
keyword: /^lambda/,
// See below, this property needs to be defined later so that it can
// reference the language object.
arguments: null,
punctuation: /[()]/
}
},
car: {
pattern: new RegExp(par + symbol),
lookbehind: true
},
punctuation: [
// open paren, brackets, and close paren
/(['`,]?\(|[)\[\]])/,
// cons
{
pattern: /(\s)\.(?=\s)/,
lookbehind: true
},
]
};
var arg = {
'lisp-marker': new RegExp(marker),
rest: {
argument: {
pattern: new RegExp(symbol),
alias: 'variable'
},
varform: {
pattern: new RegExp(par + symbol + '\\s+\\S[\\s\\S]*' + endpar),
lookbehind: true,
inside: {
string: language.string,
boolean: language.boolean,
number: language.number,
symbol: language.symbol,
punctuation: /[()]/
}
}
}
};
var forms = '\\S+(?:\\s+\\S+)*';
var arglist = {
pattern: new RegExp(par + '[\\s\\S]*' + endpar),
lookbehind: true,
inside: {
'rest-vars': {
pattern: new RegExp('&(?:rest|body)\\s+' + forms),
inside: arg
},
'other-marker-vars': {
pattern: new RegExp('&(?:optional|aux)\\s+' + forms),
inside: arg
},
keys: {
pattern: new RegExp('&key\\s+' + forms + '(?:\\s+&allow-other-keys)?'),
inside: arg
},
argument: {
pattern: new RegExp(symbol),
alias: 'variable'
},
punctuation: /[()]/
}
};
language['lambda'].inside.arguments = arglist;
language['defun'].inside.arguments = Prism.util.clone(arglist);
language['defun'].inside.arguments.inside.sublist = arglist;
Prism.languages.lisp = language;
Prism.languages.elisp = language;
Prism.languages.emacs = language;
Prism.languages['emacs-lisp'] = language;
}(Prism));

1
components/prism-lisp.min.js vendored Normal file
View File

@ -0,0 +1 @@
!function(e){function n(e){return new RegExp("(\\()"+e+"(?=[\\s\\)])")}function a(e){return new RegExp("([\\s([])"+e+"(?=[\\s)])")}var t="[-+*/_~!@$%^=<>{}\\w]+",r="&"+t,i="(\\()",s="(?=\\))",o="(?=\\s)",l={heading:{pattern:/;;;.*/,alias:["comment","title"]},comment:/;.*/,string:{pattern:/"(?:[^"\\]*|\\.)*"/,greedy:!0,inside:{argument:/[-A-Z]+(?=[.,\s])/,symbol:new RegExp("`"+t+"'")}},"quoted-symbol":{pattern:new RegExp("#?'"+t),alias:["variable","symbol"]},"lisp-property":{pattern:new RegExp(":"+t),alias:"property"},splice:{pattern:new RegExp(",@?"+t),alias:["symbol","variable"]},keyword:[{pattern:new RegExp(i+"(?:(?:lexical-)?let\\*?|(?:cl-)?letf|if|when|while|unless|cons|cl-loop|and|or|not|cond|setq|error|message|null|require|provide|use-package)"+o),lookbehind:!0},{pattern:new RegExp(i+"(?:for|do|collect|return|finally|append|concat|in|by)"+o),lookbehind:!0}],declare:{pattern:n("declare"),lookbehind:!0,alias:"keyword"},interactive:{pattern:n("interactive"),lookbehind:!0,alias:"keyword"},"boolean":{pattern:a("(?:t|nil)"),lookbehind:!0},number:{pattern:a("[-+]?\\d+(?:\\.\\d*)?"),lookbehind:!0},defvar:{pattern:new RegExp(i+"def(?:var|const|custom|group)\\s+"+t),lookbehind:!0,inside:{keyword:/^def[a-z]+/,variable:new RegExp(t)}},defun:{pattern:new RegExp(i+"(?:cl-)?(?:defun\\*?|defmacro)\\s+"+t+"\\s+\\([\\s\\S]*?\\)"),lookbehind:!0,inside:{keyword:/^(?:cl-)?def\S+/,arguments:null,"function":{pattern:new RegExp("(^\\s)"+t),lookbehind:!0},punctuation:/[()]/}},lambda:{pattern:new RegExp(i+"lambda\\s+\\((?:&?"+t+"\\s*)*\\)"),lookbehind:!0,inside:{keyword:/^lambda/,arguments:null,punctuation:/[()]/}},car:{pattern:new RegExp(i+t),lookbehind:!0},punctuation:[/(['`,]?\(|[)\[\]])/,{pattern:/(\s)\.(?=\s)/,lookbehind:!0}]},p={"lisp-marker":new RegExp(r),rest:{argument:{pattern:new RegExp(t),alias:"variable"},varform:{pattern:new RegExp(i+t+"\\s+\\S[\\s\\S]*"+s),lookbehind:!0,inside:{string:l.string,"boolean":l.boolean,number:l.number,symbol:l.symbol,punctuation:/[()]/}}}},d="\\S+(?:\\s+\\S+)*",u={pattern:new RegExp(i+"[\\s\\S]*"+s),lookbehind:!0,inside:{"rest-vars":{pattern:new RegExp("&(?:rest|body)\\s+"+d),inside:p},"other-marker-vars":{pattern:new RegExp("&(?:optional|aux)\\s+"+d),inside:p},keys:{pattern:new RegExp("&key\\s+"+d+"(?:\\s+&allow-other-keys)?"),inside:p},argument:{pattern:new RegExp(t),alias:"variable"},punctuation:/[()]/}};l.lambda.inside.arguments=u,l.defun.inside.arguments=e.util.clone(u),l.defun.inside.arguments.inside.sublist=u,e.languages.lisp=l,e.languages.elisp=l,e.languages.emacs=l,e.languages["emacs-lisp"]=l}(Prism);

46
examples/prism-lisp.html Normal file
View File

@ -0,0 +1,46 @@
<h2>Comments</h2>
<pre><code>;; (foo bar)</code></pre>
<h2>Strings</h2>
<pre><code>(foo "bar")</code></pre>
<h3>With nested symbols</h3>
<pre><code>(foo "A string with a `symbol ")</code></pre>
<h3>With nested arguments</h3>
<pre><code>(foo "A string with an ARGUMENT ")</code></pre>
<h2>Quoted symbols</h2>
<pre><code>(foo #'bar)</code></pre>
<h2>Lisp properties</h2>
<pre><code>(foo :bar)</code></pre>
<h2>Splices</h2>
<pre><code>(foo ,bar ,@bar)</code></pre>
<h2>Keywords</h2>
<pre><code>(let foo (bar arg))</code></pre>
<h2>Declarations</h2>
<pre><code>(declare foo)</code></pre>
<h2>Booleans</h2>
<pre><code>(foo t)</code></pre>
<pre><code>(foo nil)</code></pre>
<h2>Numbers</h2>
<pre><code>(foo 1)</code></pre>
<pre><code>(foo -1.5)</code></pre>
<h2>Definitions</h2>
<pre><code>(defvar bar 23)</code></pre>
<pre><code>(defcustom bar 23)</code></pre>
<h2>Function definitions</h2>
<pre><code>(defun multiply-by-seven (number)
"Multiply NUMBER by seven."
(* 7 number))</code></pre>
<h2>Lambda expressions</h2>
<pre><code>(lambda (number) (* 7 number))</code></pre>

View File

@ -0,0 +1,17 @@
(t)
(nil)
(foo t)
[t ]
----------------------------------------------------
[
["punctuation", "("], ["boolean", "t"], ["punctuation", ")"],
["punctuation", "("], ["boolean", "nil"], ["punctuation", ")"],
["punctuation", "("], ["car", "foo"], ["boolean", "t"], ["punctuation", ")"],
["punctuation", "["], ["boolean", "t"], ["punctuation", "]"]
]
----------------------------------------------------
Checks for booleans.

View File

@ -0,0 +1,13 @@
(foo)
(foo bar)
----------------------------------------------------
[
["punctuation","("], ["car", "foo"], ["punctuation",")"],
["punctuation","("], ["car", "foo"], " bar", ["punctuation",")"]
]
----------------------------------------------------
Checks for car.

View File

@ -0,0 +1,11 @@
;; h1
----------------------------------------------------
[
["comment", ";; h1"]
]
----------------------------------------------------
Checks for comments.

View File

@ -0,0 +1,16 @@
(declare)
(declare a)
(declare
a)
----------------------------------------------------
[
["punctuation", "("], ["declare", "declare"], ["punctuation", ")"],
["punctuation", "("], ["declare", "declare"], " a", ["punctuation", ")"],
["punctuation", "("], ["declare", "declare"], "\r\na", ["punctuation", ")"]
]
----------------------------------------------------
Checks for declare.

View File

@ -0,0 +1,27 @@
(defun foo ())
(defun foo (bar))
(defun foo (bar &body arg1) )
(defun foo (bar &rest arg1) )
(defun foo (bar &body arg1 arg2) )
(defun foo (bar &key arg1) )
(defun foo (bar &key arg1 &allow-other-keys) )
(defun foo (&optional arg1) )
(defun defabc ())
----------------------------------------------------
[
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", []], ["punctuation", ")"]]], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ]]], ["punctuation", ")"]]], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["rest-vars", [["lisp-marker", "&body" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["rest-vars", [["lisp-marker", "&rest" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["rest-vars", [["lisp-marker", "&body" ], ["argument", "arg1"], ["argument", "arg2"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["keys", [["lisp-marker", "&key" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["keys", [["lisp-marker", "&key" ], ["argument", "arg1"], ["lisp-marker", "&allow-other-keys"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [["other-marker-vars", [["lisp-marker", "&optional" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "defabc"], ["punctuation", "("], ["arguments", []], ["punctuation", ")"]]], ["punctuation", ")"]
]
----------------------------------------------------
Checks for defun.

View File

@ -0,0 +1,25 @@
(defvar foo)
(defvar foo bar)
(defvar foo)
(defvar)
(defconst foo)
(defcustom foo)
(defgroup foo)
(defvar defabc)
----------------------------------------------------
[
["punctuation", "("], ["defvar", [ ["keyword", "defvar" ], ["variable", "foo"] ]], ["punctuation", ")"],
["punctuation", "("], ["defvar", [ ["keyword", "defvar" ], ["variable", "foo"] ]], " bar", ["punctuation", ")"],
["punctuation", "("], ["defvar", [ ["keyword", "defvar" ], ["variable", "foo"] ]], ["punctuation", ")"],
["punctuation", "("], ["car", "defvar"], ["punctuation", ")"],
["punctuation", "("], ["defvar", [ ["keyword", "defconst" ], ["variable", "foo"] ]], ["punctuation", ")"],
["punctuation", "("], ["defvar", [ ["keyword", "defcustom" ], ["variable", "foo"] ]], ["punctuation", ")"],
["punctuation", "("], ["defvar", [ ["keyword", "defgroup" ], ["variable", "foo"] ]], ["punctuation", ")"],
["punctuation", "("], ["defvar", [ ["keyword", "defvar" ], ["variable", "defabc"] ]], ["punctuation", ")"]
]
----------------------------------------------------
Checks for defvar.

View File

@ -0,0 +1,11 @@
;;; h1
----------------------------------------------------
[
["heading", ";;; h1"]
]
----------------------------------------------------
Checks for headings.

View File

@ -0,0 +1,16 @@
(interactive)
(interactive a)
(interactive
a)
----------------------------------------------------
[
["punctuation", "("], ["interactive", "interactive"], ["punctuation", ")"],
["punctuation", "("], ["interactive", "interactive"], " a", ["punctuation", ")"],
["punctuation", "("], ["interactive", "interactive"], "\r\na", ["punctuation", ")"]
]
----------------------------------------------------
Checks for declare.

View File

@ -0,0 +1,73 @@
(let )
let
(lexical-let )
(let* )
(letf )
(cl-letf )
(if )
(when )
(while )
(unless )
(cons )
(cl-loop )
(and )
(or )
(not )
(cond )
(setq )
(error )
(message )
(null )
(require )
(provide )
(use-package )
(for )
(do )
(collect )
(return )
(finally )
(append )
(concat )
(in )
(by )
----------------------------------------------------
[
["punctuation", "("], ["keyword", "let"], ["punctuation", ")"],
"\r\nlet\r\n",
["punctuation", "("], ["keyword", "lexical-let"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "let*"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "letf"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "cl-letf"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "if"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "when"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "while"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "unless"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "cons"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "cl-loop"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "and"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "or"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "not"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "cond"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "setq"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "error"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "message"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "null"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "require"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "provide"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "use-package"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "for"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "do"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "collect"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "return"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "finally"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "append"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "concat"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "in"], ["punctuation", ")"],
["punctuation", "("], ["keyword", "by"], ["punctuation", ")"]
]
----------------------------------------------------
Checks for all keyword variations.

View File

@ -0,0 +1,13 @@
(lambda () ())
(lambda () (foo bar))
----------------------------------------------------
[
["punctuation","("],["lambda",[["keyword","lambda"],["punctuation","("],["arguments",[]],["punctuation",")"]]],["punctuation","("],["punctuation",")"],["punctuation",")"],
["punctuation","("],["lambda",[["keyword","lambda"],["punctuation","("],["arguments",[]],["punctuation",")"]]],["punctuation","("],["car","foo"]," bar",["punctuation",")"],["punctuation",")"]
]
----------------------------------------------------
Checks for lambda.

View File

@ -0,0 +1,15 @@
(
:foo
)
----------------------------------------------------
[
["punctuation", "("],
["lisp-property", ":foo"],
["punctuation", ")"]
]
----------------------------------------------------
Checks for lisp properties.

View File

@ -0,0 +1,27 @@
(1)
(12)
(1.2)
(1.23)
(1.)
(foo 1)
[1 ]
(-1)
(+1)
----------------------------------------------------
[
["punctuation", "("], ["number", "1"], ["punctuation", ")"],
["punctuation", "("], ["number", "12"], ["punctuation", ")"],
["punctuation", "("], ["number", "1.2"], ["punctuation", ")"],
["punctuation", "("], ["number", "1.23"], ["punctuation", ")"],
["punctuation", "("], ["number", "1."], ["punctuation", ")"],
["punctuation", "("], ["car", "foo"], ["number", "1"], ["punctuation", ")"],
["punctuation", "["], ["number", "1"], ["punctuation", "]"],
["punctuation", "("], ["number", "-1"], ["punctuation", ")"],
["punctuation", "("], ["number", "+1"], ["punctuation", ")"]
]
----------------------------------------------------
Checks for numbers.

View File

@ -0,0 +1,16 @@
()
( )
[]
(
----------------------------------------------------
[
["punctuation", "("], ["punctuation", ")"],
["punctuation", "("], ["punctuation", ")"],
["punctuation", "["], ["punctuation", "]"],
["punctuation", "("]
]
----------------------------------------------------
Checks for punctuation.

View File

@ -0,0 +1,17 @@
(
#'foo
'foo
)
----------------------------------------------------
[
["punctuation", "("],
["quoted-symbol", "#'foo"],
["quoted-symbol", "'foo"],
["punctuation", ")"]
]
----------------------------------------------------
Checks for quoted symbols.

View File

@ -0,0 +1,17 @@
(
,foo
,@foo
)
----------------------------------------------------
[
["punctuation", "("],
["splice", ",foo"],
["splice", ",@foo"],
["punctuation", ")"]
]
----------------------------------------------------
Checks for splices

View File

@ -0,0 +1,27 @@
(
""
"foo
bar"
"\"foo\""
"foo\tbar"
"`foo'"
"FOO."
)
----------------------------------------------------
[
["punctuation", "("],
["string", [ "\"\"" ]],
["string", [ "\"foo\r\nbar\"" ]],
["string", [ "\"\\\"foo\\\"\"" ]],
["string", [ "\"foo\\tbar\"" ]],
["string", [ "\"", ["symbol", "`foo'"], "\"" ]],
["string", [ "\"", ["argument", "FOO"], ".\"" ]],
["punctuation", ")"]
]
----------------------------------------------------
Checks for all string variations.