modeling.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. """
  2. pygments.lexers.modeling
  3. ~~~~~~~~~~~~~~~~~~~~~~~~
  4. Lexers for modeling languages.
  5. :copyright: Copyright 2006-2021 by the Pygments team, see AUTHORS.
  6. :license: BSD, see LICENSE for details.
  7. """
  8. import re
  9. from pygments.lexer import RegexLexer, include, bygroups, using, default
  10. from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
  11. Number, Punctuation, Whitespace
  12. from pygments.lexers.html import HtmlLexer
  13. from pygments.lexers import _stan_builtins
  14. __all__ = ['ModelicaLexer', 'BugsLexer', 'JagsLexer', 'StanLexer']
  15. class ModelicaLexer(RegexLexer):
  16. """
  17. For `Modelica <http://www.modelica.org/>`_ source code.
  18. .. versionadded:: 1.1
  19. """
  20. name = 'Modelica'
  21. aliases = ['modelica']
  22. filenames = ['*.mo']
  23. mimetypes = ['text/x-modelica']
  24. flags = re.DOTALL | re.MULTILINE
  25. _name = r"(?:'(?:[^\\']|\\.)+'|[a-zA-Z_]\w*)"
  26. tokens = {
  27. 'whitespace': [
  28. (r'[\s\ufeff]+', Text),
  29. (r'//[^\n]*\n?', Comment.Single),
  30. (r'/\*.*?\*/', Comment.Multiline)
  31. ],
  32. 'root': [
  33. include('whitespace'),
  34. (r'"', String.Double, 'string'),
  35. (r'[()\[\]{},;]+', Punctuation),
  36. (r'\.?[*^/+-]|\.|<>|[<>:=]=?', Operator),
  37. (r'\d+(\.?\d*[eE][-+]?\d+|\.\d*)', Number.Float),
  38. (r'\d+', Number.Integer),
  39. (r'(abs|acos|actualStream|array|asin|assert|AssertionLevel|atan|'
  40. r'atan2|backSample|Boolean|cardinality|cat|ceil|change|Clock|'
  41. r'Connections|cos|cosh|cross|delay|diagonal|div|edge|exp|'
  42. r'ExternalObject|fill|floor|getInstanceName|hold|homotopy|'
  43. r'identity|inStream|integer|Integer|interval|inverse|isPresent|'
  44. r'linspace|log|log10|matrix|max|min|mod|ndims|noClock|noEvent|'
  45. r'ones|outerProduct|pre|previous|product|Real|reinit|rem|rooted|'
  46. r'sample|scalar|semiLinear|shiftSample|sign|sin|sinh|size|skew|'
  47. r'smooth|spatialDistribution|sqrt|StateSelect|String|subSample|'
  48. r'sum|superSample|symmetric|tan|tanh|terminal|terminate|time|'
  49. r'transpose|vector|zeros)\b', Name.Builtin),
  50. (r'(algorithm|annotation|break|connect|constant|constrainedby|der|'
  51. r'discrete|each|else|elseif|elsewhen|encapsulated|enumeration|'
  52. r'equation|exit|expandable|extends|external|firstTick|final|flow|for|if|'
  53. r'import|impure|in|initial|inner|input|interval|loop|nondiscrete|outer|'
  54. r'output|parameter|partial|protected|public|pure|redeclare|'
  55. r'replaceable|return|stream|then|when|while)\b',
  56. Keyword.Reserved),
  57. (r'(and|not|or)\b', Operator.Word),
  58. (r'(block|class|connector|end|function|model|operator|package|'
  59. r'record|type)\b', Keyword.Reserved, 'class'),
  60. (r'(false|true)\b', Keyword.Constant),
  61. (r'within\b', Keyword.Reserved, 'package-prefix'),
  62. (_name, Name)
  63. ],
  64. 'class': [
  65. include('whitespace'),
  66. (r'(function|record)\b', Keyword.Reserved),
  67. (r'(if|for|when|while)\b', Keyword.Reserved, '#pop'),
  68. (_name, Name.Class, '#pop'),
  69. default('#pop')
  70. ],
  71. 'package-prefix': [
  72. include('whitespace'),
  73. (_name, Name.Namespace, '#pop'),
  74. default('#pop')
  75. ],
  76. 'string': [
  77. (r'"', String.Double, '#pop'),
  78. (r'\\[\'"?\\abfnrtv]', String.Escape),
  79. (r'(?i)<\s*html\s*>([^\\"]|\\.)+?(<\s*/\s*html\s*>|(?="))',
  80. using(HtmlLexer)),
  81. (r'<|\\?[^"\\<]+', String.Double)
  82. ]
  83. }
  84. class BugsLexer(RegexLexer):
  85. """
  86. Pygments Lexer for `OpenBugs <http://www.openbugs.net/>`_ and WinBugs
  87. models.
  88. .. versionadded:: 1.6
  89. """
  90. name = 'BUGS'
  91. aliases = ['bugs', 'winbugs', 'openbugs']
  92. filenames = ['*.bug']
  93. _FUNCTIONS = (
  94. # Scalar functions
  95. 'abs', 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctanh',
  96. 'cloglog', 'cos', 'cosh', 'cumulative', 'cut', 'density', 'deviance',
  97. 'equals', 'expr', 'gammap', 'ilogit', 'icloglog', 'integral', 'log',
  98. 'logfact', 'loggam', 'logit', 'max', 'min', 'phi', 'post.p.value',
  99. 'pow', 'prior.p.value', 'probit', 'replicate.post', 'replicate.prior',
  100. 'round', 'sin', 'sinh', 'solution', 'sqrt', 'step', 'tan', 'tanh',
  101. 'trunc',
  102. # Vector functions
  103. 'inprod', 'interp.lin', 'inverse', 'logdet', 'mean', 'eigen.vals',
  104. 'ode', 'prod', 'p.valueM', 'rank', 'ranked', 'replicate.postM',
  105. 'sd', 'sort', 'sum',
  106. # Special
  107. 'D', 'I', 'F', 'T', 'C')
  108. """ OpenBUGS built-in functions
  109. From http://www.openbugs.info/Manuals/ModelSpecification.html#ContentsAII
  110. This also includes
  111. - T, C, I : Truncation and censoring.
  112. ``T`` and ``C`` are in OpenBUGS. ``I`` in WinBUGS.
  113. - D : ODE
  114. - F : Functional http://www.openbugs.info/Examples/Functionals.html
  115. """
  116. _DISTRIBUTIONS = ('dbern', 'dbin', 'dcat', 'dnegbin', 'dpois',
  117. 'dhyper', 'dbeta', 'dchisqr', 'ddexp', 'dexp',
  118. 'dflat', 'dgamma', 'dgev', 'df', 'dggamma', 'dgpar',
  119. 'dloglik', 'dlnorm', 'dlogis', 'dnorm', 'dpar',
  120. 'dt', 'dunif', 'dweib', 'dmulti', 'ddirch', 'dmnorm',
  121. 'dmt', 'dwish')
  122. """ OpenBUGS built-in distributions
  123. Functions from
  124. http://www.openbugs.info/Manuals/ModelSpecification.html#ContentsAI
  125. """
  126. tokens = {
  127. 'whitespace': [
  128. (r"\s+", Text),
  129. ],
  130. 'comments': [
  131. # Comments
  132. (r'#.*$', Comment.Single),
  133. ],
  134. 'root': [
  135. # Comments
  136. include('comments'),
  137. include('whitespace'),
  138. # Block start
  139. (r'(model)(\s+)(\{)',
  140. bygroups(Keyword.Namespace, Text, Punctuation)),
  141. # Reserved Words
  142. (r'(for|in)(?![\w.])', Keyword.Reserved),
  143. # Built-in Functions
  144. (r'(%s)(?=\s*\()'
  145. % r'|'.join(_FUNCTIONS + _DISTRIBUTIONS),
  146. Name.Builtin),
  147. # Regular variable names
  148. (r'[A-Za-z][\w.]*', Name),
  149. # Number Literals
  150. (r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?', Number),
  151. # Punctuation
  152. (r'\[|\]|\(|\)|:|,|;', Punctuation),
  153. # Assignment operators
  154. # SLexer makes these tokens Operators.
  155. (r'<-|~', Operator),
  156. # Infix and prefix operators
  157. (r'\+|-|\*|/', Operator),
  158. # Block
  159. (r'[{}]', Punctuation),
  160. ]
  161. }
  162. def analyse_text(text):
  163. if re.search(r"^\s*model\s*{", text, re.M):
  164. return 0.7
  165. else:
  166. return 0.0
  167. class JagsLexer(RegexLexer):
  168. """
  169. Pygments Lexer for JAGS.
  170. .. versionadded:: 1.6
  171. """
  172. name = 'JAGS'
  173. aliases = ['jags']
  174. filenames = ['*.jag', '*.bug']
  175. # JAGS
  176. _FUNCTIONS = (
  177. 'abs', 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctanh',
  178. 'cos', 'cosh', 'cloglog',
  179. 'equals', 'exp', 'icloglog', 'ifelse', 'ilogit', 'log', 'logfact',
  180. 'loggam', 'logit', 'phi', 'pow', 'probit', 'round', 'sin', 'sinh',
  181. 'sqrt', 'step', 'tan', 'tanh', 'trunc', 'inprod', 'interp.lin',
  182. 'logdet', 'max', 'mean', 'min', 'prod', 'sum', 'sd', 'inverse',
  183. 'rank', 'sort', 't', 'acos', 'acosh', 'asin', 'asinh', 'atan',
  184. # Truncation/Censoring (should I include)
  185. 'T', 'I')
  186. # Distributions with density, probability and quartile functions
  187. _DISTRIBUTIONS = tuple('[dpq]%s' % x for x in
  188. ('bern', 'beta', 'dchiqsqr', 'ddexp', 'dexp',
  189. 'df', 'gamma', 'gen.gamma', 'logis', 'lnorm',
  190. 'negbin', 'nchisqr', 'norm', 'par', 'pois', 'weib'))
  191. # Other distributions without density and probability
  192. _OTHER_DISTRIBUTIONS = (
  193. 'dt', 'dunif', 'dbetabin', 'dbern', 'dbin', 'dcat', 'dhyper',
  194. 'ddirch', 'dmnorm', 'dwish', 'dmt', 'dmulti', 'dbinom', 'dchisq',
  195. 'dnbinom', 'dweibull', 'ddirich')
  196. tokens = {
  197. 'whitespace': [
  198. (r"\s+", Text),
  199. ],
  200. 'names': [
  201. # Regular variable names
  202. (r'[a-zA-Z][\w.]*\b', Name),
  203. ],
  204. 'comments': [
  205. # do not use stateful comments
  206. (r'(?s)/\*.*?\*/', Comment.Multiline),
  207. # Comments
  208. (r'#.*$', Comment.Single),
  209. ],
  210. 'root': [
  211. # Comments
  212. include('comments'),
  213. include('whitespace'),
  214. # Block start
  215. (r'(model|data)(\s+)(\{)',
  216. bygroups(Keyword.Namespace, Text, Punctuation)),
  217. (r'var(?![\w.])', Keyword.Declaration),
  218. # Reserved Words
  219. (r'(for|in)(?![\w.])', Keyword.Reserved),
  220. # Builtins
  221. # Need to use lookahead because . is a valid char
  222. (r'(%s)(?=\s*\()' % r'|'.join(_FUNCTIONS
  223. + _DISTRIBUTIONS
  224. + _OTHER_DISTRIBUTIONS),
  225. Name.Builtin),
  226. # Names
  227. include('names'),
  228. # Number Literals
  229. (r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?', Number),
  230. (r'\[|\]|\(|\)|:|,|;', Punctuation),
  231. # Assignment operators
  232. (r'<-|~', Operator),
  233. # # JAGS includes many more than OpenBUGS
  234. (r'\+|-|\*|\/|\|\|[&]{2}|[<>=]=?|\^|%.*?%', Operator),
  235. (r'[{}]', Punctuation),
  236. ]
  237. }
  238. def analyse_text(text):
  239. if re.search(r'^\s*model\s*\{', text, re.M):
  240. if re.search(r'^\s*data\s*\{', text, re.M):
  241. return 0.9
  242. elif re.search(r'^\s*var', text, re.M):
  243. return 0.9
  244. else:
  245. return 0.3
  246. else:
  247. return 0
  248. class StanLexer(RegexLexer):
  249. """Pygments Lexer for Stan models.
  250. The Stan modeling language is specified in the *Stan Modeling Language
  251. User's Guide and Reference Manual, v2.17.0*,
  252. `pdf <https://github.com/stan-dev/stan/releases/download/v2.17.0/stan-reference-2.17.0.pdf>`__.
  253. .. versionadded:: 1.6
  254. """
  255. name = 'Stan'
  256. aliases = ['stan']
  257. filenames = ['*.stan']
  258. tokens = {
  259. 'whitespace': [
  260. (r"\s+", Text),
  261. ],
  262. 'comments': [
  263. (r'(?s)/\*.*?\*/', Comment.Multiline),
  264. # Comments
  265. (r'(//|#).*$', Comment.Single),
  266. ],
  267. 'root': [
  268. # Stan is more restrictive on strings than this regex
  269. (r'"[^"]*"', String),
  270. # Comments
  271. include('comments'),
  272. # block start
  273. include('whitespace'),
  274. # Block start
  275. (r'(%s)(\s*)(\{)' %
  276. r'|'.join(('functions', 'data', r'transformed\s+?data',
  277. 'parameters', r'transformed\s+parameters',
  278. 'model', r'generated\s+quantities')),
  279. bygroups(Keyword.Namespace, Text, Punctuation)),
  280. # target keyword
  281. (r'target\s*\+=', Keyword),
  282. # Reserved Words
  283. (r'(%s)\b' % r'|'.join(_stan_builtins.KEYWORDS), Keyword),
  284. # Truncation
  285. (r'T(?=\s*\[)', Keyword),
  286. # Data types
  287. (r'(%s)\b' % r'|'.join(_stan_builtins.TYPES), Keyword.Type),
  288. # < should be punctuation, but elsewhere I can't tell if it is in
  289. # a range constraint
  290. (r'(<)(\s*)(upper|lower)(\s*)(=)',
  291. bygroups(Operator, Whitespace, Keyword, Whitespace, Punctuation)),
  292. (r'(,)(\s*)(upper)(\s*)(=)',
  293. bygroups(Punctuation, Whitespace, Keyword, Whitespace, Punctuation)),
  294. # Punctuation
  295. (r"[;,\[\]()]", Punctuation),
  296. # Builtin
  297. (r'(%s)(?=\s*\()' % '|'.join(_stan_builtins.FUNCTIONS), Name.Builtin),
  298. (r'(~)(\s*)(%s)(?=\s*\()' % '|'.join(_stan_builtins.DISTRIBUTIONS),
  299. bygroups(Operator, Whitespace, Name.Builtin)),
  300. # Special names ending in __, like lp__
  301. (r'[A-Za-z]\w*__\b', Name.Builtin.Pseudo),
  302. (r'(%s)\b' % r'|'.join(_stan_builtins.RESERVED), Keyword.Reserved),
  303. # user-defined functions
  304. (r'[A-Za-z]\w*(?=\s*\()]', Name.Function),
  305. # Regular variable names
  306. (r'[A-Za-z]\w*\b', Name),
  307. # Real Literals
  308. (r'[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?', Number.Float),
  309. (r'\.[0-9]+([eE][+-]?[0-9]+)?', Number.Float),
  310. # Integer Literals
  311. (r'[0-9]+', Number.Integer),
  312. # Assignment operators
  313. (r'<-|(?:\+|-|\.?/|\.?\*|=)?=|~', Operator),
  314. # Infix, prefix and postfix operators (and = )
  315. (r"\+|-|\.?\*|\.?/|\\|'|\^|!=?|<=?|>=?|\|\||&&|%|\?|:", Operator),
  316. # Block delimiters
  317. (r'[{}]', Punctuation),
  318. # Distribution |
  319. (r'\|', Punctuation)
  320. ]
  321. }
  322. def analyse_text(text):
  323. if re.search(r'^\s*parameters\s*\{', text, re.M):
  324. return 1.0
  325. else:
  326. return 0.0