Skip to content

Instantly share code, notes, and snippets.

@erdesigns-eu
Last active October 4, 2023 14:30
Show Gist options
  • Save erdesigns-eu/b73107f55b4451601b2794b50a827774 to your computer and use it in GitHub Desktop.
Save erdesigns-eu/b73107f55b4451601b2794b50a827774 to your computer and use it in GitHub Desktop.
Parse Delphi DFM in JavaScript
const parseDFM = (text) => {
let result = null;
// Replace all returns with newlines
text = text.replace(/\r\n/g, '\n');
text = text.replace(/\r/g, '\n');
// Split into lines
const lines = text.split('\n');
let currentComponent = null;
let stack = [];
// Loop through lines
for (let i = 0; i < lines.length; i++) {
// Trim line
let line = lines[i].trim();
// Start of component
if (line.startsWith('object ')) {
const component = line.match(/^object (\w+): (\w+)$/);
if (component) {
// Create new component object
const newComponent = {
name: component[1],
className: component[2],
children: [],
};
if (currentComponent) {
// Add to children of current component
currentComponent.children.push(newComponent);
} else {
// Set as root component
result = newComponent;
}
// Push to stack and set as current component
stack.push(newComponent);
currentComponent = newComponent;
}
continue;
}
// End of component
if (line.startsWith('end') && stack.length > 0) {
// Pop from stack
currentComponent = stack.pop();
// Set current component to parent component
if (stack.length > 0) {
currentComponent = stack[stack.length - 1];
}
continue;
}
// Component property
const property = line.match(/^([\w.]+)\s*=\s*(.*)$/);
if (property) {
const value = property[2];
// If value is a string
if (value.startsWith("'") && value.endsWith("'")) {
// Remove quotes
property[2] = String(value.substring(1, value.length - 1));
}
// If value is a number
if (!isNaN(value)) {
// Convert to number
property[2] = Number(value);
}
// If value is a nil
if (value === 'nil') {
property[2] = null;
}
// If value is empty
if (value === '') {
property[2] = null;
}
// If value is a boolean
if (value === 'True') {
property[2] = true;
}
if (value === 'False') {
property[2] = false;
}
// If value is an array
if (value.startsWith('(') && value.endsWith(')')) {
// Remove brackets
property[2] = value.substring(1, value.length - 1);
// Split into array
property[2] = property[2].split(',').filter((entry) => !!entry);
}
// If value is a set
if (value.startsWith('[') && value.endsWith(']')) {
// Remove brackets
property[2] = value.substring(1, value.length - 1);
// Split into array
property[2] = property[2].split(',').filter((entry) => !!entry);
}
// If value is a dictionary
if (value.startsWith('{') && value.endsWith('}')) {
// Remove brackets
property[2] = value.substring(1, value.length - 1);
// Split into array
property[2] = property[2].split(',').filter((entry) => !!entry);
}
// If the property name contains a dot (.) then it is a sub-property
if (property[1].indexOf('.') > -1) {
// Split property name into parts
const parts = property[1].split('.');
// Get property name
const propertyName = parts[0];
// Get sub-property name
const subPropertyName = parts[1];
// Get current component property
const currentComponentProperty = currentComponent[propertyName];
// If current component property is not an object
if (typeof currentComponentProperty !== 'object') {
// Create new object
currentComponent[propertyName] = {};
}
// Add sub-property to current component property
currentComponent[propertyName][subPropertyName] = property[2];
continue;
}
// Add property to current component
currentComponent[property[1]] = property[2];
}
}
// Return result
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment