Source code for utils.PLAParser
import re
from pathlib import Path
from typing import List, Dict
[docs]
class PLA:
def __init__(self):
"""
.i 3
.o 2
.ilb a b cin
.ob cout s #This is a comment
.type f
.phase 111
000 00
001 01
010 01
011 10
100 01
101 10
110 10
111 11
.e
"""
self.inputs = None
self.outputs = None
self.truthtable = None
self.nkeywords = {
".ilb": 0,
".ob": 0,
".i": 0,
".o": 0,
".p": 0,
".e": 0,
}
[docs]
class PLAParser:
def __init__(self, file_path: Path):
self.pla = PLA()
with open(file_path, 'r') as f:
content = f.read()
# Important: ilb and ob do not always exist.
# ABC will automatically generate input variables and output variables.
# If .i = PI and .ilb is absent, then the input variables are of the form:
# x0 x1 ... xPI
# If .o = PI and .ob is absent, then the output variables are of the form:
# z0 z1 ... zPI
keywords = ["ilb", "ob", "i", "o", "p"]
raw_lines = content.split("\n")
# We strip the comment lines
lines = []
for line in raw_lines:
if not line.startswith("#"):
lines.append(line)
components = dict()
current_keyword = None
halt = False
for i in range(len(lines)):
if halt:
break
line = lines[i]
for keyword in keywords:
if halt:
break
if line.startswith(".{}".format(keyword)):
components[keyword] = [i]
if current_keyword is not None:
components[current_keyword].append(i - 1)
current_keyword = keyword
break
elif not line.startswith('.') and not line.startswith('#'):
if current_keyword is not None:
components[current_keyword].append(i - 1)
halt = True
input_variables = []
output_variables = []
for keyword in keywords:
if keyword == "ilb" and keyword in components:
pretty_content = self._prettify(lines, components, keyword)
input_variables = re.findall(r'([\w\d\[\]]+)', pretty_content)
elif keyword == "ob" and keyword in components:
pretty_content = self._prettify(lines, components, keyword)
output_variables = re.findall(r'([\w\d\[\]]+)', pretty_content)
elif keyword == "i" and "ilb" not in components:
pretty_content = self._prettify(lines, components, keyword)
nr_inputs = int(re.findall(r'(\d+)', pretty_content)[0])
nr_char = len(str(nr_inputs - 1))
fmt = '0{}d'.format(nr_char)
input_variables = [f'x{i:{fmt}}' for i in range(nr_inputs)]
elif keyword == "o" and "ob" not in components:
pretty_content = self._prettify(lines, components, keyword)
nr_outputs = int(re.findall(r'(\d+)', pretty_content)[0])
nr_char = len(str(nr_outputs - 1))
fmt = '0{}d'.format(nr_char)
output_variables = [f'z{i:{fmt}}' for i in range(nr_outputs)]
truthtable = []
for line in lines:
if not line.startswith(".") and not line.startswith("#") and line != "":
[inputs, outputs] = line.split()
truthtable.append(([v for v in inputs], [v for v in outputs]))
self.pla.inputs = input_variables
self.pla.outputs = output_variables
self.pla.truthtable = truthtable
@staticmethod
def _prettify(lines: List, components: Dict, keyword: str):
[start, stop] = components.get(keyword)
raw_content = lines[start:stop + 1]
raw_content = ''.join(raw_content)
return raw_content.replace(".{}".format(keyword), "").replace("\\", "")