js-sexpr

S-Expression Parser, Serializer, and Tree Constructor / Walker Utilities in JavaScript for Browsers and Node.js

Usage no npm install needed!

<script type="module">
  import jsSexpr from 'https://cdn.skypack.dev/js-sexpr';
</script>

README

S-Expression in JavaScript

License: ISC Release Closed issues Patreon donate button PayPal donate button Amazon donate button

Buy Me A Coffee

S-Expression Parser, Serializer, and Tree Constructor / Walker Utilities for JavaScript in Browsers and Node.js

Zero-dependencies. Tree structure as plain JSON. Ideal for custom data transfer format and making DSLs.

⭐ Overview

S-Expression is surprisingly a powerful yet very simple concept to represent both data and function with minimalist syntax. It was popularized by LISP (a classic programming language that was used heavily in AI research) in the very beginning of computer science, circa 1960, and yet S-Expression is still one of the best ideas around due to its simplicity and extensibility. It contains only lists containing symbols and nested lists, and it's totally up to the programmers to make the meanings out of those symbols and their arrangements. S-Expression is a good choice for many use cases ranging from command format, config file format, small domain-specific language to a full-blown programming language.

S-Expression is so minimal that it resembles an abstract syntax tree (AST), which is the underlying representation of many high-level programming languages when their syntactic sugar code is parsed through the typical language grammars. This appeals to many language designers because they can bypass the typical grammar design in forms such as BNF and instead focus on the core syntax tree to accomplish their main goals for the languages, and consequently providing a native/in-language way to manipulate the syntax tree thus enables more dynamic capability and easier metaprogramming.

These are some of the reasons why there are so many popular languages based on S-Expression such as Lisp, Clojure, Scheme, Racket, and their families of languages. More recently, WebAssembly, the 4th language of the Web, also embraces S-Expression for its textual form. Once you're familiar with S-Expression and its flexibility, it becomes useful knowledge in your development toolkit and can come in handy as an obvious choice over any ad-hoc input parsing that often comes up in your career as a developer.

This project makes working with S-Expression in JavaScript really easy.

🛠️ Installation

npm install --save js-sexpr
API documentation link

🚀 Quick start

TODO: simple parsing example

See API documentation for more reference.

👋 Author

👤 Nikyle Nguyen

Twitter: NLKNguyen

🤝 Contributing

Give a ⭐️ if this project helped you working with S-Expression easily in JavaScript!

Contributions, issues and feature requests are welcome! Feel free to check issues page.

🙇 Your support is very much appreciated

I create open-source projects on GitHub and continue to develop/maintain as they are helping others. You can integrate and use these projects in your applications for free! You are free to modify and redistribute anyway you like, even in commercial products.

I try to respond to users' feedback and feature requests as much as possible. Obviously, this takes a lot of time and efforts (speaking of mental context-switching between different projects and daily work). Therefore, if these projects help you in your work, and you want to encourage me to continue create, here are a few ways you can support me:

  • 💬 Following my blog and social profiles listed above to help me connect with your network
  • ⭐️ Starring this project and sharing with others as more users come, more great ideas arrive!
  • ☘️ Donating any amount is a great way to help me work on the projects more regularly!

Buy Me A Coffee

📝 License

Copyright © 2020 Nikyle Nguyen

The project is ISC License

API

Table of Contents

SExpr

Class of S-Expression resolver that includes parser, serializer, tree constructors, and tree walker utilities.

Creates an instance of SExpr. Optional options input for configuring default behavior, such as how to recognize null, boolean values as it's up to the programmer to decide the syntax. Nevertheless, here is the default that you can override.

{
 truthy: ['true', '#t'],
 falsy: ['false', '#f'],
 nully: ['null', '#nil']
}

Parameters

  • options any (optional, default {})

context

Public field for programmers to store arbitrary data that might be useful for parsing expressions

parse

Parse a S-expression string into a JSON object representing an expression tree

Parameters

  • str string S-expression string

Returns json an expression tree in form of list that can include nested lists similar to the structure of the input S-expression

serialize

Serialize an expression tree into an S-expression string

Parameters

  • L any

Returns any

identifier

Create an identifier symbol

Parameters

Examples

const S = new SExpr()
const node = S.expression(S.identifier('a'))
// ['a']

Returns string symbol

isIdentifier

Check if a node is an identifier, optionally compare to a given name

Parameters

  • e any a node to check
  • id string optional id name to compare to (optional, default undefined)

Examples

const S = new SExpr()
const node = S.expression(S.identifier('a'))
console.log(S.isIdentifier(S.first(node)))
// true
console.log(S.isIdentifier(S.first(node, 'a')))
// true

Returns boolean true if it is an identifier

isEqual

Compare whether 2 nodes are identical

Parameters

  • a any a node
  • b any another node to compare to

Returns boolean true if they are the same

expression

Create an expression node

Parameters

  • exps rest optional initialization list of elements

Returns json a tree node

isExpression

Check if a node is an expression, and optionally compare to a given expression

Parameters

  • e any a node to check whether it's an expression
  • s json optional expression to compare to (optional, default undefined)

Returns boolean true if it's an expression (and equals the compared expression if provided)

boolean

Create a boolean node with given state

Parameters

Returns string a node with name corresponding to a boolean value

isBoolean

Check if a node is a boolean value, optionally compare to a given state

Parameters

  • e any a node to check whether it's a boolean
  • b boolean optional state to compare to (optional, default undefined)

Returns boolean true if it's a boolean (and equals the given state if provided)

isTruthy

Check if a node is considered truthy. Anything but an explicit false value is truthy.

Parameters

  • e any a node to check if it's truthy

Returns boolean true if it's truthy

null

Create a null node.

Returns string a node with name representing null value

isNull

Check if a node is null.

Parameters

  • e any a node to check if it's null

Returns boolean true if it's null

number

Create a number node

Parameters

  • n number value of the new node

Returns number a node with number value

isNumber

Check if a node is a number

Parameters

  • e any a node to check if it's a number, optionally compare to a given value
  • n number an optional value to compare to (optional, default undefined)

Returns boolean true if it's a number (and equals the given value if provided)

string

Create a string node.

Parameters

  • str string string value of the node

Returns string a node with string value

isString

Check if a node is a string, optionally compare to a given string.

Parameters

  • e any a node to check if it's a string
  • s string optional string to compare to (optional, default undefined)

Returns any true if it's a string (and equals the given string if provided)

valueOf

Get a value content of a symbol (not expression).

Parameters

  • e any a node to extract value

Returns any value

first

Get the first child of a node.

Parameters

  • e any a node to get its child

Returns any a child node if exists

second

Get the second child of a node.

Parameters

  • e any a node to get its child

Returns any a child node if exists

third

Get the third child of a node.

Parameters

  • e any a node to get its child

Returns any a child node if exists

nth

Get the n-th child of a node. Similar to the shorthand first, second, third, fourth, fifth ... tenth, but at any position provided.

Parameters

  • e any a node to get its child
  • n number position of the child node, starting from 1

Returns any a child node if exists