2021-08-29 12:37:27 +00:00
|
|
|
import re
|
|
|
|
|
2023-01-02 21:50:23 +00:00
|
|
|
# 0: full struct; 1: up to & including first []; 2 & 3: comments; 4: content between first {}
|
|
|
|
p_struct = re.compile(r'(\bstruct\b\s*[a-zA-Z0-9_\s]+\[])\s*' # 1st capturing group
|
|
|
|
r'(?:(?=(\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+))\2\s*)*' # 2nd capturing group
|
2021-08-29 12:37:27 +00:00
|
|
|
r'=\s*' # =
|
2023-01-02 21:50:23 +00:00
|
|
|
r'(?:(?=(\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+))\3\s*)*' # 3rd capturing group
|
2021-08-29 12:37:27 +00:00
|
|
|
r'{((?:.|[\r\n])*?)\{\s*NULL,\s*NULL,\s*NULL\s*(?:.|[\r\n])*?},?(?:.|[\r\n])*?};') # captures full struct, it's beginning and it's content
|
|
|
|
# 0: type name[]; 1: type; 2: name
|
2023-01-02 21:50:23 +00:00
|
|
|
p_type_name = re.compile(r'(\bretro_core_option_[a-zA-Z0-9_]+)\s*'
|
|
|
|
r'(\boption_cats([a-z_]{0,8})|\boption_defs([a-z_]*))\s*\[]')
|
2021-08-29 12:37:27 +00:00
|
|
|
# 0: full option; 1: key; 2: description; 3: additional info; 4: key/value pairs
|
|
|
|
p_option = re.compile(r'{\s*' # opening braces
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(\".*?\"|' # key start; group 1
|
|
|
|
r'[a-zA-Z0-9_]+\s*\((?:.|[\r\n])*?\)|'
|
|
|
|
r'[a-zA-Z0-9_]+\s*\[(?:.|[\r\n])*?]|'
|
|
|
|
r'[a-zA-Z0-9_]+\s*\".*?\")\s*' # key end
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(\".*?\")\s*' # description; group 2
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'((?:' # group 3
|
|
|
|
r'(?:NULL|\"(?:.|[\r\n])*?\")\s*' # description in category, info, info in category, category
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',?\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r')+)'
|
|
|
|
r'(?:' # defs only start
|
|
|
|
r'{\s*' # opening braces
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'((?:' # key/value pairs start; group 4
|
|
|
|
r'{\s*' # opening braces
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(?:NULL|\".*?\")\s*' # option key
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(?:NULL|\".*?\")\s*' # option value
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'}\s*' # closing braces
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',?\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r')*)' # key/value pairs end
|
|
|
|
r'}\s*' # closing braces
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',?\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(?:' # defaults start
|
|
|
|
r'(?:NULL|\".*?\")\s*' # default value
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',?\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r')*' # defaults end
|
|
|
|
r')?' # defs only end
|
|
|
|
r'},') # closing braces
|
|
|
|
# analyse option group 3
|
|
|
|
p_info = re.compile(r'(NULL|\"(?:.|[\r\n])*?\")\s*' # description in category, info, info in category, category
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',')
|
|
|
|
p_info_cat = re.compile(r'(NULL|\"(?:.|[\r\n])*?\")')
|
|
|
|
# analyse option group 4
|
|
|
|
p_key_value = re.compile(r'{\s*' # opening braces
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(NULL|\".*?\")\s*' # option key; 1
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r',\s*' # comma
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'(NULL|\".*?\")\s*' # option value; 2
|
|
|
|
r'(?:(?:\/\*(?:.|[\r\n])*?\*\/|\/\/.*[\r\n]+|#.*[\r\n]+)\s*)*'
|
|
|
|
r'}')
|
|
|
|
|
|
|
|
p_masked = re.compile(r'([A-Z_][A-Z0-9_]+)\s*(\"(?:"\s*"|\\\s*|.)*\")')
|
|
|
|
|
2023-01-02 21:50:23 +00:00
|
|
|
p_intl = re.compile(r'(\bstruct retro_core_option_definition \*option_defs_intl\[RETRO_LANGUAGE_LAST]) = {'
|
2021-08-29 12:37:27 +00:00
|
|
|
r'((?:.|[\r\n])*?)};')
|
2023-01-02 21:50:23 +00:00
|
|
|
p_set = re.compile(r'\bstatic INLINE void libretro_set_core_options\(retro_environment_t environ_cb\)'
|
2021-08-29 12:37:27 +00:00
|
|
|
r'(?:.|[\r\n])*?};?\s*#ifdef __cplusplus\s*}\s*#endif')
|
|
|
|
|
|
|
|
p_yaml = re.compile(r'"project_id": "[0-9]+".*\s*'
|
|
|
|
r'"api_token": "([a-zA-Z0-9]+)".*\s*'
|
|
|
|
r'"base_path": "\./intl".*\s*'
|
|
|
|
r'"base_url": "https://api\.crowdin\.com".*\s*'
|
|
|
|
r'"preserve_hierarchy": true.*\s*'
|
|
|
|
r'"files": \[\s*'
|
|
|
|
r'\{\s*'
|
|
|
|
r'"source": "/_us/\*\.json",.*\s*'
|
|
|
|
r'"translation": "/_%two_letters_code%/%original_file_name%",.*\s*'
|
|
|
|
r'"skip_untranslated_strings": true.*\s*'
|
|
|
|
r'},\s*'
|
|
|
|
r']')
|