Commit afd77ed13577b80018a6179420d9f638145b08d4

Michael Schmidt 2021-12-07T12:56:42

Stan: Added missing keywords and HOFs (#3238)

diff --git a/components/prism-stan.js b/components/prism-stan.js
index 43973be..cab2cfe 100644
--- a/components/prism-stan.js
+++ b/components/prism-stan.js
@@ -1,49 +1,65 @@
-// https://mc-stan.org/docs/2_24/reference-manual/bnf-grammars.html
+(function (Prism) {
 
-Prism.languages.stan = {
-	'comment': /\/\/.*|\/\*[\s\S]*?\*\/|#(?!include).*/,
-	'string': {
-		// String literals can contain spaces and any printable ASCII characters except for " and \
-		// https://mc-stan.org/docs/2_24/reference-manual/print-statements-section.html#string-literals
-		pattern: /"[\x20\x21\x23-\x5B\x5D-\x7E]*"/,
-		greedy: true
-	},
-	'directive': {
-		pattern: /^([ \t]*)#include\b.*/m,
-		lookbehind: true,
-		alias: 'property'
-	},
+	// https://mc-stan.org/docs/2_28/reference-manual/bnf-grammars.html
 
-	'function-arg': {
-		pattern: /(\b(?:algebra_solver|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect)\s*\(\s*)[a-zA-Z]\w*/,
-		lookbehind: true,
-		alias: 'function'
-	},
-	'constraint': {
-		pattern: /(\b(?:int|matrix|real|row_vector|vector)\s*)<[^<>]*>/,
-		lookbehind: true,
-		inside: {
-			'expression': {
-				pattern: /(=\s*)\S(?:\S|\s+(?!\s))*?(?=\s*(?:>$|,\s*\w+\s*=))/,
-				lookbehind: true,
-				inside: null // see below
+	var higherOrderFunctions = /\b(?:algebra_solver|algebra_solver_newton|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect|ode_(?:adams|bdf|ckrk|rk45)(?:_tol)?|ode_adjoint_tol_ctl|reduce_sum|reduce_sum_static)\b/;
+
+	Prism.languages.stan = {
+		'comment': /\/\/.*|\/\*[\s\S]*?\*\/|#(?!include).*/,
+		'string': {
+			// String literals can contain spaces and any printable ASCII characters except for " and \
+			// https://mc-stan.org/docs/2_24/reference-manual/print-statements-section.html#string-literals
+			pattern: /"[\x20\x21\x23-\x5B\x5D-\x7E]*"/,
+			greedy: true
+		},
+		'directive': {
+			pattern: /^([ \t]*)#include\b.*/m,
+			lookbehind: true,
+			alias: 'property'
+		},
+
+		'function-arg': {
+			pattern: RegExp(
+				'(' +
+				higherOrderFunctions.source +
+				/\s*\(\s*/.source +
+				')' +
+				/[a-zA-Z]\w*/.source
+			),
+			lookbehind: true,
+			alias: 'function'
+		},
+		'constraint': {
+			pattern: /(\b(?:int|matrix|real|row_vector|vector)\s*)<[^<>]*>/,
+			lookbehind: true,
+			inside: {
+				'expression': {
+					pattern: /(=\s*)\S(?:\S|\s+(?!\s))*?(?=\s*(?:>$|,\s*\w+\s*=))/,
+					lookbehind: true,
+					inside: null // see below
+				},
+				'property': /\b[a-z]\w*(?=\s*=)/i,
+				'operator': /=/,
+				'punctuation': /^<|>$|,/
+			}
+		},
+		'keyword': [
+			{
+				pattern: /\bdata(?=\s*\{)|\b(?:functions|generated|model|parameters|quantities|transformed)\b/,
+				alias: 'program-block'
 			},
-			'property': /\b[a-z]\w*(?=\s*=)/i,
-			'operator': /=/,
-			'punctuation': /^<|>$|,/
-		}
-	},
-	'keyword': [
-		/\b(?:break|cholesky_factor_corr|cholesky_factor_cov|continue|corr_matrix|cov_matrix|data|else|for|functions|generated|if|in|increment_log_prob|int|matrix|model|ordered|parameters|positive_ordered|print|quantities|real|reject|return|row_vector|simplex|target|transformed|unit_vector|vector|void|while)\b/,
-		// these are functions that are known to take another function as their first argument.
-		/\b(?:algebra_solver|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect)\b/
-	],
-	'function': /\b[a-z]\w*(?=\s*\()/i,
-	'number': /(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?\b/i,
-	'boolean': /\b(?:false|true)\b/,
+			/\b(?:array|break|cholesky_factor_corr|cholesky_factor_cov|complex|continue|corr_matrix|cov_matrix|data|else|for|if|in|increment_log_prob|int|matrix|ordered|positive_ordered|print|real|reject|return|row_vector|simplex|target|unit_vector|vector|void|while)\b/,
+			// these are functions that are known to take another function as their first argument.
+			higherOrderFunctions
+		],
+		'function': /\b[a-z]\w*(?=\s*\()/i,
+		'number': /(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:E[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,
+		'boolean': /\b(?:false|true)\b/,
+
+		'operator': /<-|\.[*/]=?|\|\|?|&&|[!=<>+\-*/]=?|['^%~?:]/,
+		'punctuation': /[()\[\]{},;]/
+	};
 
-	'operator': /<-|\.[*/]=?|\|\|?|&&|[!=<>+\-*/]=?|['^%~?:]/,
-	'punctuation': /[()\[\]{},;]/
-};
+	Prism.languages.stan.constraint.inside.expression.inside = Prism.languages.stan;
 
-Prism.languages.stan.constraint.inside.expression.inside = Prism.languages.stan;
+}(Prism));
diff --git a/components/prism-stan.min.js b/components/prism-stan.min.js
index 5d4f8a0..5db623f 100644
--- a/components/prism-stan.min.js
+++ b/components/prism-stan.min.js
@@ -1 +1 @@
-Prism.languages.stan={comment:/\/\/.*|\/\*[\s\S]*?\*\/|#(?!include).*/,string:{pattern:/"[\x20\x21\x23-\x5B\x5D-\x7E]*"/,greedy:!0},directive:{pattern:/^([ \t]*)#include\b.*/m,lookbehind:!0,alias:"property"},"function-arg":{pattern:/(\b(?:algebra_solver|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect)\s*\(\s*)[a-zA-Z]\w*/,lookbehind:!0,alias:"function"},constraint:{pattern:/(\b(?:int|matrix|real|row_vector|vector)\s*)<[^<>]*>/,lookbehind:!0,inside:{expression:{pattern:/(=\s*)\S(?:\S|\s+(?!\s))*?(?=\s*(?:>$|,\s*\w+\s*=))/,lookbehind:!0,inside:null},property:/\b[a-z]\w*(?=\s*=)/i,operator:/=/,punctuation:/^<|>$|,/}},keyword:[/\b(?:break|cholesky_factor_corr|cholesky_factor_cov|continue|corr_matrix|cov_matrix|data|else|for|functions|generated|if|in|increment_log_prob|int|matrix|model|ordered|parameters|positive_ordered|print|quantities|real|reject|return|row_vector|simplex|target|transformed|unit_vector|vector|void|while)\b/,/\b(?:algebra_solver|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect)\b/],function:/\b[a-z]\w*(?=\s*\()/i,number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,operator:/<-|\.[*/]=?|\|\|?|&&|[!=<>+\-*/]=?|['^%~?:]/,punctuation:/[()\[\]{},;]/},Prism.languages.stan.constraint.inside.expression.inside=Prism.languages.stan;
\ No newline at end of file
+!function(e){var r=/\b(?:algebra_solver|algebra_solver_newton|integrate_1d|integrate_ode|integrate_ode_bdf|integrate_ode_rk45|map_rect|ode_(?:adams|bdf|ckrk|rk45)(?:_tol)?|ode_adjoint_tol_ctl|reduce_sum|reduce_sum_static)\b/;e.languages.stan={comment:/\/\/.*|\/\*[\s\S]*?\*\/|#(?!include).*/,string:{pattern:/"[\x20\x21\x23-\x5B\x5D-\x7E]*"/,greedy:!0},directive:{pattern:/^([ \t]*)#include\b.*/m,lookbehind:!0,alias:"property"},"function-arg":{pattern:RegExp("("+r.source+"\\s*\\(\\s*)[a-zA-Z]\\w*"),lookbehind:!0,alias:"function"},constraint:{pattern:/(\b(?:int|matrix|real|row_vector|vector)\s*)<[^<>]*>/,lookbehind:!0,inside:{expression:{pattern:/(=\s*)\S(?:\S|\s+(?!\s))*?(?=\s*(?:>$|,\s*\w+\s*=))/,lookbehind:!0,inside:null},property:/\b[a-z]\w*(?=\s*=)/i,operator:/=/,punctuation:/^<|>$|,/}},keyword:[{pattern:/\bdata(?=\s*\{)|\b(?:functions|generated|model|parameters|quantities|transformed)\b/,alias:"program-block"},/\b(?:array|break|cholesky_factor_corr|cholesky_factor_cov|complex|continue|corr_matrix|cov_matrix|data|else|for|if|in|increment_log_prob|int|matrix|ordered|positive_ordered|print|real|reject|return|row_vector|simplex|target|unit_vector|vector|void|while)\b/,r],function:/\b[a-z]\w*(?=\s*\()/i,number:/(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:E[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,boolean:/\b(?:false|true)\b/,operator:/<-|\.[*/]=?|\|\|?|&&|[!=<>+\-*/]=?|['^%~?:]/,punctuation:/[()\[\]{},;]/},e.languages.stan.constraint.inside.expression.inside=e.languages.stan}(Prism);
\ No newline at end of file
diff --git a/tests/languages/stan/keyword_feature.test b/tests/languages/stan/keyword_feature.test
index fb1613a..1399418 100644
--- a/tests/languages/stan/keyword_feature.test
+++ b/tests/languages/stan/keyword_feature.test
@@ -1,6 +1,8 @@
+array
 break
 cholesky_factor_corr
 cholesky_factor_cov
+complex
 continue
 corr_matrix
 cov_matrix
@@ -33,18 +35,32 @@ void
 while
 
 algebra_solver
+algebra_solver_newton
 integrate_1d
 integrate_ode
 integrate_ode_bdf
 integrate_ode_rk45
 map_rect
+ode_adams
+ode_adams_tol
+ode_adjoint_tol_ctl
+ode_bdf
+ode_bdf_tol
+ode_ckrk
+ode_ckrk_tol
+ode_rk45
+ode_rk45_tol
+reduce_sum
+reduce_sum_static
 
 ----------------------------------------------------
 
 [
+	["keyword", "array"],
 	["keyword", "break"],
 	["keyword", "cholesky_factor_corr"],
 	["keyword", "cholesky_factor_cov"],
+	["keyword", "complex"],
 	["keyword", "continue"],
 	["keyword", "corr_matrix"],
 	["keyword", "cov_matrix"],
@@ -77,11 +93,23 @@ map_rect
 	["keyword", "while"],
 
 	["keyword", "algebra_solver"],
+	["keyword", "algebra_solver_newton"],
 	["keyword", "integrate_1d"],
 	["keyword", "integrate_ode"],
 	["keyword", "integrate_ode_bdf"],
 	["keyword", "integrate_ode_rk45"],
-	["keyword", "map_rect"]
+	["keyword", "map_rect"],
+	["keyword", "ode_adams"],
+	["keyword", "ode_adams_tol"],
+	["keyword", "ode_adjoint_tol_ctl"],
+	["keyword", "ode_bdf"],
+	["keyword", "ode_bdf_tol"],
+	["keyword", "ode_ckrk"],
+	["keyword", "ode_ckrk_tol"],
+	["keyword", "ode_rk45"],
+	["keyword", "ode_rk45_tol"],
+	["keyword", "reduce_sum"],
+	["keyword", "reduce_sum_static"]
 ]
 
 ----------------------------------------------------
diff --git a/tests/languages/stan/number_feature.test b/tests/languages/stan/number_feature.test
index 0d70a28..4741a87 100644
--- a/tests/languages/stan/number_feature.test
+++ b/tests/languages/stan/number_feature.test
@@ -1,6 +1,7 @@
 0
 1
 24567898765
+24_56_78_98_765
 
 0.0
 1.0
@@ -8,6 +9,11 @@
 2.7e3
 2E-5
 1.23e+3
+3.14i
+40e-3i
+1e10i
+0i
+1_2.3_4e5_6i
 
 ----------------------------------------------------
 
@@ -15,13 +21,19 @@
 	["number", "0"],
 	["number", "1"],
 	["number", "24567898765"],
+	["number", "24_56_78_98_765"],
 
 	["number", "0.0"],
 	["number", "1.0"],
 	["number", "3.14"],
 	["number", "2.7e3"],
 	["number", "2E-5"],
-	["number", "1.23e+3"]
+	["number", "1.23e+3"],
+	["number", "3.14i"],
+	["number", "40e-3i"],
+	["number", "1e10i"],
+	["number", "0i"],
+	["number", "1_2.3_4e5_6i"]
 ]
 
 ----------------------------------------------------
diff --git a/tests/languages/stan/program-block_feature.html.test b/tests/languages/stan/program-block_feature.html.test
new file mode 100644
index 0000000..1de0f53
--- /dev/null
+++ b/tests/languages/stan/program-block_feature.html.test
@@ -0,0 +1,76 @@
+functions {
+  // ... function declarations and definitions ...
+}
+data {
+  // ... declarations ...
+}
+transformed data {
+   // ... declarations ... statements ...
+}
+parameters {
+   // ... declarations ...
+}
+transformed parameters {
+   // ... declarations ... statements ...
+}
+model {
+   // ... declarations ... statements ...
+}
+generated quantities {
+   // ... declarations ... statements ...
+}
+
+// data-only quantifiers
+real foo(data real x) {
+  return x^2;
+}
+
+----------------------------------------------------
+
+<span class="token keyword program-block">functions</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... function declarations and definitions ...</span>
+<span class="token punctuation">}</span>
+<span class="token keyword program-block">data</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... declarations ...</span>
+<span class="token punctuation">}</span>
+<span class="token keyword program-block">transformed</span>
+<span class="token keyword program-block">data</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... declarations ... statements ...</span>
+<span class="token punctuation">}</span>
+<span class="token keyword program-block">parameters</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... declarations ...</span>
+<span class="token punctuation">}</span>
+<span class="token keyword program-block">transformed</span>
+<span class="token keyword program-block">parameters</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... declarations ... statements ...</span>
+<span class="token punctuation">}</span>
+<span class="token keyword program-block">model</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... declarations ... statements ...</span>
+<span class="token punctuation">}</span>
+<span class="token keyword program-block">generated</span>
+<span class="token keyword program-block">quantities</span>
+<span class="token punctuation">{</span>
+<span class="token comment">// ... declarations ... statements ...</span>
+<span class="token punctuation">}</span>
+
+<span class="token comment">// data-only quantifiers</span>
+<span class="token keyword">real</span>
+<span class="token function">foo</span>
+<span class="token punctuation">(</span>
+<span class="token keyword">data</span>
+<span class="token keyword">real</span>
+x
+<span class="token punctuation">)</span>
+<span class="token punctuation">{</span>
+<span class="token keyword">return</span>
+x
+<span class="token operator">^</span>
+<span class="token number">2</span>
+<span class="token punctuation">;</span>
+<span class="token punctuation">}</span>