modeling.py 13 KB

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