Reputation: 35
I have custom file format that I use for my program in Python. It stores logic gates in human readable form.
[output-0(
or-0(
and-0(
not-0(
input-0()),
not-1(
input-1())),
and-2(
input-0(),
not-1(
input-1())))),
output-1(
or-1(
and-1(
not-0(
input-0()),
input-1()),
and-2(
input-0(),
not-1(
input-1()))))]
And I want to parse it to json, that looks like this:
[
{
"type": "output",
"id": 0,
"i": [
{
"type": "or",
"id": 0,
"i": [
{
"type": "and",
"id": 0,
"i": [
{
"type": "not",
"id": 0,
"i": [
{
"type": "input",
"id": 0,
"i": []
}
]
},
{
"type": "not",
"id": 1,
"i": [
{
"type": "input",
"id": 1,
"i": []
}
]
}
]
},
{
"type": "and",
"id": 2,
"i": [
{
"type": "input",
"id": 0,
"i": []
},
{
"type": "not",
"id": 1,
"i": [
{
"type": "input",
"id": 1,
"i": []
}
]
}
]
}
]
}
]
},
{
"type": "output",
"id": 1,
"i": [
{
"type": "or",
"id": 1,
"i": [
{
"type": "and",
"id": 1,
"i": [
{
"type": "not",
"id": 0,
"i": [
{
"type": "input",
"id": 0,
"i": []
}
]
},
{
"type": "input",
"id": 1,
"i": []
}
]
},
{
"type": "and",
"id": 2,
"i": [
{
"type": "input",
"id": 0,
"i": []
},
{
"type": "not",
"id": 1,
"i": [
{
"type": "input",
"id": 1,
"i": []
}
]
}
]
}
]
}
]
}
]
Or if it is possible to convert it to python dictionary directly without json. All gate types are: and, or, not, buffer, nand, nor, xor, output, input. Thanks for your help.
Upvotes: 1
Views: 303
Reputation: 27201
Define the grammar:
type := word
id := number
func := type-id
call := func(args)
args := none | call {, call}*
root := [args]
Let's make ourselves a parser using pyparsing
:
import json
import pyparsing as pp
def make_parser():
LPAR, RPAR = map(pp.Suppress, "()")
LBRA, RBRA = map(pp.Suppress, "[]")
type_ = pp.Word(pp.alphas)
id_ = pp.Word(pp.nums)
func = type_ + "-" + id_
call = pp.Forward()
args = pp.Optional(call + pp.ZeroOrMore("," + call))
call <<= func + pp.Group(LPAR + args + RPAR)
many = args
root = pp.Group(LBRA + many + RBRA)
id_.setParseAction(parse_id)
args.setParseAction(parse_args)
call.setParseAction(parse_call)
root.setParseAction(parse_root)
return root
Define the actions that will convert the tokens to JSON format:
def parse_id(s, locs, tokens):
opand, = tokens
return int(opand)
def parse_call(s, locs, tokens):
type_, _dash, id_, args = tokens
return {"type": type_, "id": id_, "i": list(args)}
def parse_args(s, locs, tokens):
return tokens[::2]
def parse_root(s, locs, tokens):
root, = tokens
return root
To run:
test = "[output-0()]"
parser = make_parser()
result = parser.parseString(test)[:]
print(json.dumps(result, indent=4))
Complete example:
import json
import pyparsing as pp
def parse_id(s, locs, tokens):
opand, = tokens
return int(opand)
def parse_call(s, locs, tokens):
type_, _dash, id_, args = tokens
return {"type": type_, "id": id_, "i": list(args)}
def parse_args(s, locs, tokens):
return tokens[::2]
def parse_root(s, locs, tokens):
root, = tokens
return root
def make_parser():
LPAR, RPAR = map(pp.Suppress, "()")
LBRA, RBRA = map(pp.Suppress, "[]")
type_ = pp.Word(pp.alphas)
id_ = pp.Word(pp.nums)
func = type_ + "-" + id_
call = pp.Forward()
args = pp.Optional(call + pp.ZeroOrMore("," + call))
call <<= func + pp.Group(LPAR + args + RPAR)
many = args
root = pp.Group(LBRA + many + RBRA)
id_.setParseAction(parse_id)
args.setParseAction(parse_args)
call.setParseAction(parse_call)
root.setParseAction(parse_root)
return root
def main():
test = """[
output-0(
or-0(
and-0(
not-0(
input-0()),
not-1(
input-1())),
and-2(
input-0(),
not-1(
input-1())))),
output-1(
or-1(
and-1(
not-0(
input-0()),
input-1()),
and-2(
input-0(),
not-1(
input-1()))))
]"""
parser = make_parser()
result = parser.parseString(test)[:]
print(json.dumps(result, indent=4))
main()
Upvotes: 2