npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

oscript-ast-walker

v0.1.1

Published

A walker for nodes of the abstract syntax tree (AST) for the OScript language.

Downloads

26

Readme

OScript AST Walker

NPM version

A walker for nodes of the abstract syntax tree (AST) for the OScript language. The AST can be produced by the oscript-parser.

Synopsis

import { parseText } from 'oscript-parser'
import { simple as simpleWalk } from 'oscript-ast-walker'

const source = `
script Test
endscript
`
simpleWalk(parseText(source, { sourceType: 'script' }), {
  ScriptDeclaration: {
    pre(node) {
      console.log(`Script: ${node.id.value}`) // prints "Test"
      return true // do not continue walking below the script declaration
    }
  }
})

Installation

Use your favourite package manager to install this package locally in your Node.js project:

npm i oscript-ast-walker
pnpm i oscript-ast-walker
yarn add  oscript-ast-walker

Interface

An algorithm for recursing through a syntax tree is stored as an object, with a property for each tree node type holding functions that will recurse through such a node. There are several ways to run such a walker:

simple(node, visitors, baseVisitor, state) does a "simple: walk over a tree. node should be the AST node to walk, and visitors an object with properties whose names correspond to node types in the AST. The properties should contain an object with pre and post functions that will be called with the node object, with the state at that point (if applicable) and with the parent node. The pre-callback will be called before children of the node will be visited and the post-callback will be called after visiting the node children. If the pre-callback returns a truth-y result, children of the node will not be visited and the walking will to the next sibling. It can be used to optimize the walking if only top nodes should be visited. The last two arguments are optional. The state is a start state. The default walker will simply visit all statements and expressions and not produce a meaningful state. (An example of a use of state is to track scope at each point in the tree.)

import { parseText } from 'oscript-parser'
import { simple as simpleWalk } from 'oscript-ast-walker'

const source = `
script Test
  Integer i = 0
endscript
`
simpleWalk(parseText(source, { sourceType: 'script' }), {
  Identifier: {
    pre(node) {
      console.log(`Identifier: ${node..value}`) // prints "Test" and "i"
    }
  }
})

ancestor(node, visitors, baseVisitor, state) does a "simple" walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as the third parameter (instead of the parent node).

import { parseText } from 'oscript-parser'
import { ancestor as ancestorWalk } from 'oscript-ast-walker'

const source = `
script Test
  function Help()
    Integer i = 0
  end
endscript
`
ancestorWalk(parseText(source, { sourceType: 'script' }), {
  FunctionDeclaration: {
    pre (node, state, ancestors) {
      const path = ancestors.map(node => node.id.value).join('.')
      console.log(`Function: ${path}`) // prints "Test/Help"
      return true // do not continue walking below the function declaration
    }
  }
})

full(node, callbacks, baseVisitor, state) does a "full" walk over a tree, calling the callbacks with the arguments (node, state, parent) for each node.

import { parseText } from 'oscript-parser'
import { full as fullWalk } from 'oscript-ast-walker'

const source = `
script Test
  Integer i = 0
endscript
`
fullWalk(parseText(source, { sourceType: 'script' }), {
  pre(node) {
    if (node.type === 'Identifier') {
      console.log(`Identifier: ${node..value}`) // prints "Test" and "i"
    }
  }
})

fullAncestor(node, callbacks, baseVisitor, state) does a "full" walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as the third parameter (instead of the parent node).

import { parseText } from 'oscript-parser'
import { fullAncestor as fullAncestorWalk } from 'oscript-ast-walker'

const source = `
script Test
  Integer i = 0
  function Help()
  end
endscript
`
fullAncestorWalk(parseText(source, { sourceType: 'script' }), {
  pre(node, state, ancestors) {
    if (node.type === 'VariableDeclarator' ||
        node.type === 'FunctionDeclaration' ||
        node.type === 'ScriptDeclaration') {
      const path = ancestors.map(node => node.id.value).join('.')
      console.log(`Declared: ${path}`) // prints "Test", "Test/i", and "Test/Help"
      return true // do not continue walking below the declarations
    }
  }
})

recursive(node, functions, baseVisitor, state) does a "recursive" walk, where the walker functions are responsible for continuing the walk on the child nodes of their target node. state is the start state, and functions should contain an object that maps node types to walker functions. Such functions are called with (node, parent, state, walk) arguments, and can cause the walk to continue on a sub-node by calling the walk argument on it with (node, parent, state) arguments. The optional baseVisitor argument provides the fallback walker functions for node types that aren't handled in the functions object. If not given, the default walkers will be used.

make(functions, baseVisitor) builds a new walker object by using the walker functions in functions and filling in the missing ones by taking defaults from baseVisitor.

findNodeAround(node, position, test, base, state) tries to locate a node in a tree at the given position, which satisfies the optional predicate test. position should be an object with line (1-based) and column (0-based) properties. test may be a string (indicating a node type) or a function that takes (node, state, parent) arguments and returns a boolean indicating whether this node is interesting. baseVisitor and state are optional, and can be used to specify a custom walker. Nodes are tested from inner to outer, so if two nodes match the boundaries, the inner one will be preferred.

findNodeAroundWithAncestors(node, position, test, base, state) tries to locate a node in a tree at the given position and satisfying the optional predicate test. Keeps an array of ancestor nodes (including the current node), passes them to the test callbacks as a third parameter and includes them in the returned object.