13af6ab5fSopenharmony_ci#!/usr/bin/env python3
23af6ab5fSopenharmony_ci# coding=utf-8
33af6ab5fSopenharmony_ci#
43af6ab5fSopenharmony_ci# Copyright (c) 2024 Huawei Device Co., Ltd.
53af6ab5fSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
63af6ab5fSopenharmony_ci# you may not use this file except in compliance with the License.
73af6ab5fSopenharmony_ci# You may obtain a copy of the License at
83af6ab5fSopenharmony_ci#
93af6ab5fSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0
103af6ab5fSopenharmony_ci#
113af6ab5fSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
123af6ab5fSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
133af6ab5fSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
143af6ab5fSopenharmony_ci# See the License for the specific language governing permissions and
153af6ab5fSopenharmony_ci# limitations under the License.
163af6ab5fSopenharmony_ci
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci"""
193af6ab5fSopenharmony_ciProvides:
203af6ab5fSopenharmony_ci- parse_type
213af6ab5fSopenharmony_ci- parse_argument
223af6ab5fSopenharmony_ci- parse_arguments
233af6ab5fSopenharmony_ci"""
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_cifrom typing import Tuple, List, Any, Dict
263af6ab5fSopenharmony_cifrom log_tools import warning_log
273af6ab5fSopenharmony_cifrom cpp_keywords import modifiers_list
283af6ab5fSopenharmony_cifrom text_tools import (
293af6ab5fSopenharmony_ci    find_first_of_characters,
303af6ab5fSopenharmony_ci    find_first_not_restricted_character,
313af6ab5fSopenharmony_ci    find_scope_borders,
323af6ab5fSopenharmony_ci    smart_find_first_of_characters,
333af6ab5fSopenharmony_ci    rfind_first_not_restricted_character,
343af6ab5fSopenharmony_ci    smart_split_by,
353af6ab5fSopenharmony_ci    rfind_first_of_characters,
363af6ab5fSopenharmony_ci)
373af6ab5fSopenharmony_ci
383af6ab5fSopenharmony_ci
393af6ab5fSopenharmony_cidef parse_type(data: str) -> dict:
403af6ab5fSopenharmony_ci    data = data.strip(" \n")
413af6ab5fSopenharmony_ci    if len(data) > 100:
423af6ab5fSopenharmony_ci        warning_log("Parsing big type!\n---\n" + data + "\n---\n")
433af6ab5fSopenharmony_ci
443af6ab5fSopenharmony_ci    if data == "":
453af6ab5fSopenharmony_ci        return {}
463af6ab5fSopenharmony_ci
473af6ab5fSopenharmony_ci    res: Dict[str, Any] = {}
483af6ab5fSopenharmony_ci    current_pos = extract_type_name(data, res)
493af6ab5fSopenharmony_ci
503af6ab5fSopenharmony_ci    for modifier in modifiers_list:
513af6ab5fSopenharmony_ci        if data.find(modifier, current_pos) != -1:
523af6ab5fSopenharmony_ci            if "other_modifiers" not in res:
533af6ab5fSopenharmony_ci                res["other_modifiers"] = ""
543af6ab5fSopenharmony_ci
553af6ab5fSopenharmony_ci            res["other_modifiers"] = f"{res['other_modifiers']} {modifier}".strip(" ")
563af6ab5fSopenharmony_ci
573af6ab5fSopenharmony_ci    # Weakness (<>)
583af6ab5fSopenharmony_ci    start_of_parenthes = data.find("(")
593af6ab5fSopenharmony_ci    if start_of_parenthes != -1:
603af6ab5fSopenharmony_ci        start_of_parenthes, end_of_parenthes = find_scope_borders(data, start_of_parenthes, "(")
613af6ab5fSopenharmony_ci        res["cast_from"] = data[start_of_parenthes + 1 : end_of_parenthes]
623af6ab5fSopenharmony_ci        current_pos = end_of_parenthes + 1
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_ci    # Template in arg
653af6ab5fSopenharmony_ci    template_open_pos = data.find("<", current_pos)
663af6ab5fSopenharmony_ci    if template_open_pos != -1:
673af6ab5fSopenharmony_ci        template_open_pos, template_close_pos = find_scope_borders(data, 0, "<")
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci        offset, res["template_args"] = parse_arguments(data[template_open_pos + 1 : template_close_pos], 0, "types")
703af6ab5fSopenharmony_ci        current_pos = template_open_pos + 1 + offset + 1
713af6ab5fSopenharmony_ci
723af6ab5fSopenharmony_ci    # Ptr
733af6ab5fSopenharmony_ci    ptr_start = data.find("*", current_pos)
743af6ab5fSopenharmony_ci    if ptr_start != -1:
753af6ab5fSopenharmony_ci
763af6ab5fSopenharmony_ci        ptr_end = find_first_not_restricted_character("*", data, ptr_start)
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ci        res["ptr_depth"] = ptr_end - ptr_start
793af6ab5fSopenharmony_ci        current_pos = ptr_end
803af6ab5fSopenharmony_ci
813af6ab5fSopenharmony_ci    # Ref
823af6ab5fSopenharmony_ci    ref_start = data.find("&", current_pos)
833af6ab5fSopenharmony_ci    if ref_start != -1:
843af6ab5fSopenharmony_ci
853af6ab5fSopenharmony_ci        ref_end = find_first_not_restricted_character("&", data, ref_start)
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci        res["ref_depth"] = ref_end - ref_start
883af6ab5fSopenharmony_ci        current_pos = ref_end
893af6ab5fSopenharmony_ci
903af6ab5fSopenharmony_ci    postfix = data[current_pos:].strip(" \n")
913af6ab5fSopenharmony_ci    if postfix != "":
923af6ab5fSopenharmony_ci        res["postfix"] = postfix
933af6ab5fSopenharmony_ci
943af6ab5fSopenharmony_ci    return res
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_cidef extract_type_name(data: str, res: Dict[str, Any]) -> int:
983af6ab5fSopenharmony_ci    prefix_modifiers = ""
993af6ab5fSopenharmony_ci    type_name_start = 0
1003af6ab5fSopenharmony_ci    type_name_end = find_first_of_characters(" <([{&*", data, type_name_start)
1013af6ab5fSopenharmony_ci    type_name = data[type_name_start:type_name_end].strip(" \n")
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_ci    # Extract type name
1043af6ab5fSopenharmony_ci    while type_name in modifiers_list or type_name == "":
1053af6ab5fSopenharmony_ci        prefix_modifiers += f" {type_name}"
1063af6ab5fSopenharmony_ci
1073af6ab5fSopenharmony_ci        type_name_start = find_first_not_restricted_character(" <*", data, type_name_end)
1083af6ab5fSopenharmony_ci        type_name_end = find_first_of_characters(" <(*", data, type_name_start)
1093af6ab5fSopenharmony_ci
1103af6ab5fSopenharmony_ci        if type_name_start == len(data):
1113af6ab5fSopenharmony_ci            type_name = ""
1123af6ab5fSopenharmony_ci            break
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci        type_name = data[type_name_start:type_name_end].strip(" \n")
1153af6ab5fSopenharmony_ci
1163af6ab5fSopenharmony_ci    # 'varbinder::LocalVariable' -> 'LocalVariable'
1173af6ab5fSopenharmony_ci    if type_name.find("::") != -1:
1183af6ab5fSopenharmony_ci        namespace = type_name[: type_name.rfind("::")]
1193af6ab5fSopenharmony_ci        type_name = type_name[type_name.rfind("::") + 2 :]
1203af6ab5fSopenharmony_ci        res["namespace"] = namespace
1213af6ab5fSopenharmony_ci
1223af6ab5fSopenharmony_ci    if type_name != "":
1233af6ab5fSopenharmony_ci        res["name"] = type_name
1243af6ab5fSopenharmony_ci
1253af6ab5fSopenharmony_ci    prefix_modifiers = prefix_modifiers.strip(" ")
1263af6ab5fSopenharmony_ci    if prefix_modifiers != "":
1273af6ab5fSopenharmony_ci        res["prefix"] = prefix_modifiers
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci    return type_name_end
1303af6ab5fSopenharmony_ci
1313af6ab5fSopenharmony_ci
1323af6ab5fSopenharmony_cidef parse_argument(arg: str, mode: str = "args") -> Dict:
1333af6ab5fSopenharmony_ci    """
1343af6ab5fSopenharmony_ci    modes:
1353af6ab5fSopenharmony_ci        - args: <type> <var_name>
1363af6ab5fSopenharmony_ci        - types: <only_type>
1373af6ab5fSopenharmony_ci    """
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci    res: Dict[str, Any] = {}
1403af6ab5fSopenharmony_ci    arg = arg.strip(" \n")
1413af6ab5fSopenharmony_ci
1423af6ab5fSopenharmony_ci    if arg == "":
1433af6ab5fSopenharmony_ci        return {}
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_ci    # Default value
1463af6ab5fSopenharmony_ci    equally_pos = smart_find_first_of_characters("=", arg, 0)
1473af6ab5fSopenharmony_ci    if equally_pos != len(arg):
1483af6ab5fSopenharmony_ci        default_value_start = find_first_not_restricted_character(" ", arg, equally_pos + 1)
1493af6ab5fSopenharmony_ci        default_value_end = rfind_first_not_restricted_character("\n; ", arg, len(arg) - 1)
1503af6ab5fSopenharmony_ci        res["default_value"] = arg[default_value_start : default_value_end + 1]
1513af6ab5fSopenharmony_ci
1523af6ab5fSopenharmony_ci        arg = arg[:equally_pos].strip(" \n")
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_ci    # Default constructor
1553af6ab5fSopenharmony_ci    if smart_find_first_of_characters("{", arg, 0) != len(arg):
1563af6ab5fSopenharmony_ci        start_of_constr, end_of_constr = find_scope_borders(arg)
1573af6ab5fSopenharmony_ci        res["default_constructor"] = arg[start_of_constr + 1 : end_of_constr]
1583af6ab5fSopenharmony_ci        arg = arg[:start_of_constr].strip(" \n")
1593af6ab5fSopenharmony_ci
1603af6ab5fSopenharmony_ci    # Name
1613af6ab5fSopenharmony_ci    if mode == "args":
1623af6ab5fSopenharmony_ci        name_start = rfind_first_of_characters(" *&>)}", arg, len(arg) - 1)
1633af6ab5fSopenharmony_ci        if name_start != len(arg) and name_start != len(arg) - 1:
1643af6ab5fSopenharmony_ci            name = arg[name_start + 1 :].strip(" \n")
1653af6ab5fSopenharmony_ci            if name != "":
1663af6ab5fSopenharmony_ci                res["name"] = name
1673af6ab5fSopenharmony_ci            else:
1683af6ab5fSopenharmony_ci                raise RuntimeError("Error! Argument without name!")
1693af6ab5fSopenharmony_ci
1703af6ab5fSopenharmony_ci        res["type"] = parse_type(arg[: name_start + 1])
1713af6ab5fSopenharmony_ci    else:
1723af6ab5fSopenharmony_ci        res["type"] = parse_type(arg)
1733af6ab5fSopenharmony_ci
1743af6ab5fSopenharmony_ci    return res
1753af6ab5fSopenharmony_ci
1763af6ab5fSopenharmony_ci
1773af6ab5fSopenharmony_cidef parse_arguments(data: str, start: int = 0, mode: str = "args") -> Tuple[int, List]:
1783af6ab5fSopenharmony_ci    """
1793af6ab5fSopenharmony_ci    data:
1803af6ab5fSopenharmony_ci        - (some arguments, ...) ... some code ...
1813af6ab5fSopenharmony_ci        - arg1, arg2, ..., arg_k
1823af6ab5fSopenharmony_ci    mode:
1833af6ab5fSopenharmony_ci        - args: TYPE ARG_NAME, ...
1843af6ab5fSopenharmony_ci        - types: TYPE, ...
1853af6ab5fSopenharmony_ci    """
1863af6ab5fSopenharmony_ci    res = []
1873af6ab5fSopenharmony_ci
1883af6ab5fSopenharmony_ci    start_of_args = 0
1893af6ab5fSopenharmony_ci    end_of_args = len(data)
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci    if data[start] == "(":
1923af6ab5fSopenharmony_ci        start_of_args, end_of_args = find_scope_borders(data, start, "(")
1933af6ab5fSopenharmony_ci        start_of_args += 1
1943af6ab5fSopenharmony_ci
1953af6ab5fSopenharmony_ci    args = data[start_of_args:end_of_args]
1963af6ab5fSopenharmony_ci    args_list = smart_split_by(args, ",")
1973af6ab5fSopenharmony_ci
1983af6ab5fSopenharmony_ci    for arg in args_list:
1993af6ab5fSopenharmony_ci        parsed_arg = parse_argument(arg, mode)
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci        if parsed_arg:
2023af6ab5fSopenharmony_ci            res.append(parsed_arg)
2033af6ab5fSopenharmony_ci
2043af6ab5fSopenharmony_ci    return end_of_args, res
205