nikodemus / esrap

OLD REPOSITORY: Please go to:
https://github.com/scymtym/esrap
81 stars 25 forks source link

can't :destructure (or ...) rule #2

Closed 3b closed 11 years ago

3b commented 13 years ago

OR forms return a single item, which tends to break the destructuring-bind if it is an atom, or binds confusingly (if at all) if it happens to match a more complicated subrule which returns a list.

Not sure if it would be better to add a special case to :destructure, or if OR should always return a list.

(defrule foo-bar (or "foo" (and #\b #\a #\r))
  (:destructure (a)
      a))

(parse 'foo-bar "foo") errors with The value "foo" is not of type LIST.

while (parse 'foo-bar "bar") errors with error while parsing arguments to DESTRUCTURING-BIND: invalid number of elements in ("b" "a" "r") to satisfy lambda list (A):

nikodemus commented 13 years ago

I don't think OR returning a list would be right: that would just make it harder to determine which leg was matched.

Adding ENSURE-LIST to :DESTRUCTURE seems like a better option, but I'd like to see a real use-case first.

Note that you can also always wrap a single item in an AND:

(or (and "foo") (and #\b #\a #\r))

in which case a list is returned in both cases.

3b commented 13 years ago

ensure-list in :destructure wouldn't be quite right, since it would still destructure differently depending on whether the matched subrule returned a list or an atom. Similar problem with wrapping the single items in AND. Rather than using ensure-list I think :destructure would need to check for OR rule, and always wrap it in a list in that case.

Wrapping the whole OR in AND or using :lambda instead of :destructure are valid workarounds, but it would still be nice to not need to think about it.

For real use cases, see most of the uses of :lambda (atx-start, source, source-contents, etc.) in 3bmd/parser.lisp, which would probably all have used :destructure instead of :lambda otherwise.

nikodemus commented 13 years ago

I don't see how ATX-START or SOURCE-CONTENTS would benefit from :DESTRUCTURE. The first seems fine as it is, and the second would really like to use just (:CONCAT T).

SOURCE is a bit nasty, agreed.

I'm a bit wary about making the transform construction too smart, though.

Maybe the indication here is that OR uses should be structured so that all possible productions have the same form?

Eg. for SOURCE something like

(defrule source (or bracketed-source source-contents)
  (:function identity))

(defrule bracketed-source (and "<" source-contents ">")
  (:destructure (b1 text b2)
    (declare (ignore b1 b2))
    text))

?

nikodemus commented 11 years ago

WONTFIX, I guess.