New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

bnf-parser

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bnf-parser - npm Package Compare versions

Comparing version 3.0.3 to 3.1.0

changelog.md

22

bin/build.js

@@ -7,7 +7,3 @@ "use strict";

const getopts = require("getopts");
let opt = getopts(process.argv.slice(2), {
alias: {
verify: "v"
}
});
let opt = getopts(process.argv.slice(2), {});
let input = fs.readFileSync(path.join(__dirname, '../bnf.bnf'), 'utf8');

@@ -18,17 +14,3 @@ let res = index_js_1.BNF.parse(input);

syntax.setVerbose(opt.verbose);
if (opt['verify']) {
let test = syntax.parse(input);
if (test instanceof index_js_1.SyntaxNode) {
console.log("Double parse successful");
(0, index_js_1.Compile)(test);
console.log("Double build successful");
}
else {
console.error(res.toString());
process.exit(1);
}
}
else {
fs.writeFileSync(path.join(__dirname, '../bnf.json'), JSON.stringify(syntax.serialize()));
}
fs.writeFileSync(path.join(__dirname, '../bnf.json'), JSON.stringify(syntax.serialize()));
}

@@ -35,0 +17,0 @@ else {

@@ -7,2 +7,5 @@ "use strict";

function BuildRule(rule) {
if (rule.type != "def") {
throw new Error(`Unknown internal error, expected "def" got "${rule.type}"`);
}
return new parser_1.Rule(rule.value[0].value, BuildExpr(rule.value[1]));

@@ -12,2 +15,5 @@ }

var _a;
if (expr.type != "expr") {
throw new Error(`Unknown internal error, expected "expr" got "${expr.type}"`);
}
let base = {

@@ -69,3 +75,47 @@ type: "sequence",

}
function FlatternConstant(expr) {
if (expr.type != "constant") {
throw new Error(`Unknown internal error, expected "constant" got "${expr.type}"`);
}
let str = expr.value[0];
let inner = str.value[0];
let out = "";
if (!Array.isArray(inner.value)) {
throw new TypeError("Internal logic failure. Unexpected string");
}
for (let charNode of inner.value) {
if (charNode.type == "literal") {
out += charNode.value;
}
else {
let esc = charNode.value;
switch (esc[1].value) {
case "b":
out += "\b";
break;
case "f":
out += "\f";
break;
case "n":
out += "\n";
break;
case "r":
out += "\r";
break;
case "t":
out += "\t";
break;
case "v":
out += "\v";
break;
default: out += esc[1].value;
}
}
}
return out;
}
function BuildOperand(expr) {
if (expr.type != "expr_arg") {
throw new Error(`Unknown internal error, expected "expr_arg" got "${expr.type}"`);
}
let component = expr.value;

@@ -79,9 +129,3 @@ let prefixes = component[0].value;

case "constant":
component[1].value = component[1].value
.replace(/\\t/g, "\t")
.replace(/\\n/g, "\n")
.replace(/\\r/g, "\r")
.replace(/\\"/g, "\"")
.replace(/\\'/g, "\'")
.replace(/\\\\/g, "\\");
component[1].value = FlatternConstant(component[1]);
case "name":

@@ -122,2 +166,5 @@ base.type = component[1].type == "constant" ? "literal" : "term";

function Compile(tree) {
if (!(tree instanceof syntax_1.SyntaxNode)) {
throw new TypeError("Cannot compile syntax tree, as Syntax node is not provided");
}
let syntax = new parser_1.Parser({});

@@ -124,0 +171,0 @@ for (let node of tree.value[0].value) {

@@ -59,2 +59,3 @@ import { SyntaxNode, ParseError, Reference } from "./syntax";

constructor(json: any);
parse(input: string, ctx: Parser, cursor: Reference): SyntaxNode | ParseError;
parseSingle(input: string, ctx: Parser, cursor: Reference): SyntaxNode | ParseError;

@@ -61,0 +62,0 @@ serialize(): any;

@@ -33,3 +33,3 @@ "use strict";

case "+": return Count.OneToMany;
default: throw new Error("Unknown count");
default: throw new Error(`Unknown count "${count}"`);
}

@@ -226,4 +226,6 @@ }

else {
if (this.count == Count.One) {
return res;
}
cursor = res.ref.end;
res.type = this.value;
nodes.push(res);

@@ -241,5 +243,2 @@ consumption++;

}
if (this.count == Count.One) {
return nodes[0];
}
return new syntax_1.SyntaxNode(this.value + this.count, nodes, range);

@@ -289,6 +288,3 @@ }

}
if (this.count == Count.One) {
return nodes[0];
}
return new syntax_1.SyntaxNode(`(...)${this.count}`, nodes, range);
return new syntax_1.SyntaxNode(`(...)${this.count == "1" ? "" : this.count}`, nodes, range);
}

