On Wed, May 07, 2014 at 12:44:05AM +0100, John Beard wrote: > Then again, if you ever come across a data type that we didn't have the > foresight to include at the start, you'd have to munge it into a string or > other primitive to express it, or you're back to square one.
That's why *real* sexps work, because they are self describing. The lisp reader only has to read *one* character to decide what to do for a whole element. Greatly simplifying, the lexer is doing this way: there is a big array/hashtable which contains character handling routines. The algorithm is like this: read(stream): ch = read one character from stream f = readtable[ch] return f(stream, ch) f['('](stream, ch): l = empty list read recursively until you reach the ')' adding stuff to l return l f['"'](stream, ch): s = string with the only char ch read chars until you reach the " doing escape processing return s f[any digit, +, -, or .](stream, ch): ch is the first character of a digit parse the whole number return the number f[alphabetic or some other symbol](stream, ch): ch is the first character of a symbol parse the symbol return the symbol f[' '](stream, ch): return read(stream) ; I'm not joking :P, this simply skips blanks f['#'](stream, ch): cower in fear from the whole shebang of macro characters (common lisp specific, not really part of the sexp structure) As you see there is NO unknown data type or structure. There are only about five type of sexps: ; Nothing, i.e. NIL abc ; Symbol "ABC" ; String 123 ; A number ( sexp ) ; A list The 'unknown' thing could be the content/structure of a list. Since you know anyway how is a list structured you can't lose your bearing, just skip it. Example, from a board of mine: (fp_text reference "U24" (at 0 0 270) (layer "B.SilkS") (effects (font (size 1.2 1.2) (thickness 0.12)) (justify-current-line mirror))) (shown with forced string escaping and proper indentation) Adding a custom entry: (fp_text reference "U24" (at 0 0 270) (layer "B.SilkS") (snorple 123 456) ;;; <<< this (effects (font (size 1.2 1.2) (thickness 0.12)) (justify-current-line mirror))) When you see a 'snorple' sentence just skip it, and maybe warn. No problem indeed. *Please note that this only extract the data and build a tree out of it*, it doesn't handle data grammar. However the kicad parser handle a sexp almost linearly (it's a design decision, since it follows a grammar, it's easier that way). More or less it works in this way: read a token, fault if it isn't a '(' read a token switch (token) token is layer: process_layer_subform(); token is effects: process_effects_subform(); otherwise: fault (it doesn't know the generic sexp syntax) process_layer_subform(): read a token as a string, and that's the layer read a token, fault if it isn't a ')' See the issue? it can be adapted to 'skip over' unknown forms, but only with certain limitations; for example you could replace the otherwise with: otherwise: warn and skip until you see the closing ')' where 'skip' means handling string quoting, escaping and keeping track of the nesting (User RPL does flow control in this way :D) As a reference, this would be a more typical sexp representation for the entity above; typical doesn't mean better, it's only a design issue for knowledge representation (I chose this, many other are possible) (fp_text :type reference :string "U24" :at (0 0 270) ; The angle in the position would be maybe in ; another attribute :layer "B.SilkS" :snorple (123 456) :effects (:font (:size (1.2 1.2) :thickness 0.12) :justify-current-line mirror)) (the lists in the form (:key value :key value...) are knows as plists and have functions dedicated to deal with, by the way) -- Lorenzo Marcantonio Logos Srl _______________________________________________ Mailing list: https://launchpad.net/~kicad-developers Post to : kicad-developers@lists.launchpad.net Unsubscribe : https://launchpad.net/~kicad-developers More help : https://help.launchpad.net/ListHelp