Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for :keywords as operators in expressions #18

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Mr-Dispatch
Copy link

hopefully not too hacky.
created because having ie. + imported from generic-cl resulted in "weirdly failing" code (+ captured first instance, and expected end of stream).
and using cl:+ or esrap:+ in expressions looked way too ugly (I'm writing some code for "demo of elegance" purposes, so having to explain some wart is a big no-no).

Example:

(parse (:+ character) "abc")

could this be - in principle, not necesarilly my impl. - included into esrap ?

@Mr-Dispatch
Copy link
Author

Ok, I just realized that as this doesn't recur unless the first symbol is a keyword, it won't work for nested expression where the parent expression doesn't have a keyword op. Yay for premature optimization ;-)

So totally unsuitable for real-world usage. But the question of "should esrap support such usage" remains.

@Mr-Dispatch
Copy link
Author

seems it doesn't work for more complex expressions (I don't know what esrap is doing, obviously).

@scymtym
Copy link
Owner

scymtym commented Nov 16, 2023

Thank you for the suggestion.

I think allowing users to refer to the operators of the Esrap expression grammar via additional names is best done as a custom defrule-like macro for at least two reasons:

  1. Esrap's current behavior is to treat sub-expressions of the shape (SYMBOL SUB-EXPRESSION) where SYMBOL does not name an Esrap operator as a "semantic predicate", that is a Common Lisp function that should be called to either accept or reject the parse result produced for SUB-EXPRESSION. Identifying operators by symbol name instead of symbol identity would break existing code with semantic predicates like (my-package:! SUB-EXPRESSION).

  2. The suggested behavior requires a transformation of grammar expressions. Since Esrap sometimes has to interpret grammar expressions at runtime, this transformation would impact performance which is already not great.

In summary, as mentioned above, I would recommend a user-defined macro like

(defun transform-expression (expression)
  (labels ((rec (expression)
             (typecase expression
               ((cons (eql :+)) `(cl:+ ,(rec (second expression))))
               ;; TODO handle rest of the expression grammar
               )))
    (rec expression)))

(defmacro my-defrule (name expression &body options)
  `(esrap:defrule ,name ,(transform-expression expression)
     ,@options))

(my-defrule test (:+ "foo"))

(esrap:parse 'test "foofoo") => ("foo" "foo"), NIL, T

Instead of typecase such a macro should probably use esrap::expression-case although the symbol naming that macro is not exported at the moment. See esrap::check-expression for a use that is similar to a recursive transformation. Note that this solution would be limited to rule definitions and not cover for example (esrap:parse '(:+ "foo") "foofoo").

@Mr-Dispatch
Copy link
Author

Mr-Dispatch commented Nov 16, 2023

Thank you for your kind, oh-so detailed reply.
But my point wasn't to "solve" it just for my demo (that would be lying, by omission of glue code).
Since "we like to juggle with our symbols", I meant it more like a general alternative in cases some expected symbol is shadowed.

So, if it doesn't strike you as "syntactically disgusting", would it be acceptable in the core, or would this belong in "compat" package (which could use the wisdom imparted) ?

EDIT: and a few DSLs allow/require the :whatever for the "key words" to stand out... Except symbol pollution, I like it.
EDIT2: of course, it still doesn't work in direct use, so probably scratch the whole idea ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants