Files
PatchGen/PdFileFormat/syntaxCheck.py
AnxiousAnt 3eb4e7ef87 upload
2024-07-10 01:35:45 +05:30

171 lines
5.1 KiB
Python

def read_pd_file(file_path):
"""
Reads a .pd file and splits it into individual records.
Parameters:
- file_path (str): Path to the .pd file.
Returns:
- records (list): List of records, where each record is a dictionary with
'chunk_type', 'element_type', and 'parameters'.
"""
records = []
with open(file_path, 'r') as file:
for line in file:
# Strip the line endings
line = line.strip()
# Skip empty lines
if not line:
continue
# Check if the line ends with a semicolon and starts with '#'
if not line.endswith(';') or not line.startswith('#'):
print(f"Syntax error: Line does not start with '#' or end with ';': {line}")
continue
# Remove the leading '#' and trailing ';'
line = line[1:-1].strip()
# Split the line into parts
parts = line.split()
if len(parts) < 2:
print(f"Syntax error: Insufficient parts in the line: {line}")
continue
# Extract chunk type and element type
chunk_type = parts[0]
element_type = parts[1]
parameters = parts[2:]
# Append to the records list
records.append({
'chunk_type': chunk_type,
'element_type': element_type,
'parameters': parameters,
'original_line': line # Store the original line for later display
})
return records
def validate_canvas(parameters):
"""
Validates the parameters of a 'canvas' element.
Parameters:
- parameters (list): List of parameters for the 'canvas' element.
Returns:
- errors (list): List of error messages.
"""
errors = []
if len(parameters) != 6:
errors.append(f"Canvas element must have exactly 6 parameters, found {len(parameters)}.")
return errors
try:
x_pos = int(parameters[0])
y_pos = int(parameters[1])
x_size = int(parameters[2])
y_size = int(parameters[3])
except ValueError:
errors.append("Canvas positions and sizes must be integers.")
name = parameters[4]
try:
open_on_load = int(parameters[5])
if open_on_load not in {0, 1}:
errors.append("Canvas 'open_on_load' flag must be 0 or 1.")
except ValueError:
errors.append("Canvas 'open_on_load' flag must be an integer (0 or 1).")
return errors
def validate_pd_records(records):
"""
Validates the structure and parameters of the parsed .pd records.
Parameters:
- records (list): List of records parsed from a .pd file.
Returns:
- errors (list): List of error messages.
"""
errors = []
valid_chunk_types = {"X", "N", "A"}
valid_element_types = {
"array", "connect", "coords", "floatatom", "msg", "obj", "bng", "tgl",
"nbx", "vsl", "hsl", "vradio", "hradio", "vu", "cnv", "pd", "restore",
"symbolatom", "text", "canvas"
}
for i, record in enumerate(records):
chunk_type = record['chunk_type']
element_type = record['element_type']
parameters = record['parameters']
if chunk_type not in valid_chunk_types:
errors.append(f"Record {i}: Invalid chunk type '{chunk_type}'.")
if element_type not in valid_element_types:
errors.append(f"Record {i}: Invalid element type '{element_type}'.")
# Detailed validation for specific element types
if element_type == "canvas":
canvas_errors = validate_canvas(parameters)
if canvas_errors:
errors.extend([f"Record {i}: {error}" for error in canvas_errors])
return errors
def display_with_errors(file_path, errors):
"""
Displays the content of a .pd file with errors highlighted and explained.
Parameters:
- file_path (str): Path to the .pd file.
- records (list): List of records parsed from a .pd file.
- errors (list): List of error messages.
"""
with open(file_path, 'r') as file:
lines = file.readlines()
error_indices = [int(error.split()[1].strip(":")) for error in errors]
for i, line in enumerate(lines):
print(line.strip())
if i in error_indices:
for error in errors:
if int(error.split()[1].strip(":")) == i:
print(f" >> Error: {error}")
# Writing the sample file content to 'sample.pd'
sample_pd_patch = """
#N canvas 0 0 450 sample_patch 1;
#X obj 50 50 osc~ 440;
hey!
#X obj 50 100 dac~;
#N canvas dfa;
#X connect 0 0 1 0;
#MDMF loll fadlkf:
"""
with open('sample.pd', 'w') as file:
file.write(sample_pd_patch.strip())
# Reading and validating the sample file
file_path = 'sample.pd'
records = read_pd_file(file_path)
errors = validate_pd_records(records)
if errors:
display_with_errors(file_path, errors)
else:
print("No syntax errors found.")
print(errors)