95 lines
3.5 KiB
Python
95 lines
3.5 KiB
Python
import os
|
|
import re
|
|
import yaml
|
|
|
|
# Regular expression to match .get<T>("a:b:c", x)
|
|
pattern = re.compile(r'\.get<([^>]+)>\("([^"]+)",\s*([^);]+)\)')
|
|
|
|
def parse_value(value, type_hint):
|
|
"""Converts values to appropriate types."""
|
|
value = value.strip()
|
|
|
|
# Handle common types
|
|
if type_hint in {"int", "long"}:
|
|
return int(value)
|
|
elif type_hint in {"float", "double"}:
|
|
return float(value)
|
|
elif value == "defaultDataDir":
|
|
return "data" # special case for defaultDataDir
|
|
elif type_hint == "bool":
|
|
return value.lower() in {"true", "1"}
|
|
elif value.startswith("'") and value.endswith("'"):
|
|
return value.strip("'") # Remove single quotes
|
|
elif value.startswith('"') and value.endswith('"'):
|
|
return value.strip('"') # Remove quotes for string literals
|
|
|
|
return value # Return as-is if unsure
|
|
|
|
def insert_into_dict(hierarchy_dict, keys, value, type_hint):
|
|
"""Recursively inserts values into a nested dictionary."""
|
|
key = keys.pop(0)
|
|
if not keys: # If last key, store value
|
|
hierarchy_dict[key] = parse_value(value, type_hint)
|
|
else:
|
|
if key not in hierarchy_dict:
|
|
hierarchy_dict[key] = {}
|
|
insert_into_dict(hierarchy_dict[key], keys, value, type_hint)
|
|
|
|
def scan_files(directory):
|
|
"""Scans all .cpp, .h, .c, and .hpp files in a directory recursively."""
|
|
hierarchy_dict = {}
|
|
|
|
for root, _, files in os.walk(directory):
|
|
for file in files:
|
|
if file.endswith(('.cpp', '.h', '.c', '.hpp')):
|
|
file_path = os.path.join(root, file)
|
|
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
for line in f:
|
|
match = pattern.search(line)
|
|
if match:
|
|
type_hint, hierarchy, value = match.groups()
|
|
keys = hierarchy.split(":")
|
|
if keys[0] == "Data" and keys[1] == "Dir":
|
|
continue # Skip Data:Dir as it is a special case
|
|
insert_into_dict(hierarchy_dict, keys, value, type_hint)
|
|
|
|
return hierarchy_dict
|
|
|
|
class QuotedString(str):
|
|
pass
|
|
|
|
def represent_quoted_string(dumper, data):
|
|
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
|
|
|
|
|
|
def save_yaml(data, output_file):
|
|
"""Saves the nested dictionary to a YAML file."""
|
|
yaml.add_representer(QuotedString, represent_quoted_string)
|
|
|
|
def quote_strings(data):
|
|
if isinstance(data, dict):
|
|
return {k: quote_strings(v) for k, v in data.items()}
|
|
elif isinstance(data, list):
|
|
return [quote_strings(item) for item in data]
|
|
elif isinstance(data, str):
|
|
return QuotedString(data)
|
|
else:
|
|
return data
|
|
|
|
data = quote_strings(data)
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
yaml.dump(data, f, default_flow_style=False, sort_keys=True, indent=2)
|
|
|
|
if __name__ == "__main__":
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description="Generate a YAML file with default configuration values.")
|
|
parser.add_argument("directory", help="Directory to scan for .cpp, .h, .c, and .hpp files.")
|
|
parser.add_argument("-o", "--output", help="Output file name.", default="defaults.yaml")
|
|
args = parser.parse_args()
|
|
|
|
extracted_data = scan_files(args.directory)
|
|
save_yaml(extracted_data, args.output)
|
|
|
|
print(f"✅ YAML file generated: {args.output}")
|
|
|