← Back to team overview

kicad-developers team mailing list archive

Re: Forward-compatibility in s-expression formats

 

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


References