1""" 
    2    pygments.lexers.prolog 
    3    ~~~~~~~~~~~~~~~~~~~~~~ 
    4 
    5    Lexers for Prolog and Prolog-like languages. 
    6 
    7    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. 
    8    :license: BSD, see LICENSE for details. 
    9""" 
    10 
    11import re 
    12 
    13from pygments.lexer import RegexLexer, bygroups 
    14from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ 
    15    Number, Punctuation 
    16 
    17__all__ = ['PrologLexer', 'LogtalkLexer'] 
    18 
    19 
    20class PrologLexer(RegexLexer): 
    21    """ 
    22    Lexer for Prolog files. 
    23    """ 
    24    name = 'Prolog' 
    25    aliases = ['prolog'] 
    26    filenames = ['*.ecl', '*.prolog', '*.pro', '*.pl'] 
    27    mimetypes = ['text/x-prolog'] 
    28    url = 'https://en.wikipedia.org/wiki/Prolog' 
    29    version_added = '' 
    30 
    31    tokens = { 
    32        'root': [ 
    33            (r'/\*', Comment.Multiline, 'nested-comment'), 
    34            (r'%.*', Comment.Single), 
    35            # character literal 
    36            (r'0\'.', String.Char), 
    37            (r'0b[01]+', Number.Bin), 
    38            (r'0o[0-7]+', Number.Oct), 
    39            (r'0x[0-9a-fA-F]+', Number.Hex), 
    40            # literal with prepended base 
    41            (r'\d\d?\'[a-zA-Z0-9]+', Number.Integer), 
    42            (r'(\d+\.\d*|\d*\.\d+)([eE][+-]?[0-9]+)?', Number.Float), 
    43            (r'\d+', Number.Integer), 
    44            (r'[\[\](){}|.,;!]', Punctuation), 
    45            (r':-|-->', Punctuation), 
    46            (r'"(?:\\x[0-9a-fA-F]+\\|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|' 
    47             r'\\[0-7]+\\|\\["\\abcefnrstv]|[^\\"])*"', String.Double), 
    48            (r"'(?:''|[^'])*'", String.Atom),  # quoted atom 
    49            # Needs to not be followed by an atom. 
    50            # (r'=(?=\s|[a-zA-Z\[])', Operator), 
    51            (r'is\b', Operator), 
    52            (r'(<|>|=<|>=|==|=:=|=|/|//|\*|\+|-)(?=\s|[a-zA-Z0-9\[])', 
    53             Operator), 
    54            (r'(mod|div|not)\b', Operator), 
    55            (r'_', Keyword),  # The don't-care variable 
    56            (r'([a-z]+)(:)', bygroups(Name.Namespace, Punctuation)), 
    57            (r'([a-z\u00c0-\u1fff\u3040-\ud7ff\ue000-\uffef]' 
    58             r'[\w$\u00c0-\u1fff\u3040-\ud7ff\ue000-\uffef]*)' 
    59             r'(\s*)(:-|-->)', 
    60             bygroups(Name.Function, Text, Operator)),  # function defn 
    61            (r'([a-z\u00c0-\u1fff\u3040-\ud7ff\ue000-\uffef]' 
    62             r'[\w$\u00c0-\u1fff\u3040-\ud7ff\ue000-\uffef]*)' 
    63             r'(\s*)(\()', 
    64             bygroups(Name.Function, Text, Punctuation)), 
    65            (r'[a-z\u00c0-\u1fff\u3040-\ud7ff\ue000-\uffef]' 
    66             r'[\w$\u00c0-\u1fff\u3040-\ud7ff\ue000-\uffef]*', 
    67             String.Atom),  # atom, characters 
    68            # This one includes ! 
    69            (r'[#&*+\-./:<=>?@\\^~\u00a1-\u00bf\u2010-\u303f]+', 
    70             String.Atom),  # atom, graphics 
    71            (r'[A-Z_]\w*', Name.Variable), 
    72            (r'\s+|[\u2000-\u200f\ufff0-\ufffe\uffef]', Text), 
    73        ], 
    74        'nested-comment': [ 
    75            (r'\*/', Comment.Multiline, '#pop'), 
    76            (r'/\*', Comment.Multiline, '#push'), 
    77            (r'[^*/]+', Comment.Multiline), 
    78            (r'[*/]', Comment.Multiline), 
    79        ], 
    80    } 
    81 
    82    def analyse_text(text): 
    83        """Competes with IDL and Visual Prolog on *.pro""" 
    84        if ':-' in text: 
    85            # Visual Prolog also uses :- 
    86            return 0.5 
    87        else: 
    88            return 0 
    89 
    90 
    91class LogtalkLexer(RegexLexer): 
    92    """ 
    93    For Logtalk source code. 
    94    """ 
    95 
    96    name = 'Logtalk' 
    97    url = 'http://logtalk.org/' 
    98    aliases = ['logtalk'] 
    99    filenames = ['*.lgt', '*.logtalk'] 
    100    mimetypes = ['text/x-logtalk'] 
    101    version_added = '0.10' 
    102 
    103    tokens = { 
    104        'root': [ 
    105            # Directives 
    106            (r'^\s*:-\s', Punctuation, 'directive'), 
    107            # Comments 
    108            (r'%.*?\n', Comment), 
    109            (r'/\*(.|\n)*?\*/', Comment), 
    110            # Whitespace 
    111            (r'\n', Text), 
    112            (r'\s+', Text), 
    113            # Numbers 
    114            (r"0'[\\]?.", Number), 
    115            (r'0b[01]+', Number.Bin), 
    116            (r'0o[0-7]+', Number.Oct), 
    117            (r'0x[0-9a-fA-F]+', Number.Hex), 
    118            (r'\d+\.?\d*((e|E)(\+|-)?\d+)?', Number), 
    119            # Variables 
    120            (r'([A-Z_][a-zA-Z0-9_]*)', Name.Variable), 
    121            # Event handlers 
    122            (r'(after|before)(?=[(])', Keyword), 
    123            # Message forwarding handler 
    124            (r'forward(?=[(])', Keyword), 
    125            # Execution-context methods 
    126            (r'(context|parameter|this|se(lf|nder))(?=[(])', Keyword), 
    127            # Reflection 
    128            (r'(current_predicate|predicate_property)(?=[(])', Keyword), 
    129            # DCGs and term expansion 
    130            (r'(expand_(goal|term)|(goal|term)_expansion|phrase)(?=[(])', Keyword), 
    131            # Entity 
    132            (r'(abolish|c(reate|urrent))_(object|protocol|category)(?=[(])', Keyword), 
    133            (r'(object|protocol|category)_property(?=[(])', Keyword), 
    134            # Entity relations 
    135            (r'co(mplements_object|nforms_to_protocol)(?=[(])', Keyword), 
    136            (r'extends_(object|protocol|category)(?=[(])', Keyword), 
    137            (r'imp(lements_protocol|orts_category)(?=[(])', Keyword), 
    138            (r'(instantiat|specializ)es_class(?=[(])', Keyword), 
    139            # Events 
    140            (r'(current_event|(abolish|define)_events)(?=[(])', Keyword), 
    141            # Flags 
    142            (r'(create|current|set)_logtalk_flag(?=[(])', Keyword), 
    143            # Compiling, loading, and library paths 
    144            (r'logtalk_(compile|l(ibrary_path|oad|oad_context)|make(_target_action)?)(?=[(])', Keyword), 
    145            (r'\blogtalk_make\b', Keyword), 
    146            # Database 
    147            (r'(clause|retract(all)?)(?=[(])', Keyword), 
    148            (r'a(bolish|ssert(a|z))(?=[(])', Keyword), 
    149            # Control constructs 
    150            (r'(ca(ll|tch)|throw)(?=[(])', Keyword), 
    151            (r'(fa(il|lse)|true|(instantiation|system)_error)\b', Keyword), 
    152            (r'(uninstantiation|type|domain|existence|permission|representation|evaluation|resource|syntax)_error(?=[(])', Keyword), 
    153            # All solutions 
    154            (r'((bag|set)of|f(ind|or)all)(?=[(])', Keyword), 
    155            # Multi-threading predicates 
    156            (r'threaded(_(ca(ll|ncel)|once|ignore|exit|peek|wait|notify))?(?=[(])', Keyword), 
    157            # Engine predicates 
    158            (r'threaded_engine(_(create|destroy|self|next|next_reified|yield|post|fetch))?(?=[(])', Keyword), 
    159            # Term unification 
    160            (r'(subsumes_term|unify_with_occurs_check)(?=[(])', Keyword), 
    161            # Term creation and decomposition 
    162            (r'(functor|arg|copy_term|numbervars|term_variables)(?=[(])', Keyword), 
    163            # Evaluable functors 
    164            (r'(div|rem|m(ax|in|od)|abs|sign)(?=[(])', Keyword), 
    165            (r'float(_(integer|fractional)_part)?(?=[(])', Keyword), 
    166            (r'(floor|t(an|runcate)|round|ceiling)(?=[(])', Keyword), 
    167            # Other arithmetic functors 
    168            (r'(cos|a(cos|sin|tan|tan2)|exp|log|s(in|qrt)|xor)(?=[(])', Keyword), 
    169            # Term testing 
    170            (r'(var|atom(ic)?|integer|float|c(allable|ompound)|n(onvar|umber)|ground|acyclic_term)(?=[(])', Keyword), 
    171            # Term comparison 
    172            (r'compare(?=[(])', Keyword), 
    173            # Stream selection and control 
    174            (r'(curren|se)t_(in|out)put(?=[(])', Keyword), 
    175            (r'(open|close)(?=[(])', Keyword), 
    176            (r'flush_output(?=[(])', Keyword), 
    177            (r'(at_end_of_stream|flush_output)\b', Keyword), 
    178            (r'(stream_property|at_end_of_stream|set_stream_position)(?=[(])', Keyword), 
    179            # Character and byte input/output 
    180            (r'(nl|(get|peek|put)_(byte|c(har|ode)))(?=[(])', Keyword), 
    181            (r'\bnl\b', Keyword), 
    182            # Term input/output 
    183            (r'read(_term)?(?=[(])', Keyword), 
    184            (r'write(q|_(canonical|term))?(?=[(])', Keyword), 
    185            (r'(current_)?op(?=[(])', Keyword), 
    186            (r'(current_)?char_conversion(?=[(])', Keyword), 
    187            # Atomic term processing 
    188            (r'atom_(length|c(hars|o(ncat|des)))(?=[(])', Keyword), 
    189            (r'(char_code|sub_atom)(?=[(])', Keyword), 
    190            (r'number_c(har|ode)s(?=[(])', Keyword), 
    191            # Implementation defined hooks functions 
    192            (r'(se|curren)t_prolog_flag(?=[(])', Keyword), 
    193            (r'\bhalt\b', Keyword), 
    194            (r'halt(?=[(])', Keyword), 
    195            # Message sending operators 
    196            (r'(::|:|\^\^)', Operator), 
    197            # External call 
    198            (r'[{}]', Keyword), 
    199            # Logic and control 
    200            (r'(ignore|once)(?=[(])', Keyword), 
    201            (r'\brepeat\b', Keyword), 
    202            # Sorting 
    203            (r'(key)?sort(?=[(])', Keyword), 
    204            # Bitwise functors 
    205            (r'(>>|<<|/\\|\\\\|\\)', Operator), 
    206            # Predicate aliases 
    207            (r'\bas\b', Operator), 
    208            # Arithmetic evaluation 
    209            (r'\bis\b', Keyword), 
    210            # Arithmetic comparison 
    211            (r'(=:=|=\\=|<|=<|>=|>)', Operator), 
    212            # Term creation and decomposition 
    213            (r'=\.\.', Operator), 
    214            # Term unification 
    215            (r'(=|\\=)', Operator), 
    216            # Term comparison 
    217            (r'(==|\\==|@=<|@<|@>=|@>)', Operator), 
    218            # Evaluable functors 
    219            (r'(//|[-+*/])', Operator), 
    220            (r'\b(e|pi|div|mod|rem)\b', Operator), 
    221            # Other arithmetic functors 
    222            (r'\b\*\*\b', Operator), 
    223            # DCG rules 
    224            (r'-->', Operator), 
    225            # Control constructs 
    226            (r'([!;]|->)', Operator), 
    227            # Logic and control 
    228            (r'\\+', Operator), 
    229            # Mode operators 
    230            (r'[?@]', Operator), 
    231            # Existential quantifier 
    232            (r'\^', Operator), 
    233            # Punctuation 
    234            (r'[()\[\],.|]', Text), 
    235            # Atoms 
    236            (r"[a-z][a-zA-Z0-9_]*", Text), 
    237            (r"'", String, 'quoted_atom'), 
    238            # Double-quoted terms 
    239            (r'"', String, 'double_quoted_term'), 
    240        ], 
    241 
    242        'quoted_atom': [ 
    243            (r"''", String), 
    244            (r"'", String, '#pop'), 
    245            (r'\\([\\abfnrtv"\']|(x[a-fA-F0-9]+|[0-7]+)\\)', String.Escape), 
    246            (r"[^\\'\n]+", String), 
    247            (r'\\', String), 
    248        ], 
    249 
    250        'double_quoted_term': [ 
    251            (r'""', String), 
    252            (r'"', String, '#pop'), 
    253            (r'\\([\\abfnrtv"\']|(x[a-fA-F0-9]+|[0-7]+)\\)', String.Escape), 
    254            (r'[^\\"\n]+', String), 
    255            (r'\\', String), 
    256        ], 
    257 
    258        'directive': [ 
    259            # Conditional compilation directives 
    260            (r'(el)?if(?=[(])', Keyword, 'root'), 
    261            (r'(e(lse|ndif))(?=[.])', Keyword, 'root'), 
    262            # Entity directives 
    263            (r'(category|object|protocol)(?=[(])', Keyword, 'entityrelations'), 
    264            (r'(end_(category|object|protocol))(?=[.])', Keyword, 'root'), 
    265            # Predicate scope directives 
    266            (r'(public|protected|private)(?=[(])', Keyword, 'root'), 
    267            # Other directives 
    268            (r'e(n(coding|sure_loaded)|xport)(?=[(])', Keyword, 'root'), 
    269            (r'in(clude|itialization|fo)(?=[(])', Keyword, 'root'), 
    270            (r'(built_in|dynamic|synchronized|threaded)(?=[.])', Keyword, 'root'), 
    271            (r'(alias|d(ynamic|iscontiguous)|m(eta_(non_terminal|predicate)|ode|ultifile)|s(et_(logtalk|prolog)_flag|ynchronized))(?=[(])', Keyword, 'root'), 
    272            (r'op(?=[(])', Keyword, 'root'), 
    273            (r'(c(alls|oinductive)|module|reexport|use(s|_module))(?=[(])', Keyword, 'root'), 
    274            (r'[a-z][a-zA-Z0-9_]*(?=[(])', Text, 'root'), 
    275            (r'[a-z][a-zA-Z0-9_]*(?=[.])', Text, 'root'), 
    276        ], 
    277 
    278        'entityrelations': [ 
    279            (r'(complements|extends|i(nstantiates|mp(lements|orts))|specializes)(?=[(])', Keyword), 
    280            # Numbers 
    281            (r"0'[\\]?.", Number), 
    282            (r'0b[01]+', Number.Bin), 
    283            (r'0o[0-7]+', Number.Oct), 
    284            (r'0x[0-9a-fA-F]+', Number.Hex), 
    285            (r'\d+\.?\d*((e|E)(\+|-)?\d+)?', Number), 
    286            # Variables 
    287            (r'([A-Z_][a-zA-Z0-9_]*)', Name.Variable), 
    288            # Atoms 
    289            (r"[a-z][a-zA-Z0-9_]*", Text), 
    290            (r"'", String, 'quoted_atom'), 
    291            # Double-quoted terms 
    292            (r'"', String, 'double_quoted_term'), 
    293            # End of entity-opening directive 
    294            (r'([)]\.)', Text, 'root'), 
    295            # Scope operator 
    296            (r'(::)', Operator), 
    297            # Punctuation 
    298            (r'[()\[\],.|]', Text), 
    299            # Comments 
    300            (r'%.*?\n', Comment), 
    301            (r'/\*(.|\n)*?\*/', Comment), 
    302            # Whitespace 
    303            (r'\n', Text), 
    304            (r'\s+', Text), 
    305        ] 
    306    } 
    307 
    308    def analyse_text(text): 
    309        if ':- object(' in text: 
    310            return 1.0 
    311        elif ':- protocol(' in text: 
    312            return 1.0 
    313        elif ':- category(' in text: 
    314            return 1.0 
    315        elif re.search(r'^:-\s[a-z]', text, re.M): 
    316            return 0.9 
    317        else: 
    318            return 0.0