php-parser icon indicating copy to clipboard operation
php-parser copied to clipboard

How to turn ast into PHP code

Open Yuri2 opened this issue 2 years ago • 5 comments

const parser = new engine({ // some options : parser: { extractDoc: true, php7: true, }, ast: { withPositions: true, }, });

// Load a static file (Note: this file should exist on your computer) const phpcode = fs.readFileSync("./1.php", { encoding: "utf-8" });

let ast=parser.parseCode(phpcode);


now: How to turn ast into PHP code?

Yuri2 avatar Jul 04 '22 13:07 Yuri2

I'm new to this project, but I believe you will want to use something like php-writer for that.

dominic-p avatar Jul 19 '22 05:07 dominic-p

Possibly helpful: It's not exactly turning an AST into code, but if you just want to make changes to some PHP code based on the php-parser AST, I just made a library for that. 🙂

loilo avatar May 08 '23 10:05 loilo

@loilo Hi, do you have a code example for traversing or visitors with php-parser?

yaegassy avatar Jul 04 '23 01:07 yaegassy

@yaegassy Sure. You basically have to recursively check all properties of a node to find descendant nodes, where a node is defined by having a kind property.

Here's some code defining a walk function which you can feed a callback and an AST:

/**
 * Check whether a value resembles a php-parser AST node
 *
 * @param value The value to check
 */
function isNode(value) {
  return (
    typeof value === 'object' &&
    value !== null &&
    typeof value.kind === 'string'
  )
}

/**
 * Collect the child nodes of an AST node
 *
 * @param node The node to search for child nodes
 */
function collectChildNodes(node) {
  const childNodes = []

  // Walk all AST node properties, performing a recursive `walk`
  // on everything that looks like another AST node
  for (const key of Object.keys(node)) {
    const property = node[key]

    if (Array.isArray(property)) {
      // Step into arrays and walk their items
      for (const propertyElement of property) {
        if (isNode(propertyElement)) {
          childNodes.push(propertyElement)
        }
      }
    } else if (isNode(property)) {
      childNodes.push(property)
    }
  }

  return childNodes
}

/**
 * Walk an AST recursively
 *
 * @param callback  A function to invoke for every node
 * @param node      The tree to visit
 * @param parent    The parent of the (sub)tree node
 */
function walk(callback, node, parent = undefined) {
  const children = collectChildNodes(node)
  for (const child of children) {
    walk(callback, child, node)
  }
  callback(node, parent)
}

loilo avatar Jul 04 '23 06:07 loilo

@loilo Thanks, I will refer to it. 🙇

yaegassy avatar Jul 04 '23 06:07 yaegassy