# -*- 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__ = ["PseudocodeLexer", "PseudocodeLexer_DE"]


import re

from pygments.lexer import include, bygroups
from pygments.token import (Comment, Keyword, Name, 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


class PseudocodeLexer(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 = "Pseudocode"
    aliases = ["pseudocode", "pseudo", "algorithm", "algo"]
    filenames = ["*.algo", "*.pseudocode"]
    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",
    }
    SYMBOLS = {
        "REMARK": "▷",  # U+25B7: Unicode 1.0 (Arrows)
        "Remark": "▷",
        "remark": "▷",
        "REM": "▷",
        "Rem": "▷",
        "rem": "▷",
        "R": "▷",
        "r": "▷",
        "BLOCK": "┃",   # U+2503: Unicode 1.0 (Bow Drawing)
        "Block": "┃",
        "block": "┃",
    }

    def op_translate(toktype):

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

        return _op_translate

    def op_symbol(toktype):

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

        return _op_symbol

    tokens = {
        "root": [
            (r"\n", Whitespace),
            (r"/\*", Comment.Multiline, "multiline-nested-comment"),
            (r"//.*$", Comment.Single),
            (r"(?:\\)(REMARK|Remark|remark|REM|Rem|rem|R|r)\b(.*)$",
             bygroups(op_symbol(Comment.Single), Comment.Single)),
            (r"(?:\\)(BLOCK|Block|block)\b(.*)$",
             bygroups(op_symbol(Text), Text)),
            (r"\\\n", Text),
            (r"(?i)\\("
             r"(?:prog(?:ram)?)"
             r"|(?:algo(?:rithm)?)"
             r"|(?:proc(?:edure)?)"
             r"|(?:func(?:tion)?|(?:fn))"
             r"|(?:class)"
             r")(\s*)(\{)",
             bygroups(op_translate(Keyword), Whitespace, Name.Entity),
             "entity-name"),
            include("expr"),
            (r"\s+", Text),
        ],
        "entity-name": [       # may be multiline
            (r"[^\\}]+", Name.Entity),
            (r"\\\}", Name.Entity),
            (r"\\", Name.Entity),
            (r"\}", Name.Entity, "#pop"),
        ],
        "expr": [
            include("py-strings"),
            include("py-numbers"),
            include("py-name"),
        ]
    }


class PseudocodeLexer_DE(PseudocodeLexer):

    name = "PseudocodeDE"
    aliases = ["pseudocode-de", "pseudo-de", "algorithm-de", "algo-de"]
    filenames = ["*.algo-de", "*.pseudocode-de"]

    LANG = "de"
    TRANSLATIONS = PseudocodeLexer.TRANSLATIONS.copy()
    TRANSLATIONS.update({
        "PROG": "PROGRAMM",
        "PROGRAM": "PROGRAMM",
        "ALGO": "ALGORITHMUS",
        "ALGORITHM": "ALGORITHMUS",
        "PROC": "PROZEDUR",
        "PROCEDURE": "PROZEDUR",
        "FUNC": "FUNKTION",
        "FUNCTION": "FUNKTION",
        "FN": "FUNKTION",
        "CLASS": "KLASSE",
    })


class PseudocodeLexer_FR(PseudocodeLexer):

    name = "PseudocodeFR"
    aliases = ["pseudocode-fr", "pseudo-fr", "algorithm-fr", "algo-fr"]
    filenames = ["*.algo-fr", "*.pseudocode-fr"]

    LANG = "de"
    TRANSLATIONS = PseudocodeLexer.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",
    })
