rain-1 / racket-peg

racket scheme peg-parser
GNU General Public License v3.0
23 stars 8 forks source link

add quantifier repetition #58

Open petrolifero opened 6 years ago

petrolifero commented 6 years ago

to write something like password <- [a-zA-Z0-9]{8}[a-zA-Z0-9]* ; to the password has minimun length of 8. or a <- [a-z]{8,10} to between 8 and 10 char.

or a <- [a-z]{8,} without upper limit, with the semantics of minimun of 8

petrolifero commented 5 years ago

What do you think about A <- B{2,5} becomes simply A <- B B B? B? B?

If so, this can be just syntactic sugar, like &(positive lookahead).

rain-1 commented 5 years ago

I think B B B? B? B? is not good because there are 2^3 ways for it to parse (although maybe this PEG will always go for the first one, so maybe not an issue).

We should use B B (B (B B?)?)? instead

petrolifero commented 5 years ago

I will put one level above primary, before (*+?)

So

A <- B{2,3}? ; will mean B 0, 2 or 3 times. because will be equal to A <- (B{2,3})? ;

rain-1 commented 5 years ago

if we wrote something like B{1,9999} it would generate such an enormous output it might use up to much memory and maybe crash. Should {x,y} be implemented as a new primitive instead of desugared to ()? maybe? May just limiting the values 0 <= x < y <= 256 or something.

petrolifero commented 5 years ago

Maybe with a for generate by {x,y}? So there will not be need to using a cascate of "sk" and be more eficient?

Good

rain-1 commented 5 years ago

I don't understand what you mean

petrolifero commented 5 years ago

If we desugar the range on "ands" and "!", you said, correctly, that we will need a lot of memory because of a greater size of the continuations, right?

When you said that was better to make range a primitive, I think that this primitive can be implemented as

A <- B{x,y}; will become

for i in range(x)
   collect the result of B in a list
for i in range(y-x)
   if B fail
   Then
            break

Execute sk on list of results

When sk is the continuation of B{x,y}

This code is high level, pseudocode of what I propose. What do you think?

rain-1 commented 5 years ago

ah yes, something like that would do it

petrolifero commented 5 years ago

I am thinking about use for/fold as first for in the pseudocode above. As fold operation will be peg-result-join But I dont know yet if the parameters will preserve their values with this kind of operation.

if I use (peg-compile ...) inside a more complex body, something like

(define (f)
      (peg-compile A (lambda (x) x))
      (set! x (pegvm-input-position)))

Supose that, on executing A, the pegvm-input-position was increased by 3. Before executing A, their value was 2. x will be equal to 2 or 5 ??

I am trying to figure out this with some exercises on parameters, they behave in a different way that normal variables.

petrolifero commented 5 years ago

x will be equal to 2.

So, will be need to assign the value of express AND the state of machine(all parameters) on sucess continuation to restore and call peg-result-join on two.

petrolifero commented 5 years ago

There's a function called current-parameterization that may help here. Their conter is call-with-parameterization

rain-1 commented 5 years ago

We should use a named let loop rather than for/fold, I think. I prefer to avoid for and fold.

petrolifero commented 5 years ago

Ok, i will not use "for", but why you dont like it?

petrolifero commented 5 years ago

I try some things on repetition branch, using for(just to have something happen, I will change to named let before merge request).

When I do make install, there's error on character on s-exp, but I don't see what I do to do that. Probably some misuse of syntax object. I cant see yet

rain-1 commented 5 years ago

Can you give me permissions to push to your repo?

https://github.com/petrolifero/racket-peg

I have made one commit and want to push it.

rain-1 commented 5 years ago

The implementation should look kind of like this

#lang racket

(define (peg-compile exp)
  (match exp
    (`(and ,x ,y)
     `(and ,(peg-compile x) ,(peg-compile y)))
    (`(optional ,x)
     `(optional ,(peg-compile x)))
    (`(range ,exp ,a ,b)
     (cond ((> a 0)
            (peg-compile `(and ,exp (range ,exp ,(- a 1) ,(- b 1)))))
           ((and (> b 0) (= a 0))
            (peg-compile `(optional (and ,exp (range ,exp ,0 ,(- b 1))))))
           (else
            'epsilon)))
    (else exp)))

;; > (peg-compile '(range x 3 5))
;; '(and x (and x (and x (optional (and x (optional (and x epsilon)))))))
petrolifero commented 5 years ago

[x] - Push acess

rain-1 commented 5 years ago

ok, pushed! So just the (range-primary k min max) part needs implemented (line 229), and it can be done following the rough sketch above - it wil need to involve the success continuations and stuff though. So studying the implmentation of * (line 175) will be useful.