diff options
Diffstat (limited to 'src/ee')
-rw-r--r-- | src/ee/kicad/__init__.py | 8 | ||||
-rw-r--r-- | src/ee/kicad/_parse_kicad_pcb.py | 146 |
2 files changed, 151 insertions, 3 deletions
diff --git a/src/ee/kicad/__init__.py b/src/ee/kicad/__init__.py index d949fbe..efc20a2 100644 --- a/src/ee/kicad/__init__.py +++ b/src/ee/kicad/__init__.py @@ -4,14 +4,16 @@ from ee import EeException from ee.kicad.read_schematic import read_schematic, read_schematics from ee.kicad.to_bom import to_bom, to_bom_xml from .model import * +from ._parse_kicad_pcb import parse_kicad_pcb __all__ = [ - "Position", - "ComponentField", "Component", - "Schematic", + "ComponentField", + "parse_kicad_pcb", + "Position", "read_schematic", "read_schematics", + "Schematic", "to_bom", "to_bom_xml", "to_pandas", diff --git a/src/ee/kicad/_parse_kicad_pcb.py b/src/ee/kicad/_parse_kicad_pcb.py new file mode 100644 index 0000000..5ea4d1b --- /dev/null +++ b/src/ee/kicad/_parse_kicad_pcb.py @@ -0,0 +1,146 @@ +EVENT_START = 1 +EVENT_END = 2 +EVENT_LPAREN = 3 +EVENT_RPAREN = 4 +EVENT_TEXT = 5 + +def state_to_str(s): + if s == EVENT_START: + return "EVENT_START" + if s == EVENT_END: + return "EVENT_END" + if s == EVENT_LPAREN: + return "EVENT_LPAREN" + if s == EVENT_RPAREN: + return "EVENT_RPAREN" + if s == EVENT_TEXT: + return "EVENT_TEXT" + return "UNKNOWN STATE" + +def parse_kicad_pcb(path): + class state(object): + def __init__(self): + self.f = open(path, "r")#, 128 * 1024) + self.state = EVENT_START + self.buffer = [] + + def text(self): + return self._text + + def close(self): + if self.f: + f = self.f + self.f = None + f.close() + + def _read_c(self): + # TODO: count lines and characters + if self.buffer: + c = self.buffer[0] + while c == '\n': + del self.buffer[0] + c = self.buffer[0] + return c + + c = self.f.read(1024) + if not c: + return c + + self.buffer.extend(c) + return self._read_c() + +# if self.buffer: +# c = self.buffer[0] +# del self.buffer[0] +# return c +# +# c = self.f.read(1) +# while c and c == '\n': +# c = self.f.read(1) +# return c + + def _unread(self, s): + for c in s: + self.buffer.append(c) +# print("unreading: '{}', buffer={}".format(s, str(self.buffer))) + + def _read_token(self): + s = "" + while True: + c = self._read_c() + + if not c: + return s if s else None + + if c == " ": + # Ignore leading blanks + if not s: + continue + + if c == "(" or c == ")": + if not s: + return c + self._unread(c) + return s.rstrip() + + if c == " ": + return s + + if c == "\"": + while c: + c = self._read_c() + + if c == "\"": + break + + s += c + return s + s += c + + return s.rstrip() + + def next(self): + s = self.state +# print("next: current state={}, buffer={}".format(self.state_to_str(s), self.buffer)) + self._text = None + if s == EVENT_END: + raise Exception("Invalid state, state=END") + + token = self._read_token() +# print("token={}".format(token)) + + if token is None: + self.state = EVENT_END + self.close() + return (EVENT_END, None) + + if token == "(": + self.state = EVENT_LPAREN + return (EVENT_LPAREN, None) + if token == ")": + self.state = EVENT_RPAREN + return (EVENT_RPAREN, None) + + self._text = token + self.state = EVENT_TEXT + return (EVENT_TEXT, token) + + s = state() + (event, token) = s.next() + while event != EVENT_END: + yield (event, token) + (event, token) = s.next() + +#indent = 0 +#for (event_type, text) in parse_kicad_pcb("alpha.kicad_pcb"): +# if event_type == EVENT_LPAREN: +# prefix = " " * indent +# indent = indent + 1 +# print(prefix + "(") +# elif event_type == EVENT_RPAREN: +# indent = indent - 1 +# prefix = " " * indent +# print(prefix + ")") +# elif event_type == EVENT_TEXT: +# prefix = " " * indent +# print("{}{}".format(prefix, text)) |