UNPKG

fastparselite

Version:

Super simple & fast DSL parser for lightweight config-like data using custom syntax.

118 lines (97 loc) 3.38 kB
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; const len = content.length; while (i < len) { // Skip whitespace and newlines while (i < len && (content[i] === ' ' || content[i] === '\n' || content[i] === '\r')) i++; if (i >= len) break; // Extract key const keyMatch = content.slice(i).match(/^([a-zA-Z_]\w*):/); if (!keyMatch) break; const key = keyMatch[1]; i += key.length + 1; // Skip key and colon // Skip whitespace after colon while (i < len && (content[i] === ' ' || content[i] === '\n' || content[i] === '\r')) i++; if (i >= len) break; // Handle different value types if (content[i] === '{') { // Nested object let depth = 1; let j = i + 1; while (j < len && depth > 0) { if (content[j] === '{') depth++; else if (content[j] === '}') depth--; j++; } const innerContent = content.slice(i + 1, j - 1); obj[key] = parseObjectBlock(innerContent); i = j; } else if (content[i] === '[') { // Array let j = i + 1; while (j < len && content[j] !== ']') j++; const elements = content.slice(i + 1, j).split(',').map(el => el.trim()); obj[key] = elements; i = j + 1; } else { // Primitive value let j = i; while (j < len && content[j] !== '\n' && content[j] !== '\r' && content[j] !== ' ') j++; let value = content.slice(i, j).trim(); // Value type conversion if (value === 'true') value = true; else if (value === 'false') value = false; else if (!isNaN(value)) value = Number(value); else if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { value = value.slice(1, -1); } obj[key] = value; i = j; } } // console.log(obj); 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); console.log(result.user) // const flatUser = flatten(result.user); // console.log("User name:", flatUser.name); // console.log("User active:", flatUser.skills); // console.log("User address city:", flatUser.skills); // console.log("User address description:", flatUser.address_description); // console.log("Latitude:", flatUser.address_location_lat);