Last active
August 31, 2024 21:04
-
-
Save SpaghettDev/3744581418c69560713cfb36101836b0 to your computer and use it in GitHub Desktop.
C++ function arguments parser in python (no regex real). From BromaIDA.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| CPP_TYPE_SPECIFIERS = ("unsigned", "signed") | |
| CPP_TYPE_QUALIFIERS = ("const", "volatile") | |
| def parse_str_args(args_str: str) -> list[tuple[str]]: | |
| """Mini parser that converts a string of arguments | |
| into a list of tuples in the form of ("type", "name"). | |
| Supports templates, named and unnamed arguments, | |
| as well as stuff like long long, const short int... | |
| Args: | |
| args_str (str) | |
| Returns: | |
| list[tuple[str]]: list of tuples in the form ("type", "name"). | |
| If the argument is unnamed, the "name" is an empty string. | |
| """ | |
| args_list: list[str] = [] | |
| argstype_list: list[tuple[str]] = [] | |
| cur_arg = "" | |
| nested_template_count = 0 | |
| for i, c in enumerate(args_str): | |
| if c == "<": | |
| nested_template_count += 1 | |
| elif c == ">": | |
| nested_template_count -= 1 | |
| if nested_template_count == 0 and (c == "," or i == len(args_str) - 1): | |
| if i == len(args_str) - 1: | |
| cur_arg += c | |
| # replace east pointer or reference to west pointer or reference | |
| # (~because east sucks~, I mean because then it'll be a part | |
| # of the name and not the type) | |
| arg = cur_arg.lstrip().replace(" &", "& ").replace(" *", "* ") | |
| parts = arg.split() | |
| # parts with no specifiers nor qualifiers | |
| # this isn't actually used to build the type, | |
| # its only to avoid stuff like "long long" | |
| # being interpreted as type: long, name: long | |
| parts_no_sq = arg.split() | |
| for x in CPP_TYPE_SPECIFIERS + CPP_TYPE_QUALIFIERS: | |
| if x in parts_no_sq: | |
| parts_no_sq.remove(x) | |
| if "long" in parts_no_sq: | |
| try: | |
| if parts_no_sq[parts_no_sq.index("long") + 1] == "long": | |
| parts_no_sq.pop(parts_no_sq.index("long") + 1) | |
| if parts_no_sq[parts_no_sq.index("long") + 1] == "int": | |
| parts_no_sq.pop(parts_no_sq.index("long") + 1) | |
| except: pass | |
| if "short" in parts_no_sq: | |
| try: | |
| if parts_no_sq[parts_no_sq.index("short") + 1] == "int": | |
| parts_no_sq.pop(parts_no_sq.index("short") + 1) | |
| except: pass | |
| arg_type: str | |
| arg_name: str | |
| if len(parts_no_sq) > 1 and \ | |
| not parts_no_sq[-1].endswith("*") and \ | |
| not parts_no_sq[-1].endswith("&"): | |
| arg_type = " ".join(parts[:-1]) | |
| arg_name = parts[-1] | |
| else: | |
| arg_type = " ".join(parts) | |
| arg_name = "" | |
| argstype_list.append((arg_type, arg_name)) | |
| cur_arg = "" | |
| continue | |
| cur_arg += c | |
| return argstype_list | |
| parse_str_args("std::string const&, char const*, std::map<std::string, std::string>&") | |
| # [('std::string const&', ''), ('char const*', ''), ('std::map<std::string, std::string>&', '')] | |
| parse_str_args("std::string a1, const char, long long int* a3") | |
| # [('std::string', 'a1'), ('const char', ''), ('long long int*', 'a3')] | |
| parse_str_args("const std::vector<int> &a1, volatile bool*, char *a3") | |
| # [('const std::vector<int>&', 'a1'), ('volatile bool*', ''), ('char*', 'a3')] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment