antlr | Cell 0 | test select jison on some quake 3 C code | Search

The selectCode function is an asynchronous function that detects the language of a file, parses it using ANTLR, transforms the parsed output into HTML, selects specific DOM elements, and returns the result as a string.

The selectCode function is an asynchronous function that performs language detection, ANTLR parsing, and HTML transformation on a given file. It catches any errors that occur during the parsing process and returns the result as a string, along with an error message if an error occurs.

Run example

npm run import -- "select antlr tree"

select antlr tree

import fs from 'fs'
//import path from 'path'
import antlr from 'antlr4'
const {selectDom} = importer.import("select tree")

//TODO: fix this with own transpiler because no one is going to share their hard work on StringTemplate4 code
/*
function toString(ctx, subctx) {
    var ast = (subctx || ctx)
    if(typeof ast.ownerDocument !== 'undefined') {
        ast = htmlToTree(ast)
    }
    //escodegen.attachComments(ast, ast.comments, ast.tokens, ast.whitespace)
    return escodegen.generate(ast, {
        comment: true,
        tokens: true,
        whitespace: true,
        format: {indent: {style: '    '}, quotes: 'single'}
    })
}
*/

let extToLang
let treeToHtml
let getParser
async function selectCode(descriptor, code, language) {
    if(!extToLang)
        extToLang = await importer.import("ext to lang")
    if(!treeToHtml)
        treeToHtml = (await importer.import("antlr to html")).treeToHtml
    if(!getParser)
        getParser = await importer.import("get antlr tool")
    if(typeof code === 'function') {
        code = code.toString()
    }
    if(typeof code === 'string') {
        if(fs.existsSync(code)) {
            if(typeof language === 'undefined') {
                // TODO: use language file extension from media-server code module gheshi support
                language = await extToLang(code)
            }
            code = fs.readFileSync(code).toString('utf8')
        }
        var {lexer, parser} = await getParser(language)
        try {
            const chars = new antlr.InputStream(code);
            const lexerStream = new lexer(chars);
            const tokens = new antlr.CommonTokenStream(lexerStream);
            const parserStream = new parser(tokens);
            parserStream.input = code
            const tree = parserStream[parserStream.ruleNames[0]]();
            code = selectDom(['//' + parserStream.ruleNames[0]], treeToHtml(tree))[0]
        } catch(e) {
            console.log(e)
            throw new Error('Could not parse \n' + code)
        }
    }

    return selectDom(descriptor, code)
}

export default selectCode

What the code could have been:

import fs from 'fs';
import antlr from 'antlr4';
import { importer } from './importer';

const { selectDom } = importer.import('select tree');
const { extToLang, treeToHtml, getParser } = await loadModules();

async function loadModules() {
    const extToLang = await importer.import('ext to lang');
    const treeToHtml = (await importer.import('antlr to html')).treeToHtml;
    const getParser = await importer.import('get antlr tool');
    return { extToLang, treeToHtml, getParser };
}

/**
 * Selects code from a given descriptor and returns the selected code as HTML.
 * @param {string[]} descriptor - The descriptor to select the code from.
 * @param {string|Function} code - The code to select, either a string or a function.
 * @param {string} [language] - The language of the code, automatically detected if not provided.
 * @returns {Promise<string>} The selected code as HTML.
 */
async function selectCode(descriptor, code, language) {
    if (typeof code === 'function') {
        code = code.toString();
    }

    if (typeof code ==='string' && fs.existsSync(code)) {
        language = await getLanguageFromExtension(code);
        code = await readFile(code, 'utf8');
    }

    const lexer = await getLexer(language);
    const parser = await getParser(language);

    try {
        const antlrStream = new antlr.InputStream(code);
        const lexerStream = new lexer(antlrStream);
        const tokens = new antlr.CommonTokenStream(lexerStream);
        const parserStream = new parser(tokens);
        parserStream.input = code;

        const tree = parserStream[parserStream.ruleNames[0]]();
        const codeHtml = await getHtmlFromTree(tree);

        return selectDom(descriptor, codeHtml);
    } catch (e) {
        console.log(e);
        throw new Error(`Could not parse \n${code}`);
    }
}

async function getLanguageFromExtension(file) {
    const extToLang = await importer.import('ext to lang');
    return extToLang(file);
}

async function getLexer(language) {
    const getParser = await importer.import('get antlr tool');
    return getParser(language).lexer;
}

async function getParser(language) {
    const getParser = await importer.import('get antlr tool');
    return getParser(language);
}

async function getHtmlFromTree(tree) {
    const treeToHtml = (await importer.import('antlr to html')).treeToHtml;
    return treeToHtml(tree);
}

async function readFile(file, encoding) {
    return fs.readFileSync(file, encoding);
}

export default selectCode;

Code Breakdown

Import Statements

The code starts by importing various modules:

Variables

The code defines several variables:

selectCode Function

The selectCode function takes three parameters: descriptor, code, and language. It is an asynchronous function that performs the following tasks:

  1. Language detection: If the code parameter is a string and a file exists at the specified path, it tries to detect the language from the file extension using the extToLang object. If the language is not specified, it uses this detected language.
  2. ANTLR parsing: It uses the getParser function to get a lexer and parser for the detected language. It then reads the file contents and creates an ANTLR input stream.
  3. Parse and transform: It uses the parser to parse the input stream and creates an abstract syntax tree (AST). It then uses the treeToHtml function to convert the AST to HTML.
  4. Select DOM elements: It calls the selectDom function to select specific DOM elements from the HTML output.
  5. Return result: The final result is returned as a string.

Error Handling

The code catches any errors that occur during the parsing process and logs the error message. If an error occurs, it throws a new error with the parsed code and the error message.