view pygments_lexer_pseudocode2/algpseudocode.py @ 133:c90be4a80c1a

Wording
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 06 May 2026 23:28:18 +0200
parents f916251d5647
children 380d2607d5c7
line wrap: on
line source

# -*- coding: utf-8 -*-
# :-
# SPDX-FileCopyrightText: © 2026 Franz Glasner
# SPDX-License-Identifier: MIT
# :-
r"""A pseudocode lexer along the lines of CTAN's algpseudocode or
algpseudocodex.

"""

__all__ = ["AlgPseudocodeLexer",
           "AlgPseudocodeLexer_DE", "AlgPseudocodeLexer_FR"]


import logging
import re

import pygments.util
from pygments.lexer import bygroups, include, words
from pygments.token import (Comment, Generic, Keyword, Name, Operator,
                            Punctuation, Text, Whitespace)

#
# Relative imports do not work with pygments.lexers.load_lexer_from_file()
# in all of our supported Python releases.
#
from pygments_lexer_pseudocode2.bases import LexBase
from pygments_lexer_pseudocode2.utils import REVERSED_STANDARD_TYPES
from pygments_lexer_pseudocode2 import uniprops

#
# As in the local imports: use an explicit name because __name__ is
# __builtins__
#
_logger = logging.getLogger("pygments_lexer_pseudocode2.algpseudocode")


