bison | Cell 0 | Cell 2 | Search

This code provides a utility for selecting and manipulating code structures based on a grammar and a selection descriptor, likely used in a larger code analysis or transformation tool. It parses code, allows for querying specific parts using a descriptor, and converts the selected code into a string representation.

Run example

npm run import -- "select jison tree"

select jison tree

var fs = require('fs');
var jison = require('jison');
var importer = require('../Core')
var {
    selectDom,
    evaluateDom,
    treeToHtml,
    htmlToTree
} = importer.import("select tree",
"tree to html",
"html to tree")

function getParser(jisonFile) {
    var bnf
    if(fs.existsSync(jisonFile)) {
        bnf = fs.readFileSync(jisonFile, 'utf8')
    } else {
        bnf = importer.interpret(jisonFile).code
    }
    
    var parser = new jison.Parser(bnf)
    return parser
}


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'}
    })
}

function selectCode(descriptor, code, language) {
    if(typeof code === 'function') {
        code = code.toString()
    }
    if(typeof code === 'string') {
        if(fs.existsSync(code)) {
            code = fs.readFileSync(code)
            if(typeof language === 'undefined') {
                language = 
            }
        }
        var parser = getParser(language)
        try {
            code = esprima.parse(code, {range: true, tokens: true,
                                        comment: true, whitespace: true})
        } catch(e) {
            console.log(e)
            throw new Error('Could not parse \n' + code)
        }
    }
    // TODO: move this conversion to selectDom for all objects?
    //   No more selectTree because jsel and friends are inconsistent.
    if(typeof code.evaluate === 'undefined'
       && typeof code.ownerDocument === 'undefined') {
        code = selectDom('//Program', treeToHtml(code))
        code.ownerDocument.toString = toString.bind(code, code)
    }
    return selectDom(descriptor, code)
}

module.exports = {
    selectCode
}

What the code could have been:

const fs = require('fs');
const jison = require('jison');
const escodegen = require('escodegen');

const {
  selectDom,
  evaluateDom,
  treeToHtml,
  htmlToTree
} = require('../Core');

/**
 * Generates a Jison parser from a given BNF file.
 * 
 * If the BNF file exists, it reads the contents. Otherwise, it interprets the code.
 * 
 * @param {string} jisonFile Path to the BNF file or the code to interpret.
 * @returns {jison.Parser} The generated parser.
 */
function getParser(jisonFile) {
  try {
    const bnf = fs.existsSync(jisonFile)? fs.readFileSync(jisonFile, 'utf8') : importer.interpret(jisonFile).code;
    return new jison.Parser(bnf);
  } catch (e) {
    throw new Error(`Failed to generate parser: ${e.message}`);
  }
}

/**
 * Converts an AST to a string representation.
 * 
 * If the AST is an HTML element, it converts it to a tree first.
 * 
 * @param {Object} ast The AST to convert.
 * @param {Object} [subctx] The sub-context AST.
 * @returns {string} The string representation of the AST.
 */
function toString(ctx, subctx) {
  const ast = subctx || ctx;
  return ast.ownerDocument? treeToHtml(ast) : escodegen.generate(ast, {
    comment: true,
    tokens: true,
    whitespace: true,
    format: { indent: { style:'  '}, quotes:'single' }
  });
}

/**
 * Selects code based on a descriptor and a given code or function.
 * 
 * If the code is a function, it converts it to a string. If it's a file, it reads the contents.
 * 
 * It then parses the code using a Jison parser.
 * 
 * If the parsed code is not an AST, it converts it to one using the `selectDom` function.
 * 
 * @param {string} descriptor The selector for the code.
 * @param {Function|string} code The code to select or a function to execute.
 * @param {string} [language] The language of the code.
 * @returns {Object} The selected code.
 */
function selectCode(descriptor, code, language) {
  if (typeof code === 'function') {
    code = code.toString();
  }

  if (typeof code ==='string') {
    try {
      const parser = getParser(language || code);
      code = esprima.parse(code, { range: true, tokens: true, comment: true, whitespace: true });
      return selectDom(descriptor, code);
    } catch (e) {
      if (e instanceof SyntaxError) {
        const fileCode = fs.readFileSync(code);
        return selectCode(descriptor, fileCode, code);
      } else {
        throw new Error(`Failed to parse code: ${e.message}`);
      }
    }
  }

  if (typeof code.evaluate === 'undefined' && typeof code.ownerDocument === 'undefined') {
    return selectDom(descriptor, selectDom('//Program', treeToHtml(code)));
  }

  return selectDom(descriptor, code);
}

module.exports = { selectCode };

This code defines a utility for selecting and manipulating code structures, likely within a larger code analysis or transformation system.

Here's a breakdown:

In essence, this code provides a way to query and extract specific parts of code based on a grammar and a selection descriptor.