fastparselite
Version:
Super simple & fast DSL parser for lightweight config-like data using custom syntax.
121 lines (97 loc) • 3.04 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 convertValue(raw) {
if (raw === "true") return true;
if (raw === "false") return false;
if (raw === "null") return null;
if (!isNaN(raw)) return Number(raw);
if (raw.startsWith('"') && raw.endsWith('"')) {
return raw.slice(1, -1);
}
return raw;
}
function parseObjectBlock(content) {
const obj = {};
let i = 0;
while (i < content.length) {
if (content[i] === "\n" || content[i] === " ") {
i++;
continue;
}
const keyMatch = content.slice(i).match(/^(\w+):/);
if (!keyMatch) break;
const key = keyMatch[1];
i += key.length + 1;
while (content[i] === " ") i++;
// Handle 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;
}
// Handle arrays
else if (content[i] === "[") {
const end = content.indexOf("]", i);
const raw = content.slice(i + 1, end);
obj[key] = raw.split(",").map(s => convertValue(s.trim()));
i = end + 1;
}
// Handle strings or primitives
else {
let end = content.indexOf("\n", i);
if (end === -1) end = content.length;
let value = content.slice(i, end).trim();
obj[key] = convertValue(value);
i = end + 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 = "", res = {}) {
for (let key in obj) {
const value = obj[key];
const newKey = prefix ? `${prefix}_${key}` : key;
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
flatten(value, newKey, res);
} else {
res[newKey] = value;
}
}
return res;
}
// Sample Usage
const input = fs.readFileSync("sample.ld", "utf8");
const result = parseLiteData(input);
console.log(result);
const flatDemo = flatten(result.demo);
console.log("Demo name:", flatDemo.name);
const flatUser = flatten(result.user);
console.log("User name:", flatUser.name);
console.log("User active:", flatUser.active);
console.log("User address city:", flatUser.address_city);
console.log("User address wait:", flatUser.address_wait);
console.log("Latitude:", flatUser.address_location_lat);