UNPKG

fastparselite

Version:

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

143 lines (116 loc) 3.79 kB
const fs = require('fs'); function parseLiteData(text) { // First, remove all comments const cleanText = text.replace(/(#|\/\/).*$/gm, ''); const result = {}; // Split by blocks starting with @ const blocks = cleanText.split('@').slice(1); blocks.forEach(block => { const firstBrace = block.indexOf('{'); const lastBrace = block.lastIndexOf('}'); if (firstBrace === -1 || lastBrace === -1) return; const name = block.substring(0, firstBrace).trim(); const content = block.substring(firstBrace + 1, lastBrace).trim(); result[name] = parseBlockContent(content); }); return result; } function parseBlockContent(content) { const obj = {}; let currentPos = 0; const len = content.length; while (currentPos < len) { // Skip whitespace while (currentPos < len && isWhitespace(content[currentPos])) { currentPos++; } if (currentPos >= len) break; // Find key const keyMatch = content.slice(currentPos).match(/^([a-zA-Z_]\w*):/); if (!keyMatch) break; const key = keyMatch[1]; currentPos += key.length + 1; // Skip key and colon // Skip whitespace after colon while (currentPos < len && isWhitespace(content[currentPos])) { currentPos++; } if (currentPos >= len) break; // Determine value type if (content[currentPos] === '{') { // Nested object let depth = 1; let endPos = currentPos + 1; while (endPos < len && depth > 0) { if (content[endPos] === '{') depth++; if (content[endPos] === '}') depth--; endPos++; } const innerContent = content.substring(currentPos + 1, endPos - 1); obj[key] = parseBlockContent(innerContent); currentPos = endPos; } else if (content[currentPos] === '[') { // Array let endPos = currentPos + 1; while (endPos < len && content[endPos] !== ']') { endPos++; } const arrayContent = content.substring(currentPos + 1, endPos); obj[key] = arrayContent.split(',').map(item => convertValue(item.trim())); currentPos = endPos + 1; } else { // Primitive value let endPos = currentPos; while (endPos < len && !isWhitespace(content[endPos]) && content[endPos] !== '}') { endPos++; } const value = content.substring(currentPos, endPos).trim(); obj[key] = convertValue(value); currentPos = endPos; } } return obj; } function isWhitespace(char) { return char === ' ' || char === '\n' || char === '\r' || char === '\t'; } function convertValue(value) { if (value === 'true') return true; if (value === 'false') return false; if (!isNaN(value)) return Number(value); if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { return value.slice(1, -1); } return value; } // // Test with your exact sample // const input = ` // @user { // name: "Alice" // age: 25 // address: { // city: "Chennai" // location: { // lat: 13.08 // long: 80.27 // } // description: "something" // } // skills: [Python, JavaScript, C++] // active: true // } // @demo { // name: "dinesh" // } // `; // const parsed = parseLiteData(input); // console.log(parsed.user) // ======== Usage ========= const input = fs.readFileSync("sample.ld", "utf8"); const result = parseLiteData(input); const flatUser = flatten(result); // console.log("User name:", flatUser.name); console.log("User active:", flatUser.active); console.log("User address city:", flatUser.address_description);