antlr | get antlr tool | antlr tree visitor | Search

This JavaScript code appears to be part of a parser or tree-traversal function that handles tasks such as special character handling, filtering object properties, and converting a tree-like data structure to a string representation. The main function, treeToStr, recursively traverses the tree, extracting information from statement objects and using parser objects to resolve rule names and input strings.

Run example

npm run import -- "antlr to html"

antlr to html

var importer = require('../Core');
var {selectDom} = importer.import("select tree")

//TODO: remove \u200b characters
var specialChars = (str) => {
    var special = {
        '&':'&',
        '<':'&lt;',
        '>':'&gt;',
        '"':'&quot;',
        "'":'&apos;'
    }
    Object.keys(special).forEach(s => {
        str = (str || '').replace(new RegExp(s, 'ig'), special[s])
    })
    return str
}

function filterObject(obj) {
  let result = {}
  for(var i in obj) {
    if(i == 'children' || i == 'parentCtx') {
      continue
    }
    result[i] = obj[i]
  }
  return result
}

function treeToStr(statement, parent, parser) {
    var {type, ruleIndex, start, stop, exception, strdata} = statement;

    if(typeof start == 'object') {
        statement['start'] = start.start
        statement['line'] = start.line
    }
    if(typeof stop == 'object') {
        statement['stop'] = stop.stop
    }

    if(!parser)
        parser = (statement.parentCtx ? statement.parentCtx.parser : statement.parser)


    if(typeof type == 'number') {
        type = parser.ruleNames[type]
    } else
    if(typeof ruleIndex == 'number') {
        type = parser.ruleNames[ruleIndex]
        statement.type = type
    }

    if(exception) {
        return ''
    }

    if(!strdata && statement.start && statement.stop && statement.type) {
        statement.strdata = parser.input.substring(statement.start, statement.stop + 1)
    }

    var result = ``, attrs = ``;
    var isList = true;
    for(var i in statement) {
        if(parseInt(i) + '' === i + '') {
            result += treeToStr(statement[i], parent, parser)
            continue;
        }
        if(i == 'parentCtx' || i == 'parser' || i[0] == '_' || i == 'exception' || i == 'source') {
            continue
        }

        if(i == 'strdata') {
            statement[i] = statement[i].split('\n')[0]
        }

        if(i == 'type' && typeof statement[i] == 'number') {
            statement[i] = parser.ruleNames[statement[i]]
        }

        isList = false;
        var jsType = typeof statement[i];
        if(jsType === 'object' && statement[i]) {
            jsType = Object.getPrototypeOf(statement[i]).constructor.name;
        }

        if(i == 'symbol' && jsType == 'vt') {
            continue
        }

        // if the property is an Object, print out as a child
        // TODO: replace this type property when converting other trees
        //   should be like getEl() treeToStr(() => el.type)
        if(statement[i] && typeof statement[i].type !== 'undefined'
           // or if the property is an Array,
           //   print them out as child elements
           || (Array.isArray(statement[i]) /* && statement[i].length
           && typeof statement[i][0].type !== 'undefined' */)
        ) {
            // print out the other keys just for fun matching
            attrs +=  `
${i}="" ${i}-type="${jsType}"`;
            result += `
${treeToStr(statement[i], i, parser)}`
            // output as child element and <-attr> elements
            //   for posterity, only child elements are return on the select,
            //   but attr elements can still be matched
        } else {
            // if the property is not an object, i.e. native types
            if(typeof statement[i] == 'object' && statement[i] !== null) {
                attrs +=  `
${i}="${specialChars(JSON.stringify(filterObject(statement[i])))}" ${i}-type="${jsType}"`
            } else if(typeof statement[i] !== 'string') {
                attrs +=  `
${i}="${specialChars(JSON.stringify(statement[i]))}" ${i}-type="${jsType}"`
            } else {
                attrs +=  `
${i}="${specialChars(statement[i])}" ${i}-type="${jsType}"`
            }
        }
    }
    
    return isList ? result : `
<${type}${attrs}${parent ? `
 parent-attr="${parent}"`: ``}>${result}</${type}>`
}

function treeToHtml(tree) {
    var body = treeToStr(tree);
    require('fs').writeFileSync('text.html', body)
    return selectDom('//BODY', '<BODY>' + body + '</BODY>');
}

module.exports = {treeToHtml}

What the code could have been:

const importer = require('../Core');
const { selectDom } = importer.import('select tree');

// Function to remove special characters from a string
const removeSpecialChars = (str) => {
    const specialCharsRegex = /&|<|>|"|'|/g;
    return str.replace(specialCharsRegex, (match) => {
        switch (match) {
            case '&':
                return '&amp;';
            case '<':
                return '&lt;';
            case '>':
                return '&gt;';
            case '"':
                return '&quot;';
            case "'":
                return '&apos;';
            default:
                return match;
        }
    });
};

