modeling.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. """
  2. pygments.lexers.modeling
  3. ~~~~~~~~~~~~~~~~~~~~~~~~
  4. Lexers for modeling languages.
  5. :copyright: Copyright 2006-2023 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 source code.
  18. .. versionadded:: 1.1
  19. """
  20. name = 'Modelica'
  21. url = 'http://www.modelica.org/'
  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. (r'[\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 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. (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|offset|multiplier)(\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. # Imaginary Literals
  306. (r'[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?i', Number.Float),
  307. (r'\.[0-9]+([eE][+-]?[0-9]+)?i', Number.Float),
  308. (r'[0-9]+i', Number.Float),
  309. # Real Literals
  310. (r'[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?', Number.Float),
  311. (r'\.[0-9]+([eE][+-]?[0-9]+)?', Number.Float),
  312. # Integer Literals
  313. (r'[0-9]+', Number.Integer),
  314. # Regular variable names
  315. (r'[A-Za-z]\w*\b', Name),
  316. # Assignment operators
  317. (r'<-|(?:\+|-|\.?/|\.?\*|=)?=|~', Operator),
  318. # Infix, prefix and postfix operators (and = )
  319. (r"\+|-|\.?\*|\.?/|\\|'|\.?\^|!=?|<=?|>=?|\|\||&&|%|\?|:|%/%|!", Operator),
  320. # Block delimiters
  321. (r'[{}]', Punctuation),
  322. # Distribution |
  323. (r'\|', Punctuation)
  324. ]
  325. }
  326. def analyse_text(text):
  327. if re.search(r'^\s*parameters\s*\{', text, re.M):
  328. return 1.0
  329. else:
  330. return 0.0