/xast

Extensible Abstract Syntax Tree parser

Primary LanguageTypeScriptOtherNOASSERTION

XAST

0-deps configurable Abstract Syntax Tree parser

Build Status NPM version Downloads Coverage Status Maintainability Snyk

Table of Contents

Features

  • Configurable Lexer with predefined tokenizers
  • Flexible Parser with modulized AST node parsers
  • TypeScript support
  • Supports NodeJS and Browser

Support

NodeJS Chrome Firefox Safari Opera Edge
LTS ✔ Latest ✔ Latest ✔ Latest ✔ Latest ✔ Latest ✔

Installing

Using yarn:

$ yarn add xast

Using npm:

$ npm install xast

Example

Create an enum parser in file enum.ts

import {
  Parser,
  parsers,
  TokenKind,
  NodeParser,
  Node,
} from 'xast';

export interface EnumValueNode extends Node {
  readonly kind: 'ENUM_VALUE';
  readonly value: parsers.NameNode;
}

export const enumValueParser: NodeParser<EnumValueNode> = {
  kind: 'ENUM_VALUE',
  parse(parser: Parser): EnumValueNode | undefined {
    const start = parser.lexer.token;
    const value = parser.expectParse(parsers.nameParser);

    return parser.node<EnumValueNode>(start, {
      kind: 'ENUM_VALUE',
      value,
    });
  }
}

const KEYWORD = 'enum';

export interface EnumNode extends Node {
  readonly kind: 'ENUM';
  readonly name: parsers.NameNode;
  readonly values: EnumValueNode[];
}

export const enumParser: NodeParser<EnumNode> = {
  kind: 'ENUM',
  trigger: {
    kind: TokenKind.NAME,
    keyword: KEYWORD,
  },
  parse(parser: Parser): EnumNode | undefined {
    const start = parser.lexer.token;
    parser.expectKeyword(KEYWORD);
    const name = parser.expectParse(parsers.nameParser);
    parser.expectToken(TokenKind.BRACE_L);
    const values = parser.delimitedMany(TokenKind.COMMA, enumValueParser);
    parser.expectToken(TokenKind.BRACE_R);
    parser.expectToken(TokenKind.SEMICOLON);

    return parser.node<EnumNode>(start, {
      kind: 'ENUM',
      name,
      values,
    });
  }
}

Parser usage example

import {
  Lexer,
  addDefaultTokenizers,
  Parser,
  parsers
} from 'xast';

import { enumParser } from './enum.ts';

const schema = `enum Test { A, B, C };`;
const lexer = new Lexer(schema);
addDefaultTokenizers(lexer);

const parser = new Parser(lexer);
parser.add(enumParser);
console.log(parser.parseSchema());

Results to the following AST

{
  "kind": "SCHEMA",
  "definitions": [
    {
      "kind": "ENUM",
      "name": {
        "kind": "NAME",
        "value": "Test"
      },
      "values": [
        {
          "kind": "ENUM_VALUE",
          "value": {
            "kind": "NAME",
            "value": "A"
          }
        },
        {
          "kind": "ENUM_VALUE",
          "value": {
            "kind": "NAME",
            "value": "B"
          }
        },
        {
          "kind": "ENUM_VALUE",
          "value": {
            "kind": "NAME",
            "value": "C"
          }
        }
      ]
    }
  ]
}

License

License Apache-2.0 Copyright (c) 2023-present Ivan Zakharchanka