#!/usr/bin/env python # -*- coding: utf-8 -*- import re def red(s): return '\033[1;31m{0}\033[0;m'.format(s) class Statement: pass class ParamStmt(Statement): pass class CoordStmt(Statement): pass class ApertureStmt(Statement): pass class CommentStmt(Statement): def __init__(self, comment): self.comment = comment class EofStmt(Statement): pass class UnexpectedStmt(Statement): def __init__(self, line): self.line = line class GerberContext: x = 0 y = 0 class Gerber: NUMBER = r"[\+-]?\d+" FUNCTION = r"G\d{2}" STRING = r"[a-zA-Z0-9_+-/!?<>”’(){}.\|&@# :]+" COORD_OP = r"D[0]?[123]" PARAM_STMT = re.compile(r"%.*%") COORD_STMT = re.compile(( r"(?P{f})?" r"(X(?P{number}))?(Y(?P{number}))?" r"(I(?P{number}))?(J(?P{number}))?" r"(?P{op})?\*".format(number=NUMBER, f=FUNCTION, op=COORD_OP))) APERTURE_STMT = re.compile(r"(G54)?D\d+\*") COMMENT_STMT = re.compile(r"G04(?P{string})\*".format(string=STRING)) EOF_STMT = re.compile(r"M02\*") def __init__(self): self.apertures = {} self.ctx = GerberContext() def parse(self, filename): fp = open(filename, "r") data = fp.readlines() self.tokens = list(self.tokenize(data)) for token in self.tokens: if isinstance(token, UnexpectedStmt): print filename print red("[UNEXPECTED TOKEN]") print self.COORD_STMT.pattern print token.line def tokenize(self, data): multiline = None for i, line in enumerate(data): # remove EOL if multiline: line = multiline + line.strip() else: line = line.strip() # deal with multi-line parameters if line.startswith("%") and not line.endswith("%"): multiline = line continue else: multiline = None # parameter match = self.PARAM_STMT.match(line) if match: yield ParamStmt() continue # coord matches = self.COORD_STMT.finditer(line) if matches: for match in matches: yield CoordStmt() continue # aperture selection match = self.APERTURE_STMT.match(line) if match: yield ApertureStmt() continue # comment match = self.COMMENT_STMT.match(line) if match: yield CommentStmt(match.groupdict("comment")) continue # eof match = self.EOF_STMT.match(line) if match: yield EofStmt() continue yield UnexpectedStmt(line) if __name__ == "__main__": import sys for f in sys.argv[1:]: g = Gerber() g.parse(f)