# Copyright 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
pyparsing based module for parsing a dbus method input or output signature.
"""

# isort: THIRDPARTY
from pyparsing import Forward, Literal, OneOrMore, ZeroOrMore


class Parser:
    """
    Parse a dbus signature using pyparsing.
    """

    # pylint: disable=too-many-instance-attributes
    # pylint: disable=too-few-public-methods
    # pylint: disable=invalid-name
    def __init__(self):
        """
        Initializer.

        Instantiates the entire parser.

        All productions are public instance attributes.
        """
        self.BYTE = Literal("y")("BYTE")
        self.BOOLEAN = Literal("b")("BOOLEAN")
        self.INT16 = Literal("n")("INT16")
        self.UINT16 = Literal("q")("UINT16")
        self.INT32 = Literal("i")("INT32")
        self.UINT32 = Literal("u")("UINT32")
        self.INT64 = Literal("x")("INT64")
        self.UINT64 = Literal("t")("UINT64")
        self.DOUBLE = Literal("d")("DOUBLE")
        self.UNIX_FD = Literal("h")("UNIX_FD")

        self.STRING = Literal("s")("STRING")
        self.OBJECT_PATH = Literal("o")("OBJECT_PATH")
        self.SIGNATURE = Literal("g")("SIGNATURE")

        self.VARIANT = Literal("v")("VARIANT")

        self.CODE = (
            self.BYTE
            ^ self.BOOLEAN
            ^ self.DOUBLE
            ^ self.INT16
            ^ self.UINT16
            ^ self.INT32
            ^ self.UINT32
            ^ self.INT64
            ^ self.UINT64
            ^ self.UNIX_FD
            ^ self.STRING
            ^ self.OBJECT_PATH
            ^ self.SIGNATURE
            ^ self.VARIANT
        )

        self.COMPLETE = Forward()

        self.DICT_ENTRY = (
            Literal("{") + self.CODE + Forward(self.COMPLETE) + Literal("}")
        )
        self.DICT_ENTRY.setName("DICT_ENTRY")

        self.ARRAY = Literal("a") + (Forward(self.COMPLETE) ^ self.DICT_ENTRY)
        self.ARRAY.setName("ARRAY")

        self.STRUCT = Literal("(") + OneOrMore(Forward(self.COMPLETE)) + Literal(")")
        self.STRUCT.setName("STRUCT")

        self.COMPLETE <<= self.CODE ^ self.ARRAY ^ self.STRUCT
        self.PARSER = ZeroOrMore(self.COMPLETE)
