{"id":15082,"library":"apg-js","title":"ABNF Parser Generator","description":"JavaScript APG is a robust ABNF Parser Generator that enables developers to create recursive-descent parsers directly from a superset of ABNF (SABNF). It is currently stable at version 4.4.0, with a release cadence that has seen several updates in the past year, indicating active development and maintenance. Key differentiators include its ability to generate parsers for both standard `apg-js` and the more lightweight `apg-lite` framework, and its focus on fixing issues related to large grammars with mutually-recursive rules, a significant improvement over its predecessors like `apg-js2`. The library is designed to produce efficient parsers and provides options for TypeScript-compatible grammar objects, making it suitable for modern JavaScript and TypeScript environments.","status":"active","version":"4.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/ldthomas/apg-js","tags":["javascript","APG","parser","generator","ABNF","SABNF","pattern-matching","regex","RegExp"],"install":[{"cmd":"npm install apg-js","lang":"bash","label":"npm"},{"cmd":"yarn add apg-js","lang":"bash","label":"yarn"},{"cmd":"pnpm add apg-js","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ApgParser is the primary class for instantiating a parser with a grammar object. ESM is the preferred import style for modern projects.","wrong":"const ApgParser = require('apg-js').ApgParser;","symbol":"ApgParser","correct":"import { ApgParser } from 'apg-js';"},{"note":"apgUtilities provides helper functions for common parsing tasks and is a named export.","wrong":"const apgUtilities = require('apg-js').apgUtilities;","symbol":"apgUtilities","correct":"import { apgUtilities } from 'apg-js';"}],"quickstart":{"code":"import { ApgParser } from 'apg-js';\n\n// Define a simple grammar object programmatically. In a real scenario,\n// this would often be generated from an ABNF file using the apg-js generator.\n// This grammar parses a list of digits separated by commas.\nconst grammar = {\n    _grammar: 'SimpleList',\n    callbacks: {\n        list: () => {}, // No semantic action needed for this simple example\n        element: () => {},\n        digit: () => {}\n    },\n    rules: {\n        list: {\n            // list = element *(\",\" element)\n            op: [\n                { type: 1, p: 'element' },\n                { type: 2, p: [\n                    { type: 7, p: ',' },\n                    { type: 1, p: 'element' }\n                ]}\n            ]\n        },\n        element: {\n            // element = 1*DIGIT\n            op: [{ type: 5, min: 1, max: 0, p: 'digit' }]\n        },\n        digit: {\n            // digit = %d48-57 ; '0'-'9'\n            op: [{ type: 3, min: 48, max: 57 }]\n        }\n    },\n    udts: {},\n    operators: [],\n    ast: {\n        defined: false,\n        nodes: []\n    }\n};\n\nconst parser = new ApgParser(grammar);\n\nconst inputString1 = \"1,23,456\";\nconst result1 = parser.parse(inputString1);\n\nif (result1.success) {\n    console.log(`Successfully parsed \"${inputString1}\"`);\n} else {\n    console.error(`Failed to parse \"${inputString1}\": ${result1.state.toString()}`);\n}\n\nconst inputString2 = \"1,23,A456\"; // Invalid input\nconst result2 = parser.parse(inputString2);\n\nif (result2.success) {\n    console.log(`Successfully parsed \"${inputString2}\"`);\n} else {\n    console.error(`Failed to parse \"${inputString2}\": ${result2.state.toString()}`);\n}","lang":"typescript","description":"Demonstrates defining a simple ABNF grammar programmatically and using `ApgParser` to parse input strings, logging success or failure."},"warnings":[{"fix":"Upgrade to `apg-js@4.2.0` or newer, which explicitly imports Node.js globals and removes reliance on global `this` references.","message":"`apg-js` versions prior to 4.2.0 could cause bundling issues in browser environments or with specific bundlers due to reliance on `this` context for exported functions and direct use of Node.js globals like `Buffer` without explicit imports.","severity":"breaking","affected_versions":"<4.2.0"},{"fix":"Upgrade to `apg-js@4.2.1` or newer for correct processing. However, prefer `\"\"` for explicit empty strings as zero repetitions are deprecated.","message":"In `apg-js` versions prior to 4.2.1, ABNF zero repetitions (e.g., `0char`, `0\"x\"`) were inconsistently and often incorrectly processed as empty string acceptors, sometimes failing unexpectedly.","severity":"breaking","affected_versions":"<4.2.1"},{"fix":"Always use the empty literal string `\"\"` for explicit empty string acceptors in your ABNF grammars.","message":"The use of zero repetitions (e.g., `0\"x\"`) for empty string acceptance in ABNF grammars is deprecated, even though `apg-js` 4.2.1+ supports it correctly. Not all APG implementations accept it, and it is slightly less efficient.","severity":"deprecated","affected_versions":">=4.2.1"},{"fix":"Migrate existing projects from `apg-js2` or related packages to `apg-js` and re-evaluate grammar definitions, as the API and internal behavior have changed significantly.","message":"`apg-js` (version 4.x) is a complete rewrite and replacement for older packages like `apg-js2`, `apg-js2-lib`, `apg-js2-exp`, `apg-js2-api`, `apg-conv`, and `apg-conv-api`. It fixes a critical flaw in the attributes algorithm that could cause failures with large grammars and extensive mutual recursion in previous versions.","severity":"breaking","affected_versions":"<4.0.0 (for users of `apg-js2` and related packages)"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Upgrade `apg-js` to version `4.2.0` or higher to resolve direct global Node.js dependency issues.","cause":"Prior to `apg-js@4.2.0`, the library relied on global Node.js objects like `Buffer` without explicit imports, causing issues in non-Node.js environments or when bundled.","error":"ReferenceError: Buffer is not defined"},{"fix":"The library itself fixed this in `apg-js@4.2.0` by removing the `node:` prefix. Ensure your project and any custom tooling use the standard `require('buffer')` format where applicable.","cause":"Using the `node:` prefix with `require()` (e.g., `require('node:buffer')`) can cause compatibility problems with bundlers like `browserify`.","error":"Build error with browserify when using `require('node:buffer')` or similar 'node:' prefixed imports."},{"fix":"Migrate your project to `apg-js@4.0.0` or a newer version, which contains a corrected attributes algorithm, and retest your grammars.","cause":"A major bug in the attributes algorithm of `apg-js2` and earlier versions could lead to parsing failures or performance issues with complex, mutually-recursive ABNF rules.","error":"Parser fails or hangs unexpectedly on large or complex grammars with many mutually-recursive rules."}],"ecosystem":"npm"}