@@ -302,3 +298,5 @@ parseSingle(input, ctx, cursor) {

span.span(res.ref);
err = res.msg;
if (res.ref.end.index >= span.end.index) {
err = res.msg;
}
continue;

@@ -325,5 +323,16 @@ }

}
parse(input, ctx, cursor) {
let out = super.parse(input, ctx, cursor);
if (out instanceof syntax_1.ParseError) {
return out;
}
if (this.count == Count.One) {
return out.value[0];
}
return out;
}
parseSingle(input, ctx, cursor) {
let start = cursor.clone();
let nodes = [];
let onlyTerm = true;
for (let rule of this.exprs) {

@@ -340,2 +349,10 @@ let res = rule.parse(input, ctx, cursor.clone());

else {
if (!(rule instanceof Term)) {
onlyTerm = false;
}
// Merge selection of a single item inline
if (rule instanceof Select && rule.count == Count.One) {
nodes.push(res.value[0]);
continue;
}
nodes.push(res);

@@ -342,0 +359,0 @@ }

@@ -1,1 +0,1 @@

{"program":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"sequence","count":"+","exprs":[{"type":"term","value":"def","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}}]}]},"any":{"type":"sequence","count":"1","exprs":[{"type":"not","count":"1","expr":{"type":"literal","value":"","count":"1"}}]},"w":{"type":"select","count":"1","exprs":[{"type":"literal","value":" ","count":"1"},{"type":"literal","value":"\t","count":"1"},{"type":"omit","expr":{"type":"term","value":"comment","count":"1"}},{"type":"literal","value":"\n","count":"1"},{"type":"literal","value":"\r","count":"1"}]},"comment":{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"#","count":"1"},{"type":"not","count":"*","expr":{"type":"literal","value":"\n","count":"1"}},{"type":"literal","value":"\n","count":"1"}]},"name":{"type":"sequence","count":"1","exprs":[{"type":"gather","expr":{"type":"select","count":"+","exprs":[{"type":"term","value":"letter","count":"1"},{"type":"term","value":"digit","count":"1"},{"type":"literal","value":"_","count":"1"}]}}]},"letter":{"type":"select","count":"1","exprs":[{"type":"range","value":"a","count":"1","to":"z"},{"type":"range","value":"A","count":"1","to":"Z"}]},"digit":{"type":"range","value":"0","count":"1","to":"9"},"constant":{"type":"sequence","count":"1","exprs":[{"type":"gather","expr":{"type":"select","count":"1","exprs":[{"type":"term","value":"single","count":"1"},{"type":"term","value":"double","count":"1"}]}}]},"double":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"literal","value":"\"","count":"1"}},{"type":"gather","expr":{"type":"select","count":"*","exprs":[{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"\\","count":"1"},{"type":"term","value":"any","count":"1"}]},{"type":"not","count":"1","expr":{"type":"literal","value":"\"","count":"1"}}]}},{"type":"omit","expr":{"type":"literal","value":"\"","count":"1"}}]},"single":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"literal","value":"'","count":"1"}},{"type":"gather","expr":{"type":"select","count":"*","exprs":[{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"\\","count":"1"},{"type":"term","value":"any","count":"1"}]},{"type":"not","count":"1","expr":{"type":"literal","value":"'","count":"1"}}]}},{"type":"omit","expr":{"type":"literal","value":"'","count":"1"}}]},"def":{"type":"sequence","count":"1","exprs":[{"type":"gather","expr":{"type":"term","value":"name","count":"1"}},{"type":"omit","expr":{"type":"term","value":"w","count":"+"}},{"type":"omit","expr":{"type":"literal","value":"::=","count":"1"}},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"term","value":"expr","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"omit","expr":{"type":"literal","value":";","count":"1"}}]},"expr":{"type":"sequence","count":"1","exprs":[{"type":"term","value":"expr_arg","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"sequence","count":"*","exprs":[{"type":"gather","expr":{"type":"term","value":"expr_infix","count":"?"}},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"term","value":"expr_arg","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}}]}]},"expr_arg":{"type":"sequence","count":"1","exprs":[{"type":"term","value":"expr_prefix","count":"1"},{"type":"select","count":"1","exprs":[{"type":"gather","expr":{"type":"term","value":"constant","count":"1"}},{"type":"term","value":"expr_brackets","count":"1"},{"type":"gather","expr":{"type":"term","value":"name","count":"1"}}]},{"type":"gather","expr":{"type":"term","value":"expr_suffix","count":"?"}}]},"expr_prefix":{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"%","count":"?"},{"type":"literal","value":"...","count":"?"},{"type":"literal","value":"!","count":"?"}]},"expr_infix":{"type":"select","count":"1","exprs":[{"type":"literal","value":"->","count":"1"},{"type":"literal","value":"|","count":"1"}]},"expr_suffix":{"type":"select","count":"1","exprs":[{"type":"literal","value":"*","count":"1"},{"type":"literal","value":"?","count":"1"},{"type":"literal","value":"+","count":"1"}]},"expr_brackets":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"literal","value":"(","count":"1"}},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"term","value":"expr","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"omit","expr":{"type":"literal","value":")","count":"1"}}]}}
{"program":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"sequence","count":"+","exprs":[{"type":"term","value":"def","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}}]}]},"any":{"type":"sequence","count":"1","exprs":[{"type":"not","count":"1","expr":{"type":"literal","value":"","count":"1"}}]},"w":{"type":"select","count":"1","exprs":[{"type":"term","value":"comment","count":"1"},{"type":"literal","value":" ","count":"1"},{"type":"literal","value":"\t","count":"1"},{"type":"literal","value":"\n","count":"1"},{"type":"literal","value":"\r","count":"1"}]},"comment":{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"#","count":"1"},{"type":"not","count":"*","expr":{"type":"literal","value":"\n","count":"1"}},{"type":"literal","value":"\n","count":"1"}]},"name":{"type":"sequence","count":"1","exprs":[{"type":"gather","expr":{"type":"select","count":"+","exprs":[{"type":"term","value":"letter","count":"1"},{"type":"term","value":"digit","count":"1"},{"type":"literal","value":"_","count":"1"}]}}]},"letter":{"type":"select","count":"1","exprs":[{"type":"range","value":"a","count":"1","to":"z"},{"type":"range","value":"A","count":"1","to":"Z"}]},"digit":{"type":"range","value":"0","count":"1","to":"9"},"constant":{"type":"select","count":"1","exprs":[{"type":"term","value":"single","count":"1"},{"type":"term","value":"double","count":"1"}]},"double":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"literal","value":"\"","count":"1"}},{"type":"select","count":"*","exprs":[{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"\\","count":"1"},{"type":"gather","expr":{"type":"term","value":"any","count":"1"}}]},{"type":"not","count":"+","expr":{"type":"literal","value":"\"","count":"1"}}]},{"type":"omit","expr":{"type":"literal","value":"\"","count":"1"}}]},"single":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"literal","value":"'","count":"1"}},{"type":"select","count":"*","exprs":[{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"\\","count":"1"},{"type":"gather","expr":{"type":"term","value":"any","count":"1"}}]},{"type":"not","count":"+","expr":{"type":"literal","value":"'","count":"1"}}]},{"type":"omit","expr":{"type":"literal","value":"'","count":"1"}}]},"def":{"type":"sequence","count":"1","exprs":[{"type":"gather","expr":{"type":"term","value":"name","count":"1"}},{"type":"omit","expr":{"type":"term","value":"w","count":"+"}},{"type":"omit","expr":{"type":"literal","value":"::=","count":"1"}},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"term","value":"expr","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"omit","expr":{"type":"literal","value":";","count":"1"}}]},"expr":{"type":"sequence","count":"1","exprs":[{"type":"term","value":"expr_arg","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"sequence","count":"*","exprs":[{"type":"gather","expr":{"type":"term","value":"expr_infix","count":"?"}},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"term","value":"expr_arg","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}}]}]},"expr_arg":{"type":"sequence","count":"1","exprs":[{"type":"term","value":"expr_prefix","count":"1"},{"type":"select","count":"1","exprs":[{"type":"term","value":"constant","count":"1"},{"type":"term","value":"expr_brackets","count":"1"},{"type":"gather","expr":{"type":"term","value":"name","count":"1"}}]},{"type":"gather","expr":{"type":"term","value":"expr_suffix","count":"?"}}]},"expr_prefix":{"type":"sequence","count":"1","exprs":[{"type":"literal","value":"%","count":"?"},{"type":"literal","value":"...","count":"?"},{"type":"literal","value":"!","count":"?"}]},"expr_infix":{"type":"select","count":"1","exprs":[{"type":"literal","value":"->","count":"1"},{"type":"literal","value":"|","count":"1"}]},"expr_suffix":{"type":"select","count":"1","exprs":[{"type":"literal","value":"*","count":"1"},{"type":"literal","value":"?","count":"1"},{"type":"literal","value":"+","count":"1"}]},"expr_brackets":{"type":"sequence","count":"1","exprs":[{"type":"omit","expr":{"type":"literal","value":"(","count":"1"}},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"term","value":"expr","count":"1"},{"type":"omit","expr":{"type":"term","value":"w","count":"*"}},{"type":"omit","expr":{"type":"literal","value":")","count":"1"}}]}}
{
"name": "bnf-parser",
"version": "3.0.3",
"version": "3.1.0",
"description": "Deterministic BNF compiler/parser",

@@ -8,7 +8,5 @@ "main": "./bin/index.js",

"test": "node ./test",
"build": "npm run build-ts & npm run build-syntax",
"build-ts": "tsc",
"build-syntax": "node ./bin/build.js --verbose"
},

@@ -20,2 +18,3 @@ "repository": {

"keywords": [
"ast",
"bnf",

@@ -28,6 +27,5 @@ "compile",

"license": "ISC",
"dependencies": {
"getopts": "^2.3.0"
},
"devDependencies": {
"@types/node": "^18.11.10",
"getopts": "^2.3.0",
"ts-node": "^10.9.1",

@@ -34,0 +32,0 @@ "typescript": "^4.8.4"

@@ -7,3 +7,10 @@ # BNF-Parser <!-- no toc -->

- [Example](#example)
- [API](#api)
- [API](#api)
- [BNF Syntax](#bnf-syntax)
- [Escape Codes](#escape-codes)
- [Repetition `?`, `+`, `*`](#repetition---)
- [Omit `%`](#omit-)
- [Not `!`](#not-)
- [Range `->`](#range--)
- [Imports](#imports)
- [BNF](#bnf)

@@ -16,7 +23,10 @@ - [Parser](#parser)

- [Reference Range](#reference-range)
- [BNF Syntax](#bnf-syntax)
- [Repetition `?`, `+`, `*`](#repetition---)
- [Omit `%`](#omit-)
- [Not `!`](#not-)
- [Range `->`](#range--)
- [Syntax Tree](#syntax-tree)
- [Sequences](#sequences)
- [Select](#select)
- [Omit](#omit)
- [Gather](#gather)
- [Not](#not)
- [Range](#range)
- [Literal](#literal)

@@ -51,4 +61,86 @@ A simple library for generate syntax pasers based BNF syntax descriptions.

## API
# API
## BNF Syntax
```bnf
program ::= %w* ( def %w* )+ ;
# Consumes a single wild character
any ::= !"" ;
# Whitespace
w ::= comment | " " | "\t" | "\n" | "\r" ;
comment ::= "#" !"\n"* "\n" ;
name ::= ...( letter | digit | "_" )+ ;
letter ::= "a"->"z" | "A"->"Z" ;
digit ::= "0"->"9" ;
constant ::= single | double ;
double ::= %"\"" ( ( "\\" ...any ) | !"\""+ )* %"\"" ;
single ::= %"\'" ( ( "\\" ...any ) | !"\'"+ )* %"\'" ;
def ::= ...name %w+ %"::=" %w* expr %w* %";" ;
expr ::= expr_arg %w* ( ...expr_infix? %w* expr_arg %w* )* ;
expr_arg ::= expr_prefix ( constant | expr_brackets | ...name ) ...expr_suffix? ;
expr_prefix ::= "%"? "..."? "!"? ;
expr_infix ::= "->" | "|" ;
expr_suffix ::= "*" | "?" | "+" ;
expr_brackets ::= %"(" %w* expr %w* %")" ;
```
### Escape Codes
| Code | Result |
| :-: | :- |
| `\b` | Backspace |
| `\f` | Form Feed |
| `\n` | New Line |
| `\r` | Carriage Return |
| `\t` | Horizontal Tab |
| `\v` | Vertical Tab |
| - | Unrecognised escapes will result in just the character after the slash |
### Repetition `?`, `+`, `*`
Only one repetition mark should exist per argument.
```bnf
term # once
term? # one or zero
term+ # at least once
term* # zero or more
```
### Omit `%`
```bnf
%term
```
This operator will lead to the syntax under this operator being removed from the final syntax tree, however still remain as part of syntax validation. For instance in the BNF syntax above...
The omit character goes in front af a single term, and must be the front most operator placing it in from of any `not` or `gather` operators.
### Not `!`
```bnf
!term
```
This operator must be between two single length constants, this will accept all characters within the range of the two bounds (inclusive).
### Range `->`
```bnf
"a"->"z" # will consume a single character
"a"->"z"* # will consume as many characters as are in the range
```
This operator must be between two single length constants, this will accept all characters within the range of the two bounds (inclusive). Until the repetition count is reached.
The first operand must have no repetitions, however the repetition markers on the last operand will apply to the whole group.
## Imports
### BNF

@@ -200,70 +292,33 @@

# Syntax Tree
## BNF Syntax
There are two main core abstractions for how the syntax trees are generated from a BNF, sequences and selects.
```bnf
program ::= %w* ( def %w* )+ ;
## Sequences
# Consume a single wild character
any ::= !"" ;
A sequence is a linear list of elements that make up a match. A top level sequence (right side of the `::=`) will resolve with the `.type` of the matching name (the name on the left of the `::=`), any sub-sequences `()` will appear as a syntax node with the name `(...)` with subsequent values being evaluated the same as the top level.
# White space characters
w ::= " " | "\t" | %comment | "\n" | "\r" ;
comment ::= "#" !"\n"* "\n" ;
If there is a repetition marker such as `name+` there will be an extra noded added with the type `(...)+` of whom's children will be the number of times the pattern was matched.
name ::= ...( letter | digit | "_" )+ ;
letter ::= "a"->"z" | "A"->"Z" ;
digit ::= "0"->"9" ;
## Select
# String literals
constant ::= ...( single | double ) ;
double ::= %"\"" ...( ( "\\" any ) | !"\"" )* %"\"" ;
single ::= %"\'" ...( ( "\\" any ) | !"\'" )* %"\'" ;
Will resolve as the syntax tree of the first matching option. For instance if you have the select statement `variable | number`, if the parser matches a variable it would be the same as having a `variable` at that point in the sequence.
def ::= ...name %w+ %"::=" %w* expr %w* %";" ;
## Omit
expr ::= expr_arg %w* ( ...expr_infix? %w* expr_arg %w* )* ;
expr_arg ::= expr_prefix ( ...constant | expr_brackets | ...name ) ...expr_suffix? ;
expr_prefix ::= "%"? "..."? "!"? ;
expr_infix ::= "->" | "|" ;
expr_suffix ::= "*" | "?" | "+" ;
expr_brackets ::= %"(" %w* expr %w* %")" ;
```
Any omit statement within a sequence will be removed, and then looking at the outputted syntax tree it is like they never existed, however they are still critical to a successful match. In the case that they are within a select, they will still be visible with `.type` of `omit`, with no child nodes.
## Gather
### Repetition `?`, `+`, `*`
This does not alter the outputted syntax tree form in relation to the sequence or select it is within, however it will squash all of it's child nodes back down into a single string. Node that this will reflect the affects of any omit operations which occurred within the child nodes.
Only one repetition mark should exist per argument.
```bnf
term # once
term? # one or zero
term+ # at least once
term* # zero or more
```
## Not
### Omit `%`
It's `.values` will be a single string of all characters it could consume until it matched with the target expression.
```bnf
%term
```
## Range
This operator will lead to the syntax under this operator being removed from the final syntax tree, however still remain as part of syntax validation. For instance in the BNF syntax above...
Ranges will appear with the `.type` of `range` with `.value` being a single string with the characters consumed by this expression, inclusing any repetition markers (so a range with `+` will be a string of length at least one).
The omit character goes in front af a single term, and must be the front most operator placing it in from of any `not` or `gather` operators.
## Literal
### Not `!`
```bnf
!term
```
This operator must be between two single length constants, this will accept all characters within the range of the two bounds (inclusive).
### Range `->`
```bnf
"a"->"z" # will consume a single character
"a"->"z"* # will consume as many characters as are in the range
```
This operator must be between two single length constants, this will accept all characters within the range of the two bounds (inclusive). Until the repetition count is reached.
The first operand must have no repetitions, however the repetition markers on the last operand will apply to the whole group.
Ranges will appear with the `.type` of `literal` with `.value` being a copy of the exact literal as a string.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc