Skip to content

Feature request: Case-insensitive matching for PEG #1758

Description

@oofoe

It would be nice to conveniently do case-insensitive matching in a PEG.

One use for PEGs is defining simple command languages. Mixed-case support is often expected in such a language to simplify user interaction. However it's not enough to just force everything to lower (or upper) case before PEG matching because there may be items where case must be preserved (e.g. strings or external function references). Unfortunately, it's rather arduous to set this up:

(def ugly ~{
   :c (set "Cc")  :a (set "Aa")  :t (set "Tt")
  :command (* :c :a :t)
  :main (* (cmt (<- :command) ,string/ascii-upper))})
> (peg/match ugly "CaT")
@["CAT"]                         

Obviously, this is untenable for anything much more complex. However, @veqq came up with a nice way to automate the composition of a case insensitive matcher and I improved on it a bit to handle glyphs that don't need case matching:

(defn ci [x]
    ['* ;(map (fn [b]
               (cond (and (< 64 b) (< b 91))  ['set (string/format "%c%c" b (+ b 32))]
                     (and (< 96 b) (< b 123)) ['set (string/format "%c%c" (- b 32) b)]
                     (string/format "%c" b))) x)])
> (ci "Cat!")
(* (set "Cc") (set "Aa") (set "Tt") "!")

This produces a structure ready to plug into a grammar:

(def sweet ~{
   :command ,(ci "cat")
  :main (* (cmt (<- :command) ,string/ascii-upper))})
> (peg/match sweet "CaT")
@["CAT"]

Currently, I have to unquote the call to ci to use it, but it would be handy if it was built-in to the PEG directives. If possible, the caret ("^") might be a good shorthand notation, i.e. (^ "cat").

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions