How to use the parsing racket from the top of the stack - disable the greedy "..."

I have a parser and I am looking for patterns from the top of the stack.

Let's say, for example, that "3" is a separator, and I want the next item from the top of the stack to not matter which item, although in this example the items are "(1 2 7). I do this:

racket@match.rkt> (match '(1 2 7 3 4 5 3 6 7 3 8) [(list i ... 3 s ...) (list i s)])
'((1 2 7 3 4 5 3 6 7) (8))

(match '(1 2 7 3 4 5 3 6 7 3 8) [(list (? number? i) ... 3 s ...) (list i s)])
'((1 2 7 3 4 5 3 6 7) (8))

      

I expected to see '((1 2 7) (4 5 3 6 7 3 8)), but because "..." is "greedy", instead I return almost the entire stack - not what I wanted.

Is there an easy way to pop the patterned elements from the top of the stack?

Here is a second example using more familiar xml like "tags" instead of numbers. Here we have a file, which is a stream of tags, and we want the first section from the file, so:

racket> (match 
    (list "<apple>" "apple-stuff" "</apple>" 
          "<orange>" "orange-stuff" "</orange>" 
          "<apple>" "more-apple-stuff" "</apple>" 
    )
  [(list  "<apple>" a-stuff ... "</apple>" etc ...)
    a-stuff
  ]
)

      

Thus, one might expect the "stuff" to be "apple stuff", but in reality a-stuff is tied to the rest of the file:

  a-stuff>
    '("apple-stuff"
      "</apple>"
      "<orange>"
      "orange-stuff"
      "</orange>"
      "<apple>"
      "more-apple-stuff")

      

These are just simple string matches, if we have structured markers instead, the matching rules get a lot more involved, and "..." means "match to end and back off" will have a more subtle difference than what many people would expect. that it is "match ahead to next match".

+3


source to share


2 answers


One way is to change i ... to match non-3s.

If you're looking for type 3 fixed binding, you can do this:

(match '(1 2 7 3 4 5 3 6 7 3 8) 
   [(list (and i (not 3)) ... 3 s ...) (list i s)])

      



If you need to search for non-datum you can use:

(let ([stop-value 3])
   (match '(1 2 7 3 4 5 3 6 7 3 8) 
     [(list (and i (not (== stop-value))) ... stop-value s ...) (list i s)]))

      

+2


source


...

in the match is always greedy, so I don't think there is a match based solution. I suggest you write a function instead.



0


source







All Articles