Mail Archives: geda-user/2018/02/03/16:31:31
On Sat, Feb 03, 2018 at 08:24:14PM +0100, karl AT aspodata DOT se wrote:
> Chad:
> > The pcb file format is a little difficult to interpret and work with.
>
> If you want to write to a pcb file it is straightforward, but parsing a
> random pcb/fp file can be a little problematic, I found some surprising
> examples while scanning through [1] for pin data which i saved to [2].
Well, I don't have problems reading the syntax. My problem are ambiguities
with the semantics. In fact, depending on the tools, parsing pcb file syntax
can be next to trivial:
If you take a closer look at the format, you might notice that it is pretty
close to lisp s-expressions.
Thus, it is not a big deal to customize the lisp reader (that's how lisp
people call the lisp parser) to read this format into a lisp structure:
(defun read-pcb-file (stream)
(let ((*readtable* (copy-readtable *readtable*))
(*read-eval* nil) ; protect against #.(shell "rm -rf /")
(eof-value (gensym "EOF-")))
(set-syntax-from-char #\# #\;) ; inherit comment syntax
(set-syntax-from-char #\] #\)) ; closing delimiter for high resolution list
(set-macro-character #\[ ; read a high resolution list
#'(lambda (stream char)
(declare (ignore char))
(read-delimited-list #\] stream t)))
;; Character specifications are enclosed in quotes _without_ escaping.
;; E.g. #\' and #\\ are encoded as ''' and '\'
(set-macro-character #\'
#'(lambda (stream char)
(declare (ignore char))
(let ((ch (read-char stream t nil t))
(delim (read-char stream t nil t)))
(unless (char= delim #\')
(error "illegal character specification |'~A~A|" ch delim))
ch)))
(do* ((element () (read stream nil eof-value))
(result () (cons element result)))
((eq element eof-value)
(nreverse (rest result))))))
(defun read-pcb (pathname)
"Read a PCB file and store "
(with-open-file (stream pathname)
(read-pcb-file stream)))
(read-pcb "board.pcb")
But this handles only the syntax. The bigger problem seems to get the
semantics right.
> Examples:
> Long lines:
> Pin(0 0 70 36 "1" 257)Pin(0 100 70 36 "2" 1)Pin(0 200 70 36 "3" 1)Pin(0 300 70 36 "4" 1)Pin(0 400 70,,,
The function above handles this properly.
> Handling of ":
> Pin[15200 -15200 15000 2000 16200 7500 """10" 0x001]
And this one also. But myself agrees that this is very ugly.
> Numerical flags in [ ] notation
> Pin[0 20000 6000 2000 6600 3500 "" "1" 0x00004001]
Hmmm, I don't see why converting hex flags into symbolic flags would be a big
deal. But I want to get the basic semantics straight, first.
--
Josef Wolf
jw AT raven DOT inka DOT de
- Raw text -