Gets the language description from given language grammar file.

    :param grammar_file: Language grammar.
    :type grammar_file: unicode
    :return: Language description.
    :rtype: Language

def get_language_description(grammar_file):
    """
    Gets the language description from given language grammar file.

    :param grammar_file: Language grammar.
    :type grammar_file: unicode
    :return: Language description.
    :rtype: Language
    """

    LOGGER.debug("> Processing '{0}' grammar file.".format(grammar_file))

    sections_file_parser = foundations.parsers.SectionsFileParser(grammar_file)
    sections_file_parser.parse(strip_quotation_markers=False)

    name = sections_file_parser.get_value("Name", "Language")
    if not name:
        raise LanguageGrammarError("{0} | '{1}' attribute not found in '{2}' file!".format(__name__,
                                                                                           "Language|Name",
                                                                                           grammar_file))

    extensions = sections_file_parser.get_value("Extensions", "Language")
    if not extensions:
        raise LanguageGrammarError("{0} | '{1}' attribute not found in '{2}' file!".format(__name__,
                                                                                           "Language|Extensions",
                                                                                           grammar_file))

    highlighter = get_object_from_language_accelerators(sections_file_parser.get_value("Highlighter", "Accelerators"))
    completer = get_object_from_language_accelerators(sections_file_parser.get_value("Completer", "Accelerators"))
    pre_input_accelerators = sections_file_parser.get_value("PreInputAccelerators", "Accelerators")
    pre_input_accelerators = pre_input_accelerators and [get_object_from_language_accelerators(accelerator)
                                                         for accelerator in pre_input_accelerators.split("|")] or ()
    post_input_accelerators = sections_file_parser.get_value("PostInputAccelerators", "Accelerators")
    post_input_accelerators = post_input_accelerators and [get_object_from_language_accelerators(accelerator)
                                                           for accelerator in post_input_accelerators.split("|")] or ()

    visual_accelerators = sections_file_parser.get_value("VisualAccelerators", "Accelerators")
    visual_accelerators = visual_accelerators and [get_object_from_language_accelerators(accelerator)
                                                   for accelerator in visual_accelerators.split("|")] or ()

    indent_marker = sections_file_parser.section_exists("Syntax") and sections_file_parser.get_value("IndentMarker",
                                                                                                     "Syntax") or \
                    DEFAULT_INDENT_MARKER
    comment_marker = sections_file_parser.section_exists("Syntax") and \
                     sections_file_parser.get_value("CommentMarker", "Syntax") or ""
    comment_block_marker_start = sections_file_parser.section_exists("Syntax") and \
                                 sections_file_parser.get_value("CommentBlockMarkerStart", "Syntax") or ""
    comment_block_marker_end = sections_file_parser.section_exists("Syntax") and \
                               sections_file_parser.get_value("CommentBlockMarkerEnd", "Syntax") or ""
    symbols_pairs = sections_file_parser.section_exists("Syntax") and \
                    sections_file_parser.get_value("SymbolsPairs", "Syntax") or {}

    if symbols_pairs:
        associated_pairs = foundations.data_structures.Lookup()
        for pair in symbols_pairs.split("|"):
            associated_pairs[pair[0]] = pair[1]
        symbols_pairs = associated_pairs

    indentation_symbols = sections_file_parser.section_exists("Syntax") and \
                          sections_file_parser.get_value("IndentationSymbols", "Syntax")
    indentation_symbols = indentation_symbols and indentation_symbols.split("|") or ()

    rules = []
    attributes = sections_file_parser.sections.get("Rules")
    if attributes:
        for attribute in sections_file_parser.sections["Rules"]:
            pattern = sections_file_parser.get_value(attribute, "Rules")
            rules.append(umbra.ui.highlighters.Rule(name=foundations.namespace.remove_namespace(attribute),
                                                    pattern=QRegExp(pattern)))

    tokens = []
    dictionary = sections_file_parser.get_value("Dictionary", "Accelerators")
    if dictionary:
        dictionary_file = os.path.join(os.path.dirname(grammar_file), dictionary)
        if foundations.common.path_exists(dictionary_file):
            with open(dictionary_file, "r") as file:
                for line in iter(file):
                    line = line.strip()
                    line and tokens.append(line)
        else:
            LOGGER.warning(
                "!> {0} | '{1}' language dictionary file doesn't exists and will be skipped!".format(__name__,
                                                                                                     dictionary_file))

    theme = get_object_from_language_accelerators(sections_file_parser.get_value("Theme", "Accelerators")) or \
            umbra.ui.highlighters.DEFAULT_THEME

    attributes = {"name": name,
                  "file": grammar_file,
                  "parser": sections_file_parser,
                  "extensions": extensions,
                  "highlighter": highlighter,
                  "completer": completer,
                  "pre_input_accelerators": pre_input_accelerators,
                  "post_input_accelerators": post_input_accelerators,
                  "visual_accelerators": visual_accelerators,
                  "indent_marker": indent_marker,
                  "comment_marker": comment_marker,
                  "comment_block_marker_start": comment_block_marker_start,
                  "comment_block_marker_end": comment_block_marker_end,
                  "symbols_pairs": symbols_pairs,
                  "indentation_symbols": indentation_symbols,
                  "rules": rules,
                  "tokens": tokens,
                  "theme": theme}

    for attribute, value in sorted(attributes.iteritems()):
        if attribute == "rules":
            LOGGER.debug("> Registered '{0}' syntax rules.".format(len(value)))
        elif attribute == "tokens":
            LOGGER.debug("> Registered '{0}' completion tokens.".format(len(value)))
        else:
            LOGGER.debug("> Attribute: '{0}', Value: '{1}'.".format(attribute, value))

    return Language(**attributes)