main
Rithesh03 Update 2: schematic completed and reviewed (rev 2) a5b0bed 13d ago
"""Minimal S-expression reader/writer for KiCad files."""
import re

_TOKEN = re.compile(r'\(|\)|"(?:[^"\\]|\\.)*"|[^\s()]+')


class Sym(str):
    """Unquoted atom (keyword or number)."""


def parse(text):
    stack, cur = [], []
    for m in _TOKEN.finditer(text):
        t = m.group(0)
        if t == "(":
            stack.append(cur)
            cur = []
        elif t == ")":
            done = cur
            cur = stack.pop()
            cur.append(done)
        elif t.startswith('"'):
            cur.append(t[1:-1].replace('\\"', '"').replace("\\\\", "\\"))
        else:
            cur.append(Sym(t))
    return cur[0] if len(cur) == 1 else cur


def dump(node, indent=0):
    pad = "  " * indent
    if isinstance(node, list):
        if not node:
            return "()"
        simple = all(not isinstance(x, list) for x in node)
        if simple:
            return "(" + " ".join(dump(x) for x in node) + ")"
        head = []
        rest = []
        for i, x in enumerate(node):
            if isinstance(x, list):
                rest = node[i:]
                break
            head.append(x)
        out = "(" + " ".join(dump(x) for x in head)
        for x in rest:
            out += "\n" + pad + "  " + dump(x, indent + 1)
        return out + ")"
    if isinstance(node, Sym):
        return str(node)
    if isinstance(node, (int, float)):
        return fmt_num(node)
    s = str(node).replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n")
    return '"' + s + '"'


def fmt_num(v):
    v = round(float(v), 4)
    if v == int(v):
        return str(int(v))
    return ("%.4f" % v).rstrip("0").rstrip(".")


def find(node, key):
    return [x for x in node if isinstance(x, list) and x and x[0] == key]


def find1(node, key):
    r = find(node, key)
    return r[0] if r else None