Skip to content

Instantly share code, notes, and snippets.

@irondoge
Last active June 17, 2017 14:50
Show Gist options
  • Save irondoge/fa6c0d4ef5f17a22a26b23c8edcfd06d to your computer and use it in GitHub Desktop.
Save irondoge/fa6c0d4ef5f17a22a26b23c8edcfd06d to your computer and use it in GitHub Desktop.
IronBNF Specifications

IronBNF Specifications

IronBNF is a context-sensitive derivate of the original BNF notation.

Syntax and delimiters

The BNF syntax describe a grammar by defining rules, and each rule may be a block that may contain blocks.

Blocks and precedence

precedence delimiter mandatory description
1 : yes Rule delimiter, separate the rule name from the rule definition
2 {} no Context delimiter, specify the direct preceding block context (see context addition)
3 () no Block delimiter, define a nested block that support multiline definition
3 [] no Block delimiter, define a nested block
4 [?*+] no Block quantifiers, affects the direct preceding block (see quantification)
5 no Block delimiter, behaves like a regular and operator (see concatenation)
6 | no Block delimiter, behaves like a regular or operator (see alternation)

This is a simple example illustrating it:

rule_name:		other_rule
other_rule:		(
					[ 'a' | 'z' ]+
					[ 'A' | 'Z' ]+
)

Entry point

The entry point of any BNF grammar is the only rule that is not required by other rules. It is the top level of the grammar tree and must be named bnf as follow:

bnf:	line [ eol line ]*
line:	[:digit:] '-' [:alnum:]+
eol:	';' | '\n'

Concatenation

Chained blocks without delimiters are concatened by default. Concatenation behaves like a regular and operator. If the left operand is valid, the right operand is never checked.

Alternation

Alternation behaves like a regular or operator. If the left operand is not valid, the right operand is never checked.

Quantification

The quantifier operator specifies how often any preceding block is allowed to occur.

operator description
? Indicates zero or one occurrences
* Indicates zero or more occurrences
+ Indicates one or more occurrences

Context addition

This section is the real addition to the original BNF specification. It allows any defined rule to add elements to other rules. The context delimitor may contain a context action following this syntax:

name syntax description
alternation add block{|rule} The matching block content will be added by alternation to the rule
concatenation add block{+rule} The matching block content will be added by concatenation to the rule

If the refered rule does not exist, it is created.

Automatic character classes

class regex posix ASCII range description
[:ascii:] no [\x00-\x7F] ASCII characters
[:alnum:] yes [A-Za-z0-9] Alphanumeric characters
[:word:] no [A-Za-z0-9_] Alphanumeric characters plus _
[:alpha:] yes [A-Za-z] Alphabetic characters
[:blank:] yes [ \t] Space and tab
[:cntrl:] yes [\x00-\x1F\x7F] Control characters
[:digit:] yes [0-9] Digits
[:graph:] yes [\x21-\x7E] Visible characters
[:lower:] yes [a-z] Lowercase letters
[:print:] yes [\x20-\x7E] Visible characters and the space character
[:punct:] yes [!-/:-@\x5B-\x60{-~] Punctuation characters
[:space:] yes [ \t\r\n\v\f] Whitespace characters
[:upper:] yes [A-Z] Uppercase letters
[:xdigit:] yes [A-Fa-f0-9] Hexadecimal digits

Examples

This is a simple INI file BNF:

bnf:			ini ( eol eol ini )*
ini:			section entry+
section:		'[' wordspecial ']' eol
entry:			word [:blank:]* '=' [:blank:]* wordspecial eol
eol:			'\n\r' | '\n' | '\r'
word:			[:alpha:] [:alnum:]*
wordspecial:	[:alpha:] ( [:alnum:] | '-' )*

A much further example considering this pseudo language code:

alias meh print
define a Hello
print a
alias a world!
meh a

Result: Hello world!

This code defines a variable a and two aliases meh and a. We have the following BNF:

bnf:			line ( eol line )*
line:			var_decl | alias_decl | print
var_decl:		[ alias | keyword ] [:word:]{|var} [ alias | var | value ]
alias_decl:		[ alias | keyword ] [:word:]{|alias} [ alias | keyword | var | value ]
print:			[ alias | keyword ] [ alias | var | value ]
keyword:		'alias' | 'define' | 'print'
value:			[:ascii:]+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment