Haskell server that parses Backus-Naur form (BNF) expressions. Only the syntax is being validated, semantics are not regarded. It converts (for instance) the following BNF
<a> ::= <b>'.'
<b> ::= "b" | 'b'<b>
into this JSON representation:
{
"rules": [
{
"name": "a",
"expr": [
[
{ "ref": "b" },
{ "l": "." }
]
]
},
{
"name": "b",
"expr": [
[
{ "l": "b" }
],
[
{ "l": "b" },
{ "ref": "b" }
]
]
}
]
}
The JSON version is obviously more verbose, but might be easier to handle when it comes to further processing.
You can either run this app with Haskell and Stack installed or start the Docker container. Either way you should go ahead and clone this repository first:
git clone https://github.com/Simsso/BNF-Parser bnf-parser
cd bnf-parser
Starts the server (on port 3000):
stack build --exec bnf-parser-exe
Runs the tests:
stack test bnf-parser:test:bnf-parser-test --test-arguments --color
Builds (takes a couple of minutes) and starts the Docker container
docker build . --tag=bnf-parser
docker run -p 80:3000 bnf-parser
which will make the API accessible at http://localhost:80. The Swagger API specification can be found at /meta-data/api-spec
.
The parser accepts BNFs which satisfy the following definition (taken from the BNF Wikipedia article).
<syntax> ::= <rule> | <rule> <syntax>
<rule> ::= <opt-whitespace> "<" <rule-name> ">" <opt-whitespace> "::=" <opt-whitespace> <expression> <line-end>
<opt-whitespace> ::= " " <opt-whitespace> | ""
<expression> ::= <list> | <list> <opt-whitespace> "|" <opt-whitespace> <expression>
<line-end> ::= <opt-whitespace> <EOL> | <line-end> <line-end>
<list> ::= <term> | <term> <opt-whitespace> <list>
<term> ::= <literal> | "<" <rule-name> ">"
<literal> ::= '"' <text1> '"' | "'" <text2> "'"
<text1> ::= "" | <character1> <text1>
<text2> ::= "" | <character2> <text2>
<character> ::= <letter> | <digit> | <symbol>
<letter> ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<symbol> ::= "|" | " " | "!" | "#" | "$" | "%" | "&" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | ">" | "=" | "<" | "?" | "@" | "[" | "\" | "]" | "^" | "_" | "`" | "{" | "}" | "~"
<character1> ::= <character> | "'"
<character2> ::= <character> | '"'
<rule-name> ::= <letter> | <rule-name> <rule-char>
<rule-char> ::= <letter> | <digit> | "-"