You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
13 KiB
369 lines
13 KiB
""" |
|
pygments.lexers.modeling |
|
~~~~~~~~~~~~~~~~~~~~~~~~ |
|
|
|
Lexers for modeling languages. |
|
|
|
:copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. |
|
:license: BSD, see LICENSE for details. |
|
""" |
|
|
|
import re |
|
|
|
from pygments.lexer import RegexLexer, include, bygroups, using, default |
|
from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ |
|
Number, Punctuation, Whitespace |
|
|
|
from pygments.lexers.html import HtmlLexer |
|
from pygments.lexers import _stan_builtins |
|
|
|
__all__ = ['ModelicaLexer', 'BugsLexer', 'JagsLexer', 'StanLexer'] |
|
|
|
|
|
class ModelicaLexer(RegexLexer): |
|
""" |
|
For Modelica source code. |
|
|
|
.. versionadded:: 1.1 |
|
""" |
|
name = 'Modelica' |
|
url = 'http://www.modelica.org/' |
|
aliases = ['modelica'] |
|
filenames = ['*.mo'] |
|
mimetypes = ['text/x-modelica'] |
|
|
|
flags = re.DOTALL | re.MULTILINE |
|
|
|
_name = r"(?:'(?:[^\\']|\\.)+'|[a-zA-Z_]\w*)" |
|
|
|
tokens = { |
|
'whitespace': [ |
|
(r'[\s\ufeff]+', Text), |
|
(r'//[^\n]*\n?', Comment.Single), |
|
(r'/\*.*?\*/', Comment.Multiline) |
|
], |
|
'root': [ |
|
include('whitespace'), |
|
(r'"', String.Double, 'string'), |
|
(r'[()\[\]{},;]+', Punctuation), |
|
(r'\.?[*^/+-]|\.|<>|[<>:=]=?', Operator), |
|
(r'\d+(\.?\d*[eE][-+]?\d+|\.\d*)', Number.Float), |
|
(r'\d+', Number.Integer), |
|
(r'(abs|acos|actualStream|array|asin|assert|AssertionLevel|atan|' |
|
r'atan2|backSample|Boolean|cardinality|cat|ceil|change|Clock|' |
|
r'Connections|cos|cosh|cross|delay|diagonal|div|edge|exp|' |
|
r'ExternalObject|fill|floor|getInstanceName|hold|homotopy|' |
|
r'identity|inStream|integer|Integer|interval|inverse|isPresent|' |
|
r'linspace|log|log10|matrix|max|min|mod|ndims|noClock|noEvent|' |
|
r'ones|outerProduct|pre|previous|product|Real|reinit|rem|rooted|' |
|
r'sample|scalar|semiLinear|shiftSample|sign|sin|sinh|size|skew|' |
|
r'smooth|spatialDistribution|sqrt|StateSelect|String|subSample|' |
|
r'sum|superSample|symmetric|tan|tanh|terminal|terminate|time|' |
|
r'transpose|vector|zeros)\b', Name.Builtin), |
|
(r'(algorithm|annotation|break|connect|constant|constrainedby|der|' |
|
r'discrete|each|else|elseif|elsewhen|encapsulated|enumeration|' |
|
r'equation|exit|expandable|extends|external|firstTick|final|flow|for|if|' |
|
r'import|impure|in|initial|inner|input|interval|loop|nondiscrete|outer|' |
|
r'output|parameter|partial|protected|public|pure|redeclare|' |
|
r'replaceable|return|stream|then|when|while)\b', |
|
Keyword.Reserved), |
|
(r'(and|not|or)\b', Operator.Word), |
|
(r'(block|class|connector|end|function|model|operator|package|' |
|
r'record|type)\b', Keyword.Reserved, 'class'), |
|
(r'(false|true)\b', Keyword.Constant), |
|
(r'within\b', Keyword.Reserved, 'package-prefix'), |
|
(_name, Name) |
|
], |
|
'class': [ |
|
include('whitespace'), |
|
(r'(function|record)\b', Keyword.Reserved), |
|
(r'(if|for|when|while)\b', Keyword.Reserved, '#pop'), |
|
(_name, Name.Class, '#pop'), |
|
default('#pop') |
|
], |
|
'package-prefix': [ |
|
include('whitespace'), |
|
(_name, Name.Namespace, '#pop'), |
|
default('#pop') |
|
], |
|
'string': [ |
|
(r'"', String.Double, '#pop'), |
|
(r'\\[\'"?\\abfnrtv]', String.Escape), |
|
(r'(?i)<\s*html\s*>([^\\"]|\\.)+?(<\s*/\s*html\s*>|(?="))', |
|
using(HtmlLexer)), |
|
(r'<|\\?[^"\\<]+', String.Double) |
|
] |
|
} |
|
|
|
|
|
class BugsLexer(RegexLexer): |
|
""" |
|
Pygments Lexer for OpenBugs and WinBugs |
|
models. |
|
|
|
.. versionadded:: 1.6 |
|
""" |
|
|
|
name = 'BUGS' |
|
aliases = ['bugs', 'winbugs', 'openbugs'] |
|
filenames = ['*.bug'] |
|
|
|
_FUNCTIONS = ( |
|
# Scalar functions |
|
'abs', 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctanh', |
|
'cloglog', 'cos', 'cosh', 'cumulative', 'cut', 'density', 'deviance', |
|
'equals', 'expr', 'gammap', 'ilogit', 'icloglog', 'integral', 'log', |
|
'logfact', 'loggam', 'logit', 'max', 'min', 'phi', 'post.p.value', |
|
'pow', 'prior.p.value', 'probit', 'replicate.post', 'replicate.prior', |
|
'round', 'sin', 'sinh', 'solution', 'sqrt', 'step', 'tan', 'tanh', |
|
'trunc', |
|
# Vector functions |
|
'inprod', 'interp.lin', 'inverse', 'logdet', 'mean', 'eigen.vals', |
|
'ode', 'prod', 'p.valueM', 'rank', 'ranked', 'replicate.postM', |
|
'sd', 'sort', 'sum', |
|
# Special |
|
'D', 'I', 'F', 'T', 'C') |
|
""" OpenBUGS built-in functions |
|
|
|
From http://www.openbugs.info/Manuals/ModelSpecification.html#ContentsAII |
|
|
|
This also includes |
|
|
|
- T, C, I : Truncation and censoring. |
|
``T`` and ``C`` are in OpenBUGS. ``I`` in WinBUGS. |
|
- D : ODE |
|
- F : Functional http://www.openbugs.info/Examples/Functionals.html |
|
|
|
""" |
|
|
|
_DISTRIBUTIONS = ('dbern', 'dbin', 'dcat', 'dnegbin', 'dpois', |
|
'dhyper', 'dbeta', 'dchisqr', 'ddexp', 'dexp', |
|
'dflat', 'dgamma', 'dgev', 'df', 'dggamma', 'dgpar', |
|
'dloglik', 'dlnorm', 'dlogis', 'dnorm', 'dpar', |
|
'dt', 'dunif', 'dweib', 'dmulti', 'ddirch', 'dmnorm', |
|
'dmt', 'dwish') |
|
""" OpenBUGS built-in distributions |
|
|
|
Functions from |
|
http://www.openbugs.info/Manuals/ModelSpecification.html#ContentsAI |
|
""" |
|
|
|
tokens = { |
|
'whitespace': [ |
|
(r"\s+", Text), |
|
], |
|
'comments': [ |
|
# Comments |
|
(r'#.*$', Comment.Single), |
|
], |
|
'root': [ |
|
# Comments |
|
include('comments'), |
|
include('whitespace'), |
|
# Block start |
|
(r'(model)(\s+)(\{)', |
|
bygroups(Keyword.Namespace, Text, Punctuation)), |
|
# Reserved Words |
|
(r'(for|in)(?![\w.])', Keyword.Reserved), |
|
# Built-in Functions |
|
(r'(%s)(?=\s*\()' |
|
% r'|'.join(_FUNCTIONS + _DISTRIBUTIONS), |
|
Name.Builtin), |
|
# Regular variable names |
|
(r'[A-Za-z][\w.]*', Name), |
|
# Number Literals |
|
(r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?', Number), |
|
# Punctuation |
|
(r'\[|\]|\(|\)|:|,|;', Punctuation), |
|
# Assignment operators |
|
# SLexer makes these tokens Operators. |
|
(r'<-|~', Operator), |
|
# Infix and prefix operators |
|
(r'\+|-|\*|/', Operator), |
|
# Block |
|
(r'[{}]', Punctuation), |
|
] |
|
} |
|
|
|
def analyse_text(text): |
|
if re.search(r"^\s*model\s*{", text, re.M): |
|
return 0.7 |
|
else: |
|
return 0.0 |
|
|
|
|
|
class JagsLexer(RegexLexer): |
|
""" |
|
Pygments Lexer for JAGS. |
|
|
|
.. versionadded:: 1.6 |
|
""" |
|
|
|
name = 'JAGS' |
|
aliases = ['jags'] |
|
filenames = ['*.jag', '*.bug'] |
|
|
|
# JAGS |
|
_FUNCTIONS = ( |
|
'abs', 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctanh', |
|
'cos', 'cosh', 'cloglog', |
|
'equals', 'exp', 'icloglog', 'ifelse', 'ilogit', 'log', 'logfact', |
|
'loggam', 'logit', 'phi', 'pow', 'probit', 'round', 'sin', 'sinh', |
|
'sqrt', 'step', 'tan', 'tanh', 'trunc', 'inprod', 'interp.lin', |
|
'logdet', 'max', 'mean', 'min', 'prod', 'sum', 'sd', 'inverse', |
|
'rank', 'sort', 't', 'acos', 'acosh', 'asin', 'asinh', 'atan', |
|
# Truncation/Censoring (should I include) |
|
'T', 'I') |
|
# Distributions with density, probability and quartile functions |
|
_DISTRIBUTIONS = tuple('[dpq]%s' % x for x in |
|
('bern', 'beta', 'dchiqsqr', 'ddexp', 'dexp', |
|
'df', 'gamma', 'gen.gamma', 'logis', 'lnorm', |
|
'negbin', 'nchisqr', 'norm', 'par', 'pois', 'weib')) |
|
# Other distributions without density and probability |
|
_OTHER_DISTRIBUTIONS = ( |
|
'dt', 'dunif', 'dbetabin', 'dbern', 'dbin', 'dcat', 'dhyper', |
|
'ddirch', 'dmnorm', 'dwish', 'dmt', 'dmulti', 'dbinom', 'dchisq', |
|
'dnbinom', 'dweibull', 'ddirich') |
|
|
|
tokens = { |
|
'whitespace': [ |
|
(r"\s+", Text), |
|
], |
|
'names': [ |
|
# Regular variable names |
|
(r'[a-zA-Z][\w.]*\b', Name), |
|
], |
|
'comments': [ |
|
# do not use stateful comments |
|
(r'(?s)/\*.*?\*/', Comment.Multiline), |
|
# Comments |
|
(r'#.*$', Comment.Single), |
|
], |
|
'root': [ |
|
# Comments |
|
include('comments'), |
|
include('whitespace'), |
|
# Block start |
|
(r'(model|data)(\s+)(\{)', |
|
bygroups(Keyword.Namespace, Text, Punctuation)), |
|
(r'var(?![\w.])', Keyword.Declaration), |
|
# Reserved Words |
|
(r'(for|in)(?![\w.])', Keyword.Reserved), |
|
# Builtins |
|
# Need to use lookahead because . is a valid char |
|
(r'(%s)(?=\s*\()' % r'|'.join(_FUNCTIONS |
|
+ _DISTRIBUTIONS |
|
+ _OTHER_DISTRIBUTIONS), |
|
Name.Builtin), |
|
# Names |
|
include('names'), |
|
# Number Literals |
|
(r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?', Number), |
|
(r'\[|\]|\(|\)|:|,|;', Punctuation), |
|
# Assignment operators |
|
(r'<-|~', Operator), |
|
# # JAGS includes many more than OpenBUGS |
|
(r'\+|-|\*|\/|\|\|[&]{2}|[<>=]=?|\^|%.*?%', Operator), |
|
(r'[{}]', Punctuation), |
|
] |
|
} |
|
|
|
def analyse_text(text): |
|
if re.search(r'^\s*model\s*\{', text, re.M): |
|
if re.search(r'^\s*data\s*\{', text, re.M): |
|
return 0.9 |
|
elif re.search(r'^\s*var', text, re.M): |
|
return 0.9 |
|
else: |
|
return 0.3 |
|
else: |
|
return 0 |
|
|
|
|
|
class StanLexer(RegexLexer): |
|
"""Pygments Lexer for Stan models. |
|
|
|
The Stan modeling language is specified in the *Stan Modeling Language |
|
User's Guide and Reference Manual, v2.17.0*, |
|
`pdf <https://github.com/stan-dev/stan/releases/download/v2.17.0/stan-reference-2.17.0.pdf>`__. |
|
|
|
.. versionadded:: 1.6 |
|
""" |
|
|
|
name = 'Stan' |
|
aliases = ['stan'] |
|
filenames = ['*.stan'] |
|
|
|
tokens = { |
|
'whitespace': [ |
|
(r"\s+", Text), |
|
], |
|
'comments': [ |
|
(r'(?s)/\*.*?\*/', Comment.Multiline), |
|
# Comments |
|
(r'(//|#).*$', Comment.Single), |
|
], |
|
'root': [ |
|
(r'"[^"]*"', String), |
|
# Comments |
|
include('comments'), |
|
# block start |
|
include('whitespace'), |
|
# Block start |
|
(r'(%s)(\s*)(\{)' % |
|
r'|'.join(('functions', 'data', r'transformed\s+?data', |
|
'parameters', r'transformed\s+parameters', |
|
'model', r'generated\s+quantities')), |
|
bygroups(Keyword.Namespace, Text, Punctuation)), |
|
# target keyword |
|
(r'target\s*\+=', Keyword), |
|
# Reserved Words |
|
(r'(%s)\b' % r'|'.join(_stan_builtins.KEYWORDS), Keyword), |
|
# Truncation |
|
(r'T(?=\s*\[)', Keyword), |
|
# Data types |
|
(r'(%s)\b' % r'|'.join(_stan_builtins.TYPES), Keyword.Type), |
|
# < should be punctuation, but elsewhere I can't tell if it is in |
|
# a range constraint |
|
(r'(<)(\s*)(upper|lower|offset|multiplier)(\s*)(=)', |
|
bygroups(Operator, Whitespace, Keyword, Whitespace, Punctuation)), |
|
(r'(,)(\s*)(upper)(\s*)(=)', |
|
bygroups(Punctuation, Whitespace, Keyword, Whitespace, Punctuation)), |
|
# Punctuation |
|
(r"[;,\[\]()]", Punctuation), |
|
# Builtin |
|
(r'(%s)(?=\s*\()' % '|'.join(_stan_builtins.FUNCTIONS), Name.Builtin), |
|
(r'(~)(\s*)(%s)(?=\s*\()' % '|'.join(_stan_builtins.DISTRIBUTIONS), |
|
bygroups(Operator, Whitespace, Name.Builtin)), |
|
# Special names ending in __, like lp__ |
|
(r'[A-Za-z]\w*__\b', Name.Builtin.Pseudo), |
|
(r'(%s)\b' % r'|'.join(_stan_builtins.RESERVED), Keyword.Reserved), |
|
# user-defined functions |
|
(r'[A-Za-z]\w*(?=\s*\()]', Name.Function), |
|
# Imaginary Literals |
|
(r'[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?i', Number.Float), |
|
(r'\.[0-9]+([eE][+-]?[0-9]+)?i', Number.Float), |
|
(r'[0-9]+i', Number.Float), |
|
# Real Literals |
|
(r'[0-9]+(\.[0-9]*)?([eE][+-]?[0-9]+)?', Number.Float), |
|
(r'\.[0-9]+([eE][+-]?[0-9]+)?', Number.Float), |
|
# Integer Literals |
|
(r'[0-9]+', Number.Integer), |
|
# Regular variable names |
|
(r'[A-Za-z]\w*\b', Name), |
|
# Assignment operators |
|
(r'<-|(?:\+|-|\.?/|\.?\*|=)?=|~', Operator), |
|
# Infix, prefix and postfix operators (and = ) |
|
(r"\+|-|\.?\*|\.?/|\\|'|\.?\^|!=?|<=?|>=?|\|\||&&|%|\?|:|%/%|!", Operator), |
|
# Block delimiters |
|
(r'[{}]', Punctuation), |
|
# Distribution | |
|
(r'\|', Punctuation) |
|
] |
|
} |
|
|
|
def analyse_text(text): |
|
if re.search(r'^\s*parameters\s*\{', text, re.M): |
|
return 1.0 |
|
else: |
|
return 0.0
|
|
|