class AlgPseudocodeLexer(LexBase):

    """A pseudocode lexer along the lines of CTAN's algpseudocode or
    algpseudocodex.

    Some ideas (e.g. strings) are borrowed from Pygment's Python lexer.

    """

    name = "AlgPseudocode"
    aliases = ["algpseudocode", "algpseudo"]
    filenames = ["*.algpseudo", "*.algpseudocode"]
    mimetypes = []
    flags = re.MULTILINE

    LANG = "en"
    TRANSLATIONS = {
        "PROG": "PROGRAM",
        "PROGRAM": "PROGRAM",
        "ALGO": "ALGORITHM",
        "ALGORITHM": "ALGORITHM",
        "PROC": "PROCEDURE",
        "PROCEDURE": "PROCEDURE",
        "FUNC": "FUNCTION",
        "FUNCTION": "FUNCTION",
        "FN": "FUNCTION",
        "CLASS": "CLASS",
        "INPUT": "Input:",
        "INPUTS": "Inputs:",
        "OUTPUT": "Output:",
        "OUTPUTS": "Outputs:",
        "RETURNS": "Returns:",
        "ENSURE": "Ensure:",
        "REQUIRE": "Require:",
        "IS": "IS",
        "WITH": "WITH",
        "IF": "IF",
        "THEN": "THEN",
        "ELSE": "ELSE",
        "ELSEIF": "ELSE IF",
        "ELSIF": "ELSE IF",
        "ELIF": "ELSE IF",
        "DO": "DO",           # in WHILE ... DO
        "WHILE": "WHILE",
        "FOR": "FOR",
        "FORALL": "FOR ALL",
        "FROM": "FROM",
        "TO": "TO",
        "IN": "IN",           # as in FOR ... IN
        "STEP": "STEP",
        "LOOP": "LOOP",
        "REPEAT": "REPEAT",
        "UNTIL": "UNTIL",
        "RETURN": "RETURN",
        "BEGIN": "BEGIN",
        "END": "END",         # not in END_TRANSLATIONS
    }
    END_TRANSLATIONS = {
        "PROG": "END OF PROGRAM",
        "PROGRAM": "END OF PROGRAM",
        "ALGO": "END OF ALGORITHM",
        "ALGORITHM": "END OF ALGORITHM",
        "PROC": "END OF PROCEDURE",
        "PROCEDURE": "END OF PROCEDURE",
        "FUNC": "END OF FUNCTION",
        "FUNCTION": "END OF FUNCTION",
        "FN": "END OF FUNCTION",
        "CLASS": "END OF CLASS",
        "IF": "END IF",
        "WHILE": "END WHILE",
        "FOR": "END FOR",
        "FORALL": "END FOR ALL",
        "LOOP": "END LOOP",
    }
    DEFAULT_END_PREFIX = "END OF "
    SYMBOL_REMARK = u"▷"           # U+25B7: Unicode 1.0 (Geometric Shapes)
    # SYMBOL_REMARK = u"▻"         # U+25BB: Unicode 1.0 (Geometric Shapes)
    # SYMBOL_REMARK = u"⍝"         # U+235D: Unicode 1.1 (Misc. Technical, APL)
    SYMBOL_BLOCK = u"◆"            # U+25C6: Unicode 1.0 (Geometric Shapes)
    # SYMBOL_BLOCK = u"┃"          # U+2503: Unicode 1.0 (Bow Drawing)
    # SYMBOL_BLOCK = u"●"          # U+25CF: Unicode 1.0 (Geometric Shapes)
    SYMBOL_TEXTSTATEMENT = u"▪"    # U+25AA: Unicode 1.0 (Geometric Shapes)
    # SYMBOL_TEXTSTATEMENT = u"■"  # U+25A0: Unicode 1.0 (Geometric Shapes)
    SYMBOLS = {
        # Group REMARK
        "REMARK": SYMBOL_REMARK,
        "REM": SYMBOL_REMARK,
        # Group STATEMENT
        "STATEMENT": SYMBOL_BLOCK,
        "STATE": SYMBOL_BLOCK,
        "BLOCK": SYMBOL_BLOCK,
        # Group TEXTSTATEMENT
        "TEXTSTATEMENT": SYMBOL_TEXTSTATEMENT,
        "TEXTSTATE": SYMBOL_TEXTSTATEMENT,
        "TSTATEMENT": SYMBOL_TEXTSTATEMENT,
        "TSTATE": SYMBOL_TEXTSTATEMENT,
        "TEXTBLOCK": SYMBOL_TEXTSTATEMENT,
        "TBLOCK": SYMBOL_TEXTSTATEMENT,
        "<-": u"⟵",          # U+27F5: Unicode 3.2 (Supplemental Arrows-A)
        "->": u"⟶",          # U+27F6: Unicode 3.2 (Supplemental Arrows-A)
        "<->": u"⟷",         # U+27F7: Unicode 3.2 (Supplemental Arrows-A)
        # "=>": u"⟹",       # U+27F9: Unicode 3.2 (Supplemental Arrows-A)
        # "<=>": u"⟺",      # U+27FA: Unicode 3.2 (Supplemental Arrows-A)
        # "<-": u"←",        # U+2190: Unicode 1.0 (Arrows)
        # "->": u"→",        # U+2192: Unicode 1.0 (Arrows)
        # "<->": u"↔",       # U+2194: Unicode 1.0 (Arrows)
        "=>": u"⇒",          # U+21D2: Unicode 1.0 (Arrows)
        "<=>": u"⇔",         # U+21D4: Unicode 1.0 (Arrows)
        "<=": u"≤",          # U+2264: Unicode 1.0 (Mathematical Operators)
        ">=": u"≥",          # U+2265: Unicode 1.0 (Mathematical Operators)
        "<>": u"≠",          # U+2260: Unicode 1.0 (Mathematical Operators)
        "!=": u"≠",          # U+2260: Unicode 1.0 (Mathematical Operators)
        ":=": u"∶=",    # "≔" U+2254  not recognizable in my (small) mono font
        "=:": u"=∶",    # "≕" U+2255  not recognizable in my (small) mono font
        "?=": u"≟",          # U+225F: Unicode 1.0 (Mathematical Operators)
    }

    def op_translate(toktype):

        def _op_translate(lexer, match, ctx=None):
            kw = match.group().upper()
            yield match.start(), toktype, lexer.TRANSLATIONS.get(kw, kw)
            if ctx:
                ctx.pos = match.end()

        return _op_translate

    def op_opt_end_translate(toktype):

        def _op_end_translate(lexer, match, ctx=None):
            if not lexer.no_end:
                kw = match.group().upper()
                yield (match.start(),
                       toktype,
                       lexer.END_TRANSLATIONS.get(
                           kw,
                           lexer.DEFAULT_END_PREFIX + kw))
            if ctx:
                ctx.pos = match.end()

        return _op_end_translate

    def op_opt_ignore(toktype):

        def _op_opt_ignore(lexer, match, ctx=None):
            if not lexer.no_end:
                yield match.start(), toktype, match.group()
            if ctx:
                ctx.pos = match.end()

        return _op_opt_ignore

    def op_opt_ignore_or_fixed(toktype, value):
        """Yield a fixed given token type and value or -- if the lexer's
        `no_end` setting evals to ``True`` nothing.

        """

        def _op_opt_ignore_or_fixed(lexer, match, ctx=None):
            if not lexer.no_end:
                yield match.start(), toktype, value
            if ctx:
                ctx.pos = match.end()

        return _op_opt_ignore_or_fixed

    def op_gets(lexer, match, ctx=None):
        yield match.start(), Operator, lexer.symbol_gets

    def op_remark(lexer, match, ctx=None):
        yield match.start(), Comment.Single, lexer.symbol_remark

    def op_symbol(toktype):

        def _op_symbol(lexer, match, ctx=None):
            kw = match.group().upper()
            yield match.start(), toktype, lexer.SYMBOLS.get(kw, kw)
            if ctx:
                ctx.pos = match.end()

        return _op_symbol

    def op_explicit_tokentype(lexer, match, ctx=None):
        needed_css = match.group("type")
        toktype = REVERSED_STANDARD_TYPES.get(needed_css, None)
        if toktype is None:
            # Be more error friendly
            toktype = Generic.Error
            val = match.group()
            _logger.warning("Unhandled explicit token type: %s", val)
        else:
            val = match.group("character")
        yield match.start(), toktype, val
        if ctx:
            ctx.pos = match.end()

    tokens = {
        "root": [
            (r"\n", Whitespace),
            (r"/\*", Comment.Multiline, "multiline-nested-comment"),
            (r"\(\*", Comment.Multiline, "multiline-nested-comment-alt"),
            (r"(//|#).*$", Comment.Single),
            include("remark"),
            (r"(?i)\\(block|state(?:ment)?)[ \t]*(\{)",
             bygroups(op_symbol(Text), LexBase.op_fixed(Whitespace, " ")),
             "block-expr"),
            (r"(?i)\\("
             r"(?:textstate(?:ment)?)"
             r"|(?:tstate(?:ment)?)"
             r"|(?:textblock)"
             r"|(?:tblock)"
             r")[ \t]*(\{)",
             bygroups(op_symbol(Text), LexBase.op_fixed(Whitespace, " ")),
             "text-statement"),
            (r"(?i)\\("
             r"(?:input(?:s)?)"
             r"|(?:output(?:s)?)"
             r"|(?:ensure)"
             r"|(?:require)"
             r"|(?:returns)"
             r")[ \t]*(\{)",
             bygroups(op_translate(Keyword),
                      LexBase.op_fixed(Whitespace, " ")),
             "text-statement"),
            (r"(?i)\\("
             r"(?:if)"
             r"|(?:then)"
             r"|(?:else)"
             r"|(?:el(?:s(?:e)?)?if)"
             r"|(?:do)"               # as in WHILE ... DO not DO ... UNTIL
             r"|(?:while)"
             r"|(?:forall)"
             r"|(?:for)"
             r"|(?:from)"
             r"|(?:to)"
             r"|(?:step)"
             r"|(?:in)"
             r"|(?:loop)"
             r"|(?:repeat)"
             r"|(?:until)"
             r"|(?:return)"
             r")\b",
             bygroups(op_translate(Keyword))),
            (r"\\\n", Text),
            (r"(?i)\\("
             r"(?:prog(?:ram)?)"
             r"|(?:algo(?:rithm)?)"
             r"|(?:proc(?:edure)?)"
             r"|(?:func(?:tion)?|(?:fn))"
             r"|(?:class)"
             r")[ \t]*(\{)",
             bygroups(op_translate(Keyword),
                      LexBase.op_fixed(Whitespace, " ")),
             "entity-name"),
            # ENDxxx keywords with optional entity name in two parts:
            #   1. with name
            (r"(?i)\\end(?:[_\-]|(?:[ \t]+))?("
             r"(?:prog(?:ram)?)"
             r"|(?:algo(?:rithm)?)"
             r"|(?:proc(?:edure)?)"
             r"|(?:func(?:tion)?)"
             r"|(?:fn)"
             r"|(?:class)"
             r")(?:[_\-]|(?:[\t ]+))?(\{)",
             bygroups(op_opt_end_translate(Keyword),
                      op_opt_ignore_or_fixed(Whitespace, " ")),
             "entity-name-end"),
            #   2. without name
            #   3. AND keywords that do not allow a param (e.g. endif)
            (r"(?i)\\end(?:[_\-]|(?:[ \t]+))?("
             r"(?:prog(?:ram)?)"
             r"|(?:algo(?:rithm)?)"
             r"|(?:proc(?:edure)?)"
             r"|(?:func(?:tion)?)"
             r"|(?:fn)"
             r"|(?:class)"
             r"|(?:if)"
             r"|(?:while)"
             r"|(?:for)"
             r"|(?:forall)"
             r"|(?:loop)"
             r")\b",
             bygroups(op_opt_end_translate(Keyword))),
            #
            # A single begin or end that is never suppressed because
            # it is supposed to be paired with begin
            #
            (r"(?i)\\(begin|end)\b",
             bygroups(op_translate(Keyword))),
            # Keywords
            (r"(?i)\\("
             r"(?:is)"
             r"|(?:with)"
             r")\b",
             bygroups(op_translate(Keyword))),
            include("expr"),
            include("unicode-separators"),
            include("unicode-other"),
            (r"[^\S\n]+", Text),
            (r".", Generic.Error),     # tolerance for errors
        ],
        "remark": [
            (r"(?i)\\(remark|rem)\b(.*)$",
             bygroups(op_remark, Comment.Single)),
        ],
        "entity-name": [      # may be multiline
            (r"[^\\}]+", Name.Entity),
            (r"\}", LexBase.op_ignore, "#pop"),
            (r"\\\}", LexBase.op_fixed(Name.Entity, "}")),
            (r"\\\\", LexBase.op_fixed(Name.Entity, "\\")),
            (r"\\", LexBase.op_fixed(Name.Entity, "\\")),
        ],
        "entity-name-end": [  # may be multiline -- suppressed if no_end
            (r"[^\\}]+", op_opt_ignore(Name.Entity)),
            (r"\}", LexBase.op_ignore, "#pop"),
            (r"\\\}", op_opt_ignore_or_fixed(Name.Entity, "}")),
            (r"\\\\", op_opt_ignore_or_fixed(Name.Entity, "\\")),
            (r"\\", op_opt_ignore_or_fixed(Name.Entity, "\\")),
        ],
        "expr": [
            include("math-symbols"),          # must be before punctuation
            include("ascii-punctuation"),
            include("unicode-punctuation"),
            include("escaped-string-start"),
            include("py-strings"),
            include("py-numbers"),
            (r"(?i)\\call[ \t]*(\{)", LexBase.op_ignore, "entity-name"),
            (r"(?i)\\gets\b", op_gets),
            (r"(?i)\\text[ \t]*\{", LexBase.op_ignore, "text-in-expr"),
            include("explicit-tokentype"),
            include("remark"),
            include("keyword-constants"),
            include("word-operators"),
            include("math-builtins"),
            include("py-name"),
        ],
        "expr-in-braces": [
            include("math-symbols"),          # must be before punctuation
            include("ascii-punctuation-in-braces"),
            include("unicode-punctuation"),
            include("escaped-string-start"),
            include("py-strings"),
            include("py-numbers"),
            (r"(?i)\\call[ \t]*(\{)", LexBase.op_ignore, "entity-name"),
            (r"(?i)\\gets\b", op_gets),
            (r"(?i)\\text[ \t]*\{", LexBase.op_ignore, "text-in-expr"),
            include("explicit-tokentype"),
            include("remark"),
            include("keyword-constants"),
            include("word-operators"),
            include("math-builtins"),
            include("py-name"),
        ],
        "block-expr": [      # somewhat similar to "root"
            (r"\}", LexBase.op_ignore, "#pop"),
            (r"\n", Whitespace),
            include("expr-in-braces"),
            (r"\\\\", LexBase.op_fixed(Text, "\\")),
            (r"\\", LexBase.op_fixed(Text, "\\")),
            include("unicode-separators"),
            include("unicode-other"),
            (r"[^\S\n]+", Text),
            (r".", Generic.Error),     # tolerance for errors
        ],
        "text-statement": [  # like block but default to text-mode
            (r"[^\\}\n]+", Text),
            (r"\}", LexBase.op_ignore, "#pop"),
            (r"\n", Whitespace),
            (r"\\\}", LexBase.op_fixed(Text, "}")),
            (r"(?i)\\expr(?:ession)?[ \t]*\{",
             LexBase.op_ignore,
             "block-expr"),
            include("explicit-tokentype"),
            include("remark"),
            (r"\\\\", LexBase.op_fixed(Text, "\\")),
            (r"\\", LexBase.op_fixed(Text, "\\")),
            (r".", Generic.Error),     # tolerance for errors
        ],
        "text-in-expr": [
            (r"[^\\}\n]+", Text),
            (r"\}", LexBase.op_ignore, "#pop"),
            (r"\n", Whitespace),
            (r"\\\}", LexBase.op_fixed(Text, "}")),
            (r"(?i)\\expr(?:ession)?[ \t]*\{",
             LexBase.op_ignore,
             "block-expr"),
            include("explicit-tokentype"),
            include("remark"),
            (r"\\\\", LexBase.op_fixed(Text, "\\")),
            (r"\\", LexBase.op_fixed(Text, "\\")),
            (r".", Generic.Error),     # tolerance for errors
        ],
        "math-builtins": [
            (words(("sqrt", "pow", "cos", "sin", "tan", "arcos", "arcsin",
                    "arctan", "arctan2", "mod", "exp", "ln", "log",
                    "min", "max"),
                   prefix=r"(?<!\.)",
                   suffix=r"\b"),
             Name.Builtin),
        ],
        "math-symbols": [
            (r"<=>|<->|<-|->|=>|<=|>=|<>|!=|:=|=:|\?=", op_symbol(Operator)),
            (r"[!&<>=+\-*/%|~]", Operator),         # ASCII
            (u"[%s]" % (uniprops.Sm,), Operator),   # other Unicode
        ],
        "word-operators": [
            (words(("IN", "In", "in",
                    "IS", "Is", "is",
                    "AND", "And", "and",
                    "OR", "Or", "or",
                    "XOR", "Xor", "xor",
                    "NOT", "Not", "not"),
                   prefix=r"(?<!\.)",
                   suffix=r"\b"),
             Operator.Word),
        ],
        "keyword-constants": [
            (words(("True", "TRUE", "true", "False", "FALSE", "false",
                    "None", "NONE", "none", "Nil", "NIL", "nil",
                    "Null", "NULL", "null",
                    "Empty", "EMPTY", "empty"),
                   prefix=r"(?<!\.)",
                   suffix=r"\b"),
             Keyword.Constant),
        ],
        "ascii-punctuation": [
            (r"[{}:(),;[\]?@]", Punctuation),
        ],
        "ascii-punctuation-in-braces": [
            #
            # Like "punctuation" but needs an escaped curly brace for } because
            # a single closing curly brace pops the current state here.
            #
            (r"\\\}", LexBase.op_fixed(Punctuation, "}")),
            (r"[{:(),;[\]?@]", Punctuation),
        ],
        "unicode-separators": [
            (u"[%s]" % (uniprops.Zl,), Whitespace),
            (u"[%s]" % (uniprops.Zp,), Whitespace),
            (u"[%s]" % (uniprops.Zs,), Whitespace),
        ],
        "unicode-punctuation": [
            (u"[%s]" % (uniprops.Pc,), Punctuation),
            (u"[%s]" % (uniprops.Pd,), Punctuation),
            (u"[%s]" % (uniprops.Ps,), Punctuation),
            (u"[%s]" % (uniprops.Pe,), Punctuation),
            (u"[%s]" % (uniprops.Pi,), Punctuation),
            (u"[%s]" % (uniprops.Pf,), Punctuation),
            (u"[%s]" % (uniprops.Po,), Punctuation),
        ],
        "unicode-other": [
            (u"[%s]" % (uniprops.Sc,), Text),    # Currency
            (u"[%s]" % (uniprops.So,), Text),    # Other symbols
        ],
        "escaped-string-start": [
            (r"""\\(['"])""", bygroups(Punctuation)),
        ],
        "explicit-tokentype": [
            # All these REs are CASE-SENSITIVE!

            # Multiple characters possible, but no escaping!
            (r"\\ttx\-(?P<type>[a-zA-Z0-9_-]+?)(?P<sep>[/:|=*+!\$~])"
             r"(?P<character>(.|\n)+?)(?P=sep)",
             op_explicit_tokentype),
            (r"\\ttx\-(?P<type>[a-zA-Z0-9_-]+?)\{(?P<character>[^}]+?)\}",
             op_explicit_tokentype),
            (r"\\ttx\-(?P<type>[a-zA-Z0-9_-]+?)\((?P<character>[^)]+?)\)",
             op_explicit_tokentype),
            (r"\\ttx\-(?P<type>[a-zA-Z0-9_-]+?)<(?P<character>[^>]+?)>",
             op_explicit_tokentype),
            (r"\\ttx\-(?P<type>[a-zA-Z0-9_-]+?)\[(?P<character>[^\]]+?)\]",
             op_explicit_tokentype),

            # Every character is possible: no escaping needed!
            (r"\\tt-(?P<type>[^/]+?)/(?P<character>(?:.|\n))",
             op_explicit_tokentype),
        ],
    }

    def __init__(self, **options):
        self.no_end = pygments.util.get_bool_opt(
            options, "no_end", default=False)
        self.symbol_gets = options.get("gets", None)
        if self.symbol_gets is None:
            self.symbol_gets = self.SYMBOLS["<-"]   # Default: "⟵"  # U+27F5
        self.symbol_remark = options.get("remark", None)
        if self.symbol_remark is None:
            self.symbol_remark = self.SYMBOLS["REM"]  # Default: "▷"  # U+25B7
        LexBase.__init__(self, **options)


