summaryrefslogtreecommitdiff
path: root/gerber.py
diff options
context:
space:
mode:
authorPaulo Henrique Silva <ph.silva@gmail.com>2013-12-17 18:05:30 -0200
committerPaulo Henrique Silva <ph.silva@gmail.com>2013-12-17 18:05:30 -0200
commitc1518b5dfe7c5265ffa2df60598a0db223263ecb (patch)
treeee1ca2547466a75bd03b240067c1a37ca4cb3ef8 /gerber.py
parente53c6bba9bbdc265ca96396f979f0ad70598fa1c (diff)
downloadgerbonara-c1518b5dfe7c5265ffa2df60598a0db223263ecb.tar.gz
gerbonara-c1518b5dfe7c5265ffa2df60598a0db223263ecb.tar.bz2
gerbonara-c1518b5dfe7c5265ffa2df60598a0db223263ecb.zip
Working version of Gerber RS-274X parser.
Diffstat (limited to 'gerber.py')
-rw-r--r--gerber.py129
1 files changed, 129 insertions, 0 deletions
diff --git a/gerber.py b/gerber.py
new file mode 100644
index 0000000..74da114
--- /dev/null
+++ b/gerber.py
@@ -0,0 +1,129 @@
+#!/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>{f})?"
+ r"(X(?P<x>{number}))?(Y(?P<y>{number}))?"
+ r"(I(?P<i>{number}))?(J(?P<j>{number}))?"
+ r"(?P<op>{op})?\*".format(number=NUMBER, f=FUNCTION, op=COORD_OP)))
+
+ APERTURE_STMT = re.compile(r"(G54)?D\d+\*")
+
+ COMMENT_STMT = re.compile(r"G04(?P<comment>{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)