Grako (for the grammar compiler) allows you to separate the specification of the input format (grammar) from its interpretation (semantics). Here is the grammar for your input format in a variety of Graco EBNF :
(* a file contains zero or more blocks *)
file = {block} $;
(* a named block has at least one assignment statement *)
block = name '{' {assignment}+ '}';
assignment = name '=' value NEWLINE;
name = /[a-z][a-z0-9_]*/;
value = integer | string;
NEWLINE = /\n/;
integer = /[0-9]+/;
(* string value is everything until the next newline *)
string = /[^\n]+/;
To install grako
, run pip install grako
. To create a PEG parser from a grammar:
$ grako -o config_parser.py Config.ebnf
To convert stdin to json using the generated module config_parser
:
import json
import string
import sys
from config_parser import ConfigParser
class Semantics(object):
def file(self, ast):
return dict(ast)
def block(self, ast):
return ast[0], dict(ast[2])
def assignment(self, ast):
return ast[0], ast[2]
def integer(self, ast):
return int(ast)
def string(self, ast):
return ast.strip()
parser = ConfigParser(whitespace='\t\n\v\f\r ', eol_comments_re="#.*?$")
ast = parser.parse(sys.stdin.read(), rule_name='file', semantics=Semantics())
json.dump(ast, sys.stdout, indent=2, sort_keys=True)
Exit
{
"block1": {
"othervalue": 32423432,
"some_value": "some other kind of data",
"value": "data"
},
"block2": {
"othervalue": 32423432,
"some_value": "some other kind of data",
"value": "data"
}
}
source
share