fastparselite
Version:
Super simple & fast DSL parser for lightweight config-like data using custom syntax.
113 lines (93 loc) • 3.05 kB
JavaScript
const fs = require("fs");
function removeComments(text) {
return text
.split("\n")
.map(line => line.replace(/(#|\/\/).*/, "").trim())
.filter(line => line.length > 0)
.join("\n");
}
function parseObjectBlock(content) {
const obj = {};
let i = 0;
while (i < content.length) {
while (content[i] === "\n" || content[i] === " ") i++;
const keyMatch = content.slice(i).match(/^(\w+):/);
if (!keyMatch) break;
const key = keyMatch[1];
i += key.length + 1;
while (content[i] === " " || content[i] === "\n") i++;
// Nested object
if (content[i] === "{") {
let depth = 1;
let j = i + 1;
while (j < content.length && depth > 0) {
if (content[j] === "{") depth++;
else if (content[j] === "}") depth--;
j++;
}
const inner = content.slice(i + 1, j - 1);
obj[key] = parseObjectBlock(inner.trim());
i = j;
// Move to next line after closing }
while (content[i] === "\n" || content[i] === " ") i++;
}
// Array
else if (content[i] === "[") {
let j = i + 1;
while (j < content.length && content[j] !== "]") j++;
const inner = content.slice(i + 1, j);
obj[key] = inner.split(",").map(s => s.trim());
i = j + 1;
}
// Primitive
else {
let j = i;
while (j < content.length && content[j] !== "\n" && content[j] !== "\r") j++;
let value = content.slice(i, j).trim();
if (value.startsWith('"') && value.endsWith('"')) {
value = value.slice(1, -1);
} else if (value === "true") {
value = true;
} else if (value === "false") {
value = false;
} else if (!isNaN(value)) {
value = Number(value);
}
obj[key] = value;
i = j + 1;
}
}
return obj;
}
function parseLiteData(text) {
const cleanText = removeComments(text);
const data = {};
const blocks = cleanText.match(/@(\w+)\s*{([\s\S]*?)}/g);
if (!blocks) return data;
for (const block of blocks) {
const [, name, content] = block.match(/@(\w+)\s*{([\s\S]*)}/);
data[name] = parseObjectBlock(content.trim());
}
return data;
}
function flatten(obj, prefix = "", result = {}) {
for (const key in obj) {
const value = obj[key];
const newKey = prefix ? `${prefix}_${key}` : key;
if (typeof value === "object" && !Array.isArray(value)) {
flatten(value, newKey, result);
} else {
result[newKey] = value;
}
}
return result;
}
// ======== Usage =========
const input = fs.readFileSync("sample.ld", "utf8");
const result = parseLiteData(input);
const flatUser = flatten(result.user);
// console.log("User name:", flatUser.name);
console.log("User active:", flatUser.active);
console.log("User address city:", flatUser.address_description);
// console.log("User address wait:", flatUser.address_wait);
// console.log("Latitude:", flatUser.address_location_lat);