class AlgPseudocodeLexer_DE(AlgPseudocodeLexer):

    """

    .. seealso::
       - https://de.wikipedia.org/wiki/Pseudocode

    .. todo:: Complete german translations

    """

    name = "AlgPseudocodeDE"
    aliases = ["algpseudocode-de", "algpseudo-de"]
    filenames = ["*.algpseudo-de", "*.algpseudocode-de"]

    LANG = "de"
    TRANSLATIONS = AlgPseudocodeLexer.TRANSLATIONS.copy()
    TRANSLATIONS.update({
        "PROG": "PROGRAMM",
        "PROGRAM": "PROGRAMM",
        "ALGO": "ALGORITHMUS",
        "ALGORITHM": "ALGORITHMUS",
        "PROC": "PROZEDUR",
        "PROCEDURE": "PROZEDUR",
        "FUNC": "FUNKTION",
        "FUNCTION": "FUNKTION",
        "FN": "FUNKTION",
        "CLASS": "KLASSE",
        "IS": "IST",
        "WITH": "MIT",
        "IF": "WENN",
        "THEN": "DANN",
        "ELSE": "ANDERNFALLS",
        "ELSEIF": "ANDERNFALLS WENN",
        "ELSIF": "ANDERNFALLS WENN",
        "ELIF": "ANDERNFALLS WENN",
#       "DO": # XXX TBD  # in WHILE WHILE ... DO  # noqa  # in WHILE ... DO
        "WHILE": "SOLANGE",
        "FOR": "FÜR",
        "FORALL": "FÜR ALLE",
        "FROM": "VON",
        "TO": "BIS",
        "IN": "IN",
        "STEP": "SCHRITTWEITE",
#       "LOOP": XXX TBD        # noqa
        "REPEAT": "WIEDERHOLE",
        "UNTIL": "BIS",
#       "RETURN": XXX TBD      # noqa
        "BEGIN": "START",
        "END": "ENDE",
    })
    END_TRANSLATIONS = AlgPseudocodeLexer.END_TRANSLATIONS.copy()
    END_TRANSLATIONS.update({
        "PROG": "ENDE DES PROGRAMMS",
        "PROGRAM": "ENDE DES PROGRAMMS",
        "ALGO": "ENDE DES ALGORITHMUS",
        "ALGORITHM": "ENDE DES ALGORITHMUS",
        "PROC": "ENDE DER PROZEDUR",
        "PROCEDURE": "ENDE DER PROZEDUR",
        "FUNC": "ENDE DER FUNKTION",
        "FUNCTION": "ENDE DER FUNKTION",
        "FN": "ENDE DER FUNKTION",
        "CLASS": "ENDE DER KLASSE",
        "IF": "ENDE WENN",
        "WHILE": "ENDE SOLANGE",
        "FOR": "ENDE FÜR",
        "FORALL": "ENDE FÜR ALLE",
#       "LOOP": "ENDE XXX",            # XXX TBD   # noqa
    })
    DEFAULT_END_PREFIX = "ENDE VON "


