handleNDepthEntity = function(parsedContent, entityName, entityRoles, entityLines, range) {
    const SPACEASTABS = 4;
    addItemOrRoleIfNotPresent(parsedContent.LUISJsonStructure, LUISObjNameEnum.ENTITIES, entityName, entityRoles);
    let rootEntity = parsedContent.LUISJsonStructure.entities.find(item => item.name == entityName);
    rootEntity.explicitlyAdded = true;
    let defLine = range.Start.Line
    let baseTabLevel = 0;
    let entityIdxByLevel = [];
    let currentParentEntity = undefined;
    // process each entity line
    entityLines.forEach(child => {
        currentParentEntity = undefined;
        defLine++;
        let captureGroups = /^((?<leadingSpaces>[ ]*)|(?<leadingTabs>[\t]*))-\s*@\s*(?<instanceOf>[^\s]+) (?<entityName>(?:'[^']+')|(?:"[^"]+")|(?:[^ '"=]+))(?: uses?[fF]eatures? (?<features>[^=]+))?\s*=?\s*$/g;
        let groupsFound = captureGroups.exec(child);
        if (!groupsFound) {
            let errorMsg = `Invalid child entity definition found for "${child.trim()}". Child definitions must start with '- @' and only include a type, name and optionally one or more usesFeature(s) definition.`;
            const error = BuildDiagnostic({
                message: errorMsg,
                line: defLine
            });
            throw (new exception(retCode.errorCode.INVALID_INPUT, error.toString(), [error]));
        }
        let childEntityName = groupsFound.groups.entityName.replace(/^['"]/g, '').replace(/['"]$/g, '');
        let childEntityType = groupsFound.groups.instanceOf.trim();
        let childFeatures = groupsFound.groups.features ? groupsFound.groups.features.trim().split(/[,;]/g).map(item => item.trim()) : undefined;
        
        // Get current tab level
        let tabLevel = Math.ceil(groupsFound.groups.leadingSpaces !== undefined ? groupsFound.groups.leadingSpaces.length / SPACEASTABS : 0) || (groupsFound.groups.leadingTabs !== undefined ? groupsFound.groups.leadingTabs.length : 0);
        if (defLine === range.Start.Line + 1) {
            // remember the tab level at the first line of child definition
            baseTabLevel = tabLevel;
            // Push the ID of the parent since we are proessing the first child entity
            entityIdxByLevel.push({level : 0, entity : rootEntity});
        } 
        
        currentParentEntity = entityIdxByLevel.reverse().find(item => item.level == tabLevel - baseTabLevel);
        entityIdxByLevel.reverse();
        if (!currentParentEntity) {
            let errorMsg = `[ERROR] line ${defLine}: Invalid definition found for child "${child.trim()}". Parent of each child entity must be of type "${EntityTypeEnum.ML}".`;
            const error = BuildDiagnostic({
                message: errorMsg,
                line: defLine
            });
            throw (new exception(retCode.errorCode.INVALID_INPUT, error.toString(), [error]));
        }
        let context = {line : defLine, definition: child.trim()};
        if (groupsFound.groups.instanceOf.toLowerCase().trim() === EntityTypeEnum.SIMPLE) {
            pushNDepthChild(currentParentEntity.entity, childEntityName, context, childFeatures);
        } else if (groupsFound.groups.instanceOf.toLowerCase().trim() === EntityTypeEnum.ML) {
            pushNDepthChild(currentParentEntity.entity, childEntityName, context, childFeatures);
            let newParent = currentParentEntity.entity.children.find(item => item.name == childEntityName);
            // Push the ID of the parent since we are proessing the first child entity
            entityIdxByLevel.push({level : tabLevel - baseTabLevel + 1, entity : newParent});
        } else {
            pushNDepthChild(currentParentEntity.entity, childEntityName, context, childFeatures, childEntityType);
        }
    });
}
Helper to handle ndepth entity definition.
@param {Object} parsedContent 
@param {String} entityName 
@param {String[]} entityRoles 
@param {String[]} entityLines 
@param {Object} range