bison | select jison tree | Cell 3 | Search

This JavaScript parser, created using the Jison library, takes an input string and generates an indented Abstract Syntax Tree (AST) from it. The parser defines a grammar and uses a parser instance to parse the input string, resulting in an AST with a specific structure, including a root node hex_strings and child nodes representing hex strings.

Cell 2

function jisonAST(name, x) { this.name = name; this.x = x; }

// return the indented AST
jisonAST.prototype.get = function(indent){
  // create an indentation for level l
  function indentString(l) { var r=""; for(var i=0;i<l;i++){r+="  "}; return r }

  var r = indentString(indent) + "["+this.name+": ";
  var rem = this.x;
  if( rem.length == 1 && !(rem[0] instanceof jisonAST) ) r += "'"+rem[0]+"'"; 
  else for( i in rem ){ 
      if( rem[i] instanceof jisonAST ) r += "\n" + rem[i].get(indent+1);
      else { r += "\n" + indentString(indent+1); r += "'"+rem[i]+"'"; }
    }
  return r + "]";
}

function o( s ){
    r = "$ = new yy.jisonAST('"+s+"',[";
    for( i = 1; i <= s.split(" ").length; i++ ){ r += "$"+i+"," }
    r = r.slice(0,-1) + "]);";
    return [s,r];
}

var Parser = require("jison").Parser;

// a grammar in JSON
var grammar = {
    "lex": {
        "rules": [
           ["\\s+", "/* skip whitespace */"],
           ["[a-f0-9]+", "return 'HEX';"]
        ]
    },
    "bnf": {
        // had to add a start/end, see below
        "start" : [ [ "hex_strings", "return $1" ] ],
        "hex_strings" :[ 
            o("hex_strings HEX"), 
            o("HEX") 
        ]
    }
};

var parser = new Parser(grammar);
// expose the AST object to Jison
parser.yy.jisonAST = jisonAST

console.log( parser.parse("adfe34bc e82a 43af").get(0) );

/*
expects
[hex_strings HEX: 
  [hex_strings HEX: 
    [HEX: 'adfe34bc']  
    'e82a']  
  '43af']
*/

What the code could have been:

// Import the required modules
const { Parser } = require("jison");

// Define the jisonAST class
class JisonAST {
  /**
   * Constructor for the jisonAST class.
   * @param {string} name - The name of the AST node.
   * @param {array} x - The children of the AST node.
   */
  constructor(name, x) {
    this.name = name;
    this.x = x;
  }

  // Return the indented AST
  get(indent = 0) {
    // Create an indentation string for the given level
    const indentString = (level) => "  ".repeat(level);

    let result = indentString(indent) + "[" + this.name + ": ";

    // Process the children of the AST node
    const processChild = (child) =>
      child instanceof JisonAST
       ? "\n" + child.get(indent + 1)
        : "\n" + indentString(indent + 1) + "'" + child + "'";

    // Recursively process each child and append the result to the string
    result +=
      this.x.length === 1 &&!this.x[0] instanceof JisonAST
       ? "'" + this.x[0] + "'"
        : this.x.map(processChild).join("");

    return result + "]";
  }
}

// Function to generate a string in the format required by Jison
const generateOString = (s) => `$ = new yy.JisonAST('${s}', [${s.split(" ").map((_, i) => `${i + 1}`).join(",")}]));`;

// Define the grammar for the parser
const grammar = {
  lex: {
    rules: [
      ["\\s+", "/* skip whitespace */"],
      ["[a-f0-9]+", "return 'HEX';"],
    ],
  },
  bnf: {
    start: [["hex_strings", "return $1"]],
    hex_strings: [generateOString("hex_strings HEX"), generateOString("HEX")],
  },
};

// Create a new parser instance
const parser = new Parser(grammar);

// Expose the AST object to Jison
parser.yy.JisonAST = JisonAST;

// Test the parser
const input = "adfe34bc e82a 43af";
const result = parser.parse(input);
console.log(result.get());

/*
expects
[hex_strings HEX: 
  [hex_strings HEX: 
    [HEX: 'adfe34bc']  
    'e82a']  
  '43af']
*/

Overview

This code defines a JavaScript parser using the Jison library. It creates an Abstract Syntax Tree (AST) from a given input string and outputs the indented AST.

Function Breakdown

jisonAST Function

function jisonAST(name, x) { this.name = name; this.x = x; }

Creates a new AST object with name and x properties.

get Method

jisonAST.prototype.get = function(indent){
  //...
}

Returns the indented AST as a string. It takes an indent parameter, which specifies the level of indentation.

indentString Function

function indentString(l) { var r=""; for(var i=0;i<l;i++){r+="  "}; return r }

Creates a string with the specified number of indentation levels (represented by spaces).

o Function

function o(s){
    //...
}

Generates a JSON object representing an AST node, given a string s.

Grammar Object

var grammar = {
  //...
}

Defines a Jison grammar in JSON format, which consists of lexical rules and BNF rules.

Parser Object

var parser = new Parser(grammar);

Creates a new parser instance using the grammar object.

parse Method

console.log( parser.parse("adfe34bc e82a 43af").get(0) );

Parses the input string "adfe34bc e82a 43af" and returns the indented AST as a string.

AST Structure

The resulting AST has the following structure: