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_cifrom typing import Any, Dict, Union 183af6ab5fSopenharmony_cifrom line_iterator import LineIterator 193af6ab5fSopenharmony_cifrom runtime_collections import add_to_statistics, add_to_custom_yamls 203af6ab5fSopenharmony_cifrom parse_namespace import parse_namespace 213af6ab5fSopenharmony_cifrom parse_enum import parse_enum_class 223af6ab5fSopenharmony_cifrom parse_struct import parse_struct 233af6ab5fSopenharmony_cifrom parse_using import parse_using 243af6ab5fSopenharmony_cifrom parse_define import parse_define_macros 253af6ab5fSopenharmony_cifrom parse_class import parse_class, parse_friend_class, parse_template_prefix 263af6ab5fSopenharmony_cifrom parse_method import parse_method_or_constructor 273af6ab5fSopenharmony_cifrom parse_arguments import parse_argument 283af6ab5fSopenharmony_cifrom log_tools import warning_log 293af6ab5fSopenharmony_ci 303af6ab5fSopenharmony_ci 313af6ab5fSopenharmony_cidef deep_copy(data: Any) -> Any: 323af6ab5fSopenharmony_ci if isinstance(data, (dict, list)): 333af6ab5fSopenharmony_ci return data.copy() 343af6ab5fSopenharmony_ci return data 353af6ab5fSopenharmony_ci 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_ciclass CppParser: 383af6ab5fSopenharmony_ci def __init__(self, data: str, namespace: str = "", parent_class_name: str = ""): 393af6ab5fSopenharmony_ci self.it = LineIterator(data) 403af6ab5fSopenharmony_ci self.parsed: Any = None 413af6ab5fSopenharmony_ci self.res: Dict[str, Any] = {} 423af6ab5fSopenharmony_ci self.template: Union[str, None] = None 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_ci self.parent_class_name = parent_class_name 453af6ab5fSopenharmony_ci self.namespace = namespace 463af6ab5fSopenharmony_ci self.current_modifier = "" 473af6ab5fSopenharmony_ci 483af6ab5fSopenharmony_ci def parse(self) -> Dict[str, Any]: # pylint: disable=R0912 493af6ab5fSopenharmony_ci 503af6ab5fSopenharmony_ci while self.it.next_line(): 513af6ab5fSopenharmony_ci # Skip "#include", "#ifndef", "#undef", "template" 523af6ab5fSopenharmony_ci 533af6ab5fSopenharmony_ci if self.it.is_skip_line(): 543af6ab5fSopenharmony_ci add_to_statistics("skip", self.it.current_line) 553af6ab5fSopenharmony_ci 563af6ab5fSopenharmony_ci elif self.it.is_template(): 573af6ab5fSopenharmony_ci self.it.end, self.template = parse_template_prefix(self.it.data, self.it.start) 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_ci # Namespaces 603af6ab5fSopenharmony_ci elif self.it.is_namespace(): 613af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_namespace(self.it.data, self.it.start) 623af6ab5fSopenharmony_ci self.res_update() 633af6ab5fSopenharmony_ci 643af6ab5fSopenharmony_ci # Enum class 653af6ab5fSopenharmony_ci elif self.it.is_enum(): 663af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_enum_class(self.it.data, self.it.start) 673af6ab5fSopenharmony_ci self.res_append_namespace() 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_ci # Struct 703af6ab5fSopenharmony_ci elif self.it.is_struct(): 713af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_struct(self.it.data, self.it.start) 723af6ab5fSopenharmony_ci self.res_append("structs") 733af6ab5fSopenharmony_ci 743af6ab5fSopenharmony_ci # Using 753af6ab5fSopenharmony_ci elif self.it.is_using(): 763af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_using(self.it.data, self.it.start) 773af6ab5fSopenharmony_ci self.res_append_in_modifier("usings") 783af6ab5fSopenharmony_ci 793af6ab5fSopenharmony_ci # define macros (from class parser) 803af6ab5fSopenharmony_ci elif self.it.is_define_macro(): 813af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_define_macros(self.it.data, self.it.start) 823af6ab5fSopenharmony_ci self.res_append("macros") 833af6ab5fSopenharmony_ci 843af6ab5fSopenharmony_ci # Known macroses (from class parser) 853af6ab5fSopenharmony_ci elif self.it.is_known_macros(): 863af6ab5fSopenharmony_ci self.parsed = self.it.current_line 873af6ab5fSopenharmony_ci self.res_append("known_macroses") 883af6ab5fSopenharmony_ci 893af6ab5fSopenharmony_ci # Private, public, protected modifier (from class parser) 903af6ab5fSopenharmony_ci elif self.it.is_access_modifier(): 913af6ab5fSopenharmony_ci self.update_access_modifier() 923af6ab5fSopenharmony_ci 933af6ab5fSopenharmony_ci # Friend class 943af6ab5fSopenharmony_ci elif self.it.is_firend_class(): 953af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_friend_class(self.it.data, self.it.start) 963af6ab5fSopenharmony_ci self.res_append("friends") 973af6ab5fSopenharmony_ci 983af6ab5fSopenharmony_ci # Class forward declaration 993af6ab5fSopenharmony_ci elif self.it.is_class_forward_decl(): 1003af6ab5fSopenharmony_ci self.parsed = self.it.current_line.replace("class", "").strip(" ;") 1013af6ab5fSopenharmony_ci self.res_append("class_forward_declaration") 1023af6ab5fSopenharmony_ci 1033af6ab5fSopenharmony_ci # Class definition 1043af6ab5fSopenharmony_ci elif self.it.is_class_definition(): 1053af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_class( 1063af6ab5fSopenharmony_ci self.it.data, self.it.start, self.namespace, self.parent_class_name 1073af6ab5fSopenharmony_ci ) 1083af6ab5fSopenharmony_ci self.res_append_class_definition() 1093af6ab5fSopenharmony_ci 1103af6ab5fSopenharmony_ci # Function, method or constructor 1113af6ab5fSopenharmony_ci elif self.it.is_method_or_constructor(): 1123af6ab5fSopenharmony_ci self.it.end, self.parsed = parse_method_or_constructor(self.it.data, self.it.start) 1133af6ab5fSopenharmony_ci self.res_append_method_or_constructor() 1143af6ab5fSopenharmony_ci 1153af6ab5fSopenharmony_ci # Field 1163af6ab5fSopenharmony_ci elif self.it.is_field(): 1173af6ab5fSopenharmony_ci self.parsed = parse_argument(self.it.data[self.it.start : self.it.next_semicolon]) 1183af6ab5fSopenharmony_ci self.it.end = self.it.next_semicolon 1193af6ab5fSopenharmony_ci self.res_append_field() 1203af6ab5fSopenharmony_ci 1213af6ab5fSopenharmony_ci else: 1223af6ab5fSopenharmony_ci add_to_statistics("unreachable", self.it.current_line) 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ci return self.res 1253af6ab5fSopenharmony_ci 1263af6ab5fSopenharmony_ci def res_append(self, key: str) -> None: 1273af6ab5fSopenharmony_ci if not self.parsed: 1283af6ab5fSopenharmony_ci return 1293af6ab5fSopenharmony_ci 1303af6ab5fSopenharmony_ci self.parsed_update_template() 1313af6ab5fSopenharmony_ci if key not in self.res: 1323af6ab5fSopenharmony_ci self.res[key] = [] 1333af6ab5fSopenharmony_ci self.res[key].append(deep_copy(self.parsed)) 1343af6ab5fSopenharmony_ci 1353af6ab5fSopenharmony_ci def res_append_in_modifier(self, key: str) -> None: 1363af6ab5fSopenharmony_ci if not self.parsed: 1373af6ab5fSopenharmony_ci return 1383af6ab5fSopenharmony_ci 1393af6ab5fSopenharmony_ci self.parsed_update_template() 1403af6ab5fSopenharmony_ci if self.current_modifier == "": 1413af6ab5fSopenharmony_ci if key == "usings": 1423af6ab5fSopenharmony_ci self.res_append("usings") 1433af6ab5fSopenharmony_ci return 1443af6ab5fSopenharmony_ci raise RuntimeError("Unreachable") 1453af6ab5fSopenharmony_ci 1463af6ab5fSopenharmony_ci if key not in self.res[self.current_modifier]: 1473af6ab5fSopenharmony_ci self.res[self.current_modifier][key] = [] 1483af6ab5fSopenharmony_ci 1493af6ab5fSopenharmony_ci self.res[self.current_modifier][key].append(deep_copy(self.parsed)) 1503af6ab5fSopenharmony_ci 1513af6ab5fSopenharmony_ci def res_update(self) -> None: 1523af6ab5fSopenharmony_ci if self.parsed: 1533af6ab5fSopenharmony_ci self.parsed_update_template() 1543af6ab5fSopenharmony_ci self.res.update(self.parsed) 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ci def res_append_namespace(self) -> None: 1573af6ab5fSopenharmony_ci self.parsed["namespace"] = self.namespace 1583af6ab5fSopenharmony_ci 1593af6ab5fSopenharmony_ci if self.parent_class_name != "": 1603af6ab5fSopenharmony_ci self.parsed["parent_class_name"] = self.parent_class_name 1613af6ab5fSopenharmony_ci 1623af6ab5fSopenharmony_ci if "flags" in self.parsed or "flag_unions" in self.parsed: 1633af6ab5fSopenharmony_ci self.res_append("enums") 1643af6ab5fSopenharmony_ci add_to_custom_yamls("allEnums", "enums", self.parsed) 1653af6ab5fSopenharmony_ci 1663af6ab5fSopenharmony_ci def update_access_modifier(self) -> None: 1673af6ab5fSopenharmony_ci if self.parent_class_name == "": 1683af6ab5fSopenharmony_ci raise RuntimeError("Found modifier not in class") 1693af6ab5fSopenharmony_ci self.current_modifier = self.it.current_line.strip(" :") 1703af6ab5fSopenharmony_ci if self.current_modifier not in self.res: 1713af6ab5fSopenharmony_ci self.res[self.current_modifier] = {} 1723af6ab5fSopenharmony_ci 1733af6ab5fSopenharmony_ci def res_append_method_or_constructor(self) -> None: 1743af6ab5fSopenharmony_ci # Constructor 1753af6ab5fSopenharmony_ci if self.parsed["name"] == self.parent_class_name: 1763af6ab5fSopenharmony_ci self.res_append_in_modifier("constructors") 1773af6ab5fSopenharmony_ci 1783af6ab5fSopenharmony_ci # Destructor 1793af6ab5fSopenharmony_ci elif self.parsed["name"] == "~" + self.parent_class_name: 1803af6ab5fSopenharmony_ci self.res_append_in_modifier("destructors") 1813af6ab5fSopenharmony_ci 1823af6ab5fSopenharmony_ci # Method 1833af6ab5fSopenharmony_ci elif self.current_modifier != "": 1843af6ab5fSopenharmony_ci self.res_append_in_modifier("methods") 1853af6ab5fSopenharmony_ci 1863af6ab5fSopenharmony_ci # Function 1873af6ab5fSopenharmony_ci else: 1883af6ab5fSopenharmony_ci self.res_append("functions") 1893af6ab5fSopenharmony_ci 1903af6ab5fSopenharmony_ci def res_append_field(self) -> None: 1913af6ab5fSopenharmony_ci # Class field 1923af6ab5fSopenharmony_ci if self.current_modifier != "": 1933af6ab5fSopenharmony_ci self.res_append_in_modifier("fields") 1943af6ab5fSopenharmony_ci 1953af6ab5fSopenharmony_ci # Top level variable 1963af6ab5fSopenharmony_ci else: 1973af6ab5fSopenharmony_ci self.res_append("vars") 1983af6ab5fSopenharmony_ci 1993af6ab5fSopenharmony_ci def res_append_class_definition(self) -> None: 2003af6ab5fSopenharmony_ci self.res_append("class_definitions") 2013af6ab5fSopenharmony_ci 2023af6ab5fSopenharmony_ci def parsed_update_template(self) -> None: 2033af6ab5fSopenharmony_ci if self.template and self.parsed: 2043af6ab5fSopenharmony_ci if isinstance(self.parsed, dict): 2053af6ab5fSopenharmony_ci self.parsed["template"] = self.template 2063af6ab5fSopenharmony_ci self.template = None 2073af6ab5fSopenharmony_ci else: 2083af6ab5fSopenharmony_ci warning_log("Skipping template for '" + self.parsed + "'") 209