// Function to filter out unwanted properties from an object
const filterObject = (obj) => {
    return Object.fromEntries(Object.entries(obj).filter(([key, value]) => key!== 'children' && key!== 'parentCtx'));
};

// Function to convert a tree statement to a string
const treeToStr = (statement, parent, parser) => {
    const { type, ruleIndex, start, stop, exception, strdata } = statement;

    if (typeof start === 'object') {
        statement['start'] = start.start;
        statement['line'] = start.line;
    }
    if (typeof stop === 'object') {
        statement['stop'] = stop.stop;
    }

    const parserNames = parser.ruleNames;
    if (!parser) {
        parser = statement.parentCtx?.parser?? statement.parser;
    }

    if (typeof type === 'number') {
        type = parserNames[type];
    } else if (typeof ruleIndex === 'number') {
        type = parserNames[ruleIndex];
        statement.type = type;
    }

    if (exception) {
        return '';
    }

    if (!strdata && statement.start && statement.stop && statement.type) {
        statement.strdata = parser.input.substring(statement.start, statement.stop + 1);
    }

    const result = [];
    const attrs = {};
    let isList = true;

    for (const [key, value] of Object.entries(statement)) {
        // Recursively convert child elements
        if (parseInt(key) + '' === key + '') {
            result.push(treeToStr(value, parent, parser));
            continue;
        }
        if (key === 'parentCtx' || key === 'parser' || key.startsWith('_') || key === 'exception' || key ==='source') {
            continue;
        }

        if (key ==='strdata') {
            statement[key] = statement[key].split('\n')[0];
        }

        if (key === 'type' && typeof statement[key] === 'number') {
            statement[key] = parserNames[statement[key]];
        }

        isList = false;
        const jsType = typeof value;

        if (jsType === 'object' && value) {
            jsType = Object.getPrototypeOf(value).constructor.name;
        }

        if (key ==='symbol' && jsType === 'Function') {
            continue;
        }

        // Convert objects and arrays to HTML
        if (statement[key] && typeof statement[key].type!== 'undefined' ||
            (Array.isArray(statement[key])) // TODO: uncomment this line
        ) {
            attrs[key] = { type: jsType };
            // Recursively convert child elements
            result.push(treeToStr(statement[key], key, parser));
            // Output as child element and <-attr> elements
            // TODO: uncomment this line
        } else {
            // Convert native types to HTML
            if (typeof value === 'object' && value!== null) {
                attrs[key] = { type: jsType };
                attrs[key].value = specialChars(JSON.stringify(filterObject(value)));
            } else if (typeof value!=='string') {
                attrs[key] = { type: jsType };
                attrs[key].value = specialChars(JSON.stringify(value));
            } else {
                attrs[key] = { type: jsType };
                attrs[key].value = specialChars(value);
            }
        }
    }

    // Output as child element or element with attributes
    if (isList) {
        return result.join('');
    }
    return `<${type}${Object.keys(attrs).map((key) => `${key}="${attrs[key].value}" ${key}-type="${attrs[key].type}""`).join('')}${parent? ` parent-attr="${parent}"`: ``}>${result.join('')}</${type}>`;
};

// Function to convert a tree to HTML
const treeToHtml = (tree) => {
    const body = treeToStr(tree);
    const fs = require('fs');
    fs.writeFileSync('text.html', body);
    return selectDom('//BODY', `<BODY>${body}</BODY>`);
};

module.exports = { treeToHtml };

Code Breakdown

This code appears to be a part of a parser or a tree-traversal function. It's written in JavaScript and uses Node.js's require function to import other modules. Here's a brief explanation of the code:

Importing Dependencies

var importer = require('../Core');
var {selectDom} = importer.import('select tree')

This code imports a module from ../Core and extracts the selectDom function from it.

Special Character Handling

var specialChars = (str) => {
    var special = {
        '&':'&amp;',
        '<':'&lt;',
        '>':'&gt;',
        '"':'&quot;',
        "'":'&apos;'
    }
    Object.keys(special).forEach(s => {
        str = (str || '').replace(new RegExp(s, 'ig'), special[s])
    })
    return str
}

This function takes a string as input and replaces special characters with their HTML entity equivalents. This is likely used to escape special characters in text data.

Filtering Object Properties

function filterObject(obj) {
  let result = {}
  for(var i in obj) {
    if(i == 'children' || i == 'parentCtx') {
      continue
    }
    result[i] = obj[i]
  }
  return result
}

This function takes an object as input and returns a new object with some properties filtered out. Specifically, it ignores properties named 'children' and 'parentCtx'.

Tree to String Conversion

function treeToStr(statement, parent, parser) {
    //...
}

This is the main function of interest. It takes a statement object, an optional parent object, and a parser object as input. It appears to recursively traverse a tree-like data structure, converting each statement to a string representation.

The function performs several tasks:

This function seems to be used to serialize a tree-like data structure into a human-readable string representation.