"""
    pygments.lexers.openscad
    ~~~~~~~~~~~~~~~~~~~~~~~~

    Lexers for the OpenSCAD languages.

    :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

from pygments.lexer import RegexLexer, bygroups, words, include
from pygments.token import Text, Comment, Punctuation, Operator, Keyword, Name, Number, Whitespace, Literal, String

__all__ = ["OpenScadLexer"]


class OpenScadLexer(RegexLexer):
    """For openSCAD code.

    .. versionadded:: 2.16
    """

    name = "OpenSCAD"
    url = "https://openscad.org/"
    aliases = ["openscad"]
    filenames = ["*.scad"]
    mimetypes = ["application/x-openscad"]

    tokens = {
        "root": [
            (r"[^\S\n]+", Whitespace),
            (r"//", Comment.Single, "comment-single"),
            (r"/\*", Comment.Multiline, "comment-multi"),
            (r"[{}\[\]\(\),;:]", Punctuation),
            (r"[*!#%\-+=?/]", Operator),
            (r"<=|<|==|!=|>=|>|&&|\|\|", Operator),
            (r"\$(f[asn]|t|vp[rtd]|children)", Operator),
            (r"(undef|PI)\b", Keyword.Constant),
            (
                r"(use|include)((?:\s|\\\\s)+)",
                bygroups(Keyword.Namespace, Text),
                "includes",
            ),
            (r"(module)(\s*)([^\s\(]+)", bygroups(Keyword.Namespace, Whitespace, Name.Namespace)),
            (r"(function)(\s*)([^\s\(]+)", bygroups(Keyword.Declaration, Whitespace, Name.Function)),
            (words(("true", "false"), prefix=r"\b", suffix=r"\b"), Literal),
            (
                words(
                    ("function", "module", "include", "use", "for", "intersection_for", "if", "else", "return"),
                    prefix=r"\b",
                    suffix=r"\b",
                ),
                Keyword,
            ),
            (
                words(
                    (
                        "circle",
                        "square",
                        "polygon",
                        "text",
                        "sphere",
                        "cube",
                        "cylinder",
                        "polyhedron",
                        "translate",
                        "rotate",
                        "scale",
                        "resize",
                        "mirror",
                        "multmatrix",
                        "color",
                        "offset",
                        "hull",
                        "minkowski",
                        "union",
                        "difference",
                        "intersection",
                        "abs",
                        "sign",
                        "sin",
                        "cos",
                        "tan",
                        "acos",
                        "asin",
                        "atan",
                        "atan2",
                        "floor",
                        "round",
                        "ceil",
                        "ln",
                        "log",
                        "pow",
                        "sqrt",
                        "exp",
                        "rands",
                        "min",
                        "max",
                        "concat",
                        "lookup",
                        "str",
                        "chr",
                        "search",
                        "version",
                        "version_num",
                        "norm",
                        "cross",
                        "parent_module",
                        "echo",
                        "import",
                        "import_dxf",
                        "dxf_linear_extrude",
                        "linear_extrude",
                        "rotate_extrude",
                        "surface",
                        "projection",
                        "render",
                        "dxf_cross",
                        "dxf_dim",
                        "let",
                        "assign",
                        "len",
                    ),
                    prefix=r"\b",
                    suffix=r"\b",
                ),
                Name.Builtin,
            ),
            (r"\bchildren\b", Name.Builtin.Pseudo),
            (r'""".*?"""', String.Double),
            (r'"(\\\\|\\[^\\]|[^"\\])*"', String.Double),
            (r"-?\d+(\.\d+)?(e[+-]?\d+)?", Number),
            (r"\w+", Name),
        ],
        "includes": [
            (
                r"(<)([^>]*)(>)",
                bygroups(Punctuation, Comment.PreprocFile, Punctuation),
            ),
        ],
        "comment": [(r":param: [a-zA-Z_]\w*|:returns?:|(FIXME|MARK|TODO):", Comment.Special)],
        "comment-single": [(r"\n", Text, "#pop"), include("comment"), (r"[^\n]+", Comment.Single)],
        "comment-multi": [
            include("comment"),
            (r"[^*/]+", Comment.Multiline),
            (r"/\*", Comment.Multiline, "#push"),
            (r"\*/", Comment.Multiline, "#pop"),
            (r"[*/]", Comment.Multiline),
        ],
    }