class AlgPseudocodeLexer_FR(AlgPseudocodeLexer):

    """

    .. seealso::
      - https://info.blaisepascal.fr/pseudo-code/
      - https://fr.wikipedia.org/wiki/Pseudo-code
      - https://fr.wikipedia.org/wiki/Structure_de_contr%C3%B4le

    .. todo:: Complete french translations

    """

    name = "AlgPseudocodeFR"
    aliases = ["algpseudocode-fr", "algpseudo-fr"]
    filenames = ["*.algpseudo-fr", "*.algpseudocode-fr"]

    LANG = "fr"
    TRANSLATIONS = AlgPseudocodeLexer.TRANSLATIONS.copy()
    TRANSLATIONS.update({
        "PROG": "PROGRAMME",
        "PROGRAM": "PROGRAMME",
        "ALGO": "ALGORITHME",
        "ALGORITHM": "ALGORITHME",
        "PROC": "PROCÉDURE",
        "PROCEDURE": "PROCÉDURE",
        "FUNC": "FONCTION",
        "FUNCTION": "FOUNCTION",
        "FN": "FONCTION",
        "CLASS": "CLASSE",
        "IS": "EST",
        "WITH": "AVEC",
        "IF": "SI",
        "THEN": "ALORS",
        "ELSE": "SINON",
        "ELSEIF": "SINONSI",
        "ELSIF": "SINONSI",
        "ELIF": "SINONSI",
        "DO": "FAIRE",             # as in in WHILE ... DO (not DO ... UNTIL)
        "WHILE": "TANTQUE",
        "FOR": "POUR",
        "FORALL": "POUR CHAQUE",
        "FROM": "DE",
        "TO": "JUSQU'À",           # or just "À",
        "IN": "DANS",              # as in FOR ... IN
        "STEP": "PAR PAS DE",
        "LOOP": "BOUCLE",          # XXX FIXME???
        "REPEAT": "RÉPÉTER",
        "UNTIL": "JUSQUACEQUE",
        "RETURN": "RENVOYER",
        "BEGIN": "DÉBUT",
        "END": "FIN",
    })
    END_TRANSLATIONS = AlgPseudocodeLexer.END_TRANSLATIONS.copy()
    END_TRANSLATIONS.update({
        "PROG": "FIN DE PROGRAMME",
        "PROGRAM": "FIN DE PROGRAMME",
        "ALGO": "FIN D'ALGORITHME",
        "ALGORITHM": "FIN D'ALGORITHME",
        "PROC": "FIN DE PROCÉDURE",
        "PROCEDURE": "FIN DE PROCÉDURE",
        "FUNC": "FIN DE FONCTION",
        "FUNCTION": "FIN DE FOUNCTION",
        "FN": "FIN DE FONCTION",
        "CLASS": "FIN DE CLASSE",
        "SI": "FIN SI",
        "FOR": "FIN POUR",
        "FORALL": "FIN POUR CHAQUE",
        "WHILE": "FIN TANTQUE",
        "LOOP": "FIN BOUCLE",
    })
    DEFAULT_END_PREFIX = "FIN DE "
