Source: lib/compiler/expressionParser.js

/**
 * ExpressionParser is responsible for extracting state, computed properties,
 * and methods from Avenx component source code.
 */
class ExpressionParser {
    /**
     * Extracts the initial state from <state /> tags.
     * @param {string} content - The component source code.
     * @returns {Object} The extracted state object.
     */
    parseState(content) {
        const state = {};
        const match = content.match(/<state\s+([\s\S]*?)\s*\/>/);
        if (match) {
            const attrRegex = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
            let m;
            while ((m = attrRegex.exec(match[1])) !== null) {
                const k = m[1];
                const val = m[2] !== undefined ? m[2] : m[3];
                state[k] = this.#coerceValue(val);
            }
        }
        return state;
    }

    /**
     * Coerces a string value to its proper JavaScript type.
     * @param {string} val - The raw string value.
     * @returns {any} The coerced value.
     * @private
     */
    #coerceValue(val) {
        const trimmed = val.trim();
        if (trimmed === 'true') return true;
        if (trimmed === 'false') return false;
        if (trimmed === 'null') return null;
        if (trimmed !== '' && !isNaN(trimmed)) return Number(trimmed);
        
        try {
            return JSON.parse(val);
        } catch (e) {
            return val;
        }
    }

    /**
     * Extracts computed property definitions from <computed /> tags.
     * @param {string} content - The component source code.
     * @returns {Object} A map of computed property names to their expressions.
     */
    parseComputed(content) {
        const computed = {};
        const regex = /<computed\s+([\s\S]*?)\s*\/>/g;
        let m;
        while ((m = regex.exec(content)) !== null) {
            const attrRegex = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
            let attrMatch;
            let name = null;
            let value = null;
            while ((attrMatch = attrRegex.exec(m[1])) !== null) {
                const k = attrMatch[1];
                const val = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];
                if (k === 'name') name = val;
                if (k === 'value') value = val;
            }
            if (name && value !== null) {
                computed[name] = value;
            }
        }
        return computed;
    }

    /**
     * Extracts method definitions from <action /> tags.
     * @param {string} content - The component source code.
     * @returns {Object} A map of method names to their source code.
     */
    parseMethods(content) {
        const methods = {};
        const actionRegex = /<action\s+name\s*=\s*(?:"(\w+)"|'(\w+)')\s*>([\s\S]*?)<\/action>/g;
        let m;
        while ((m = actionRegex.exec(content)) !== null) {
            const name = m[1] || m[2];
            methods[name] = m[3].trim();
        }
        return methods;
    }
}

module.exports = ExpressionParser;