
What is this?
It parses a formal grammar and returns a parser instance. That parser returns ASTs based on your grammar. SEE IT IN ACTION HERE GitHub source
Install
npm i --save ebnf
(It's compatible with WebPack, and Browserify)
Usage
By the moment we only accept two grammars. BNF and W3C EBNF (compatible with Railroad Diagram Generator)
Create a parser
import { Grammars } from 'ebnf';
let bnfParser = new Grammars.BNF.Parser(bnfGrammar);
let w3cParser = new Grammars.W3C.Parser(railRoadGeneratorGrammar);
Check out the test folder for more examples
BNF Equation example
In this example we use plain BNF to create a simple integer formula parser
Grammar:
<Equation> ::= <BinaryOperation> | <Term>
<Term> ::= "(" <RULE_WHITESPACE> <Equation> <RULE_WHITESPACE> ")" | "(" <RULE_WHITESPACE> <Number> <RULE_WHITESPACE> ")" | <RULE_WHITESPACE> <Number> <RULE_WHITESPACE>
<BinaryOperation> ::= <Term> <RULE_WHITESPACE> <Operator> <RULE_WHITESPACE> <Term>
<Number> ::= <RULE_NEGATIVE> <RULE_NON_ZERO> <RULE_NUMBER_LIST> | <RULE_NON_ZERO> <RULE_NUMBER_LIST> | <RULE_DIGIT>
<Operator> ::= "+" | "-" | "*" | "/" | "^"
<RULE_NUMBER_LIST> ::= <RULE_DIGIT> <RULE_NUMBER_LIST> | <RULE_DIGIT>
<RULE_NEGATIVE> ::= "-"
<RULE_NON_ZERO> ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<RULE_DIGIT> ::= "0" | <RULE_NON_ZERO>
<RULE_WHITESPACE> ::= <RULE_WS> | ""
<RULE_WS> ::= " " <RULE_WHITESPACE> | <EOL> <RULE_WHITESPACE> | " " | <EOL>
import { Grammars } from 'ebnf';
let parser = new Grammars.BNF.Parser(grammar);
parser.getAST('-122 + 2');
parser.getAST( '(2 + (2 * -123)) * 5332');
JSON example
/* https://www.ietf.org/rfc/rfc4627.txt */
value ::= false | null | true | object | array | number | string
BEGIN_ARRAY ::= WS* #x5B WS* /* [ left square bracket */
BEGIN_OBJECT ::= WS* #x7B WS* /* { left curly bracket */
END_ARRAY ::= WS* #x5D WS* /* ] right square bracket */
END_OBJECT ::= WS* #x7D WS* /* } right curly bracket */
NAME_SEPARATOR ::= WS* #x3A WS* /* : colon */
VALUE_SEPARATOR ::= WS* #x2C WS* /* , comma */
WS ::= [#x20#x09#x0A#x0D]+ /* Space | Tab | \n | \r */
false ::= "false"
null ::= "null"
true ::= "true"
object ::= BEGIN_OBJECT (member (VALUE_SEPARATOR member)*)? END_OBJECT
member ::= string NAME_SEPARATOR value
array ::= BEGIN_ARRAY (value (VALUE_SEPARATOR value)*)? END_ARRAY
number ::= "-"? ("0" | [1-9] [0-9]*) ("." [0-9]+)? (("e" | "E") ( "-" | "+" )? ("0" | [1-9] [0-9]*))?
/* STRINGS */
string ::= '"' (([#x20-#x21] | [#x23-#x5B] | [#x5D-#xFFFF]) | #x5C (#x22 | #x5C | #x2F | #x62 | #x66 | #x6E | #x72 | #x74 | #x75 HEXDIG HEXDIG HEXDIG HEXDIG))* '"'
HEXDIG ::= [a-fA-F0-9]
import { Grammars } from 'ebnf';
let parser = new Grammars.W3C.Parser(grammar);
parser.getAST( '{"a":false,"b":"asd\\n asd ","list":[1,2,3,true]}');
AST
Every ast node has the following interface
interface IToken {
type: string;
text: string;
children: IToken[];
start: number;
end: number;
errors: TokenError[];
}
Conventions
We try to keep this tool as much unopinionated and free of conventions as possible. However, we have some conventions:
- All
UPPER_AND_SNAKE_CASE
rules are not emmited on the AST. This option can be deactivated setting the flag keepUpperRules: true
.