PK&5[o5; PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/.exrcUT(#hPK&5[;n@ PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/.gitignoreUT(#hPK&5[S1\ñ= PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/AUTHORSUT(#hPK&5[ID PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/CMakeLists.txtUT(#hPK&5[ = .PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/COPYINGUT(#hPK&5[۩}? PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/ChangeLogUT(#hPK&5[B@< PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/READMEUT(#hPK&5[h ";9D QPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/README.androidUT(#hPK&5[?6^G PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/README.blackberryUT(#hPK&5[b0pB XPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/README.cmakeUT(#hPK&5[HV"V I APyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/README.cygwin_mingwUT(#hPK&5[{)H PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/README.mingw_crossUT(#hPK&5["HB PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/README.win32UT(#hPK&5[H PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/android/Android.mkUT(#hPK&5[8SfsD PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/android/READMEUT(#hPK&5[QMM PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/android_toolchain.cmakeUT(#hPK&5[ݾ 6&P "PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/blackberry.toolchain.cmakeUT(#hPK&5[ڎ`A PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/config.h.inUT(#hPK&5[`'tG  PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/download.htmlUT(#hPK&5[(\`"G PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/freeglut.htmlUT(#hPK&5[%&I=>K PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/freeglut_logo.pngUT(#hPK&5[?V ]PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/freeglut_user_interface.htmlUT(#hPK&5[ .b. D 큺PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/index.htmlUT(#hPK&5[ޢ2D !PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/ogl_sm.pngUT(#hPK&5[ G 큋PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/progress.htmlUT(#hPK&5[}c|H PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/doc/structure.htmlUT(#hPK&5[ZTD ýPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/freeglut.pc.inUT(#hPK&5[07D ,PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/freeglut.rc.inUT(#hPK&5[bDeK PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/include/GL/freeglut.hUT(#hPK&5[W[ )O PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/include/GL/freeglut_ext.hUT(#hPK&5[(W8jO PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/include/GL/freeglut_std.hUT(#hPK&5[hϗG PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/include/GL/glut.hUT(#hPK&5[#<Q PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/mingw_cross_toolchain.cmakeUT(#hPK&5[햖"QUY_ PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/CallbackMaker/CallbackMaker.cUT(#hPK&5[V< O#U PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/Fractals/fractals.cUT(#hPK&5[u| eW PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/Fractals/fractals.datUT(#hPK&5[u| e^ PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/Fractals_random/fractals.datUT(#hPK&5[ܐ *'c PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/Fractals_random/fractals_random.cUT(#hPK&5[2RFdE+Q ?PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/Lorenz/lorenz.cUT(#hPK&5[~Q +-PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/One/objects.icoUT(#hPK&5[@iq= )K /PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/One/one.cUT(#hPK&5[-3L =PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/One/one.rcUT(#hPK&5[nNT@ 9,U =PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/Resizer/Resizer.cppUT(#hPK&5[\]5 c HPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/init_error_func/init_error_func.cUT(#hPK&5[y~i[ NKPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/multi-touch/multi-touch.cUT(#hPK&5[oHSS RPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/shapes/glmatrix.cUT(#hPK&5[gMS wYPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/shapes/glmatrix.hUT(#hPK&5[`!ZQ N[PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/shapes/shapes.cUT(#hPK&5[P/,)Aa X}PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/smooth_opengl3/smooth_opengl3.cUT(#hPK&5[y_d"W PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/spaceball/spaceball.cUT(#hPK&5[=\S ̖PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/spaceball/vmath.cUT(#hPK&5[LVzS PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/spaceball/vmath.hUT(#hPK&5[@U PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/spaceball/vmath.inlUT(#hPK&5[LIQ לPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/subwin/subwin.cUT(#hPK&5[B k3 O PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/demos/timer/timer.cUT(#hPK&5[<a gPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/AndroidManifest.xmlUT(#hPK&5[/$:\ PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/CMakeLists.txtUT(#hPK&5[_e QPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/android_toolchain.cmakeUT(#hPK&5[2L!e PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/ndk/AndroidManifest.xmlUT(#hPK&5[X@` 8PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/ndk/jni/Android.mkUT(#hPK&5[[413d PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/ndk/jni/Application.mkUT(#hPK&5[nڸ U*a vPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/progs/test-shapes-gles1/test-shapes-gles1.cUT(#hPK&5[E)U PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_cursor_android.cUT(#hPK&5[gXxR LPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_ext_android.cUT(#hPK&5[LѝӀW PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_gamemode_android.cUT(#hPK&5[mS PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_init_android.cUT(#hPK&5[Q\ PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_input_devices_android.cUT(#hPK&5[l/aW ~PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_internal_android.hUT(#hPK&5[W PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_joystick_android.cUT(#hPK&5[9US APyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_main_android.cUT(#hPK&5[ mVS PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_main_android.hUT(#hPK&5[/O V PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_runtime_android.cUT(#hPK&5[T0X :PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_spaceball_android.cUT(#hPK&5[Fi T oPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_state_android.cUT(#hPK&5[~!-X cPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_structure_android.cUT(#hPK&5[q%) BU  PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/fg_window_android.cUT(#hPK&5[Ц7X )PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/native_app_glue/READMEUT(#hPK&5[CA- @k +PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/native_app_glue/android_native_app_glue.cUT(#hPK&5[J/k 58PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/android/native_app_glue/android_native_app_glue.hUT(#hPK&5[ÎY !HPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/blackberry/fg_init_blackberry.cUT(#hPK&5[] NPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/blackberry/fg_internal_blackberry.hUT(#hPK&5[S gY VPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/blackberry/fg_main_blackberry.cUT(#hPK&5[1*SZ wPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/blackberry/fg_state_blackberry.cUT(#hPK&5[5^ PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/blackberry/fg_structure_blackberry.cUT(#hPK&5[Q )[ =PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/blackberry/fg_window_blackberry.cUT(#hPK&5[5OWN PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_display_egl.cUT(#hPK&5[^q 5J PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_ext_egl.cUT(#hPK&5[& K PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_init_egl.cUT(#hPK&5[K ߝPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_init_egl.hUT(#hPK&5[#O |PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_internal_egl.hUT(#hPK&5[ 'L PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_state_egl.cUT(#hPK&5[LS /L PPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_state_egl.hUT(#hPK&5[x,GP ܱPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_structure_egl.cUT(#hPK&5[ P PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_structure_egl.hUT(#hPK&5[[^ (M "PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_window_egl.cUT(#hPK&5[@:g/M PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/egl/fg_window_egl.hUT(#hPK&5[w8 t'H PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_callbacks.cUT(#hPK&5[q~ E nPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_cursor.cUT(#hPK&5[4,( F PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_display.cUT(#hPK&5[T B lPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_ext.cUT(#hPK&5[ 5C yPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_font.cUT(#hPK&5[KsKvjH PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_font_data.cUT(#hPK&5[!^G lPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_gamemode.cUT(#hPK&5[?0t6-:G uPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_geometry.cUT(#hPK&5[cBB PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_gl2.cUT(#hPK&5[i[ B PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_gl2.hUT(#hPK&5[őmWMXC PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_init.cUT(#hPK&5[l ,C PyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_init.hUT(#hPK&5[z gL cPyMuPDF-da085c7f52c6/mupdf-source/thirdparty/freeglut/src/fg_input_devices.cUT(#hPKmmf