smalltalkevaluationpharopetitparser

PetitParser evaluator not working properly


when I try running this code on pharo, my answers are somewhat off. I try evaluating 1-2+3 but for some reason, it does 1- (2+3) and I do not understand why this is so. Thanks for your time.

number :=  #digit asParser plus token trim ==> [ :token | token inputValue asNumber ].

term := PPUnresolvedParser new.
prod := PPUnresolvedParser new.
term2 := PPUnresolvedParser new.
prod2 := PPUnresolvedParser new.
prim := PPUnresolvedParser new.

term def: (prod , $+ asParser trim , term ==> [ :nodes | nodes first + nodes last ]) / term2.

term2 def: (prod , $- asParser trim , term ==> [ :nodes | nodes first - nodes last ])/ prod.

prod def: (prim , $* asParser trim , prod ==> [ :nodes | nodes first * nodes last ])/ prim.

prod2 def: (prim , $/ asParser trim , prod ==> [ :nodes | nodes first / nodes last ])/ prim.

prim def: ($( asParser trim , term , $) asParser trim ==> [ :nodes | nodes second ]) / number.

start := term end.

start parse: '1 - 2 + 3'

Solution

  • Consider the definition of term

    term
        def: prod , $+ asParser trim , term
            ==> [:nodes | nodes first + nodes last]
            / term2.
    

    The / term2 part is an OR between

    prod , $+ asParser trim, term ==> [something]
    

    and

    term2 
    

    Let's mentally parse '1 - 2 + 3' according to term.

    We first read $1 and have to decide between the two options above. The first one will fail unless prod consumes '1 - 2'. But this is impossible because

    prod
        def: prim , $* asParser trim , prod
            ==> [:nodes | nodes first * nodes last]
            / prim.
    
    prim
        def: $( asParser trim , term , $) asParser trim
            ==> [:nodes | nodes second]
            / number
    

    and there is no $* or $( coming, and '1 - 2' is not parsed by #number.

    So, we try with term2, which is defined in a similar way

    term2
        def: prod , $- asParser trim , term
            ==> [:nodes | nodes first - nodes last]
            / prod.
    

    so now we have a OR between two options.

    As above, the first option fails, so we next try prod, then prim and finally number. The number parser begins with

    #digit asParser plus 
    

    which consumes the digit $1 and produces the integer 1.

    We are now back in term2. We consume ' - ' and are left with '2 + 3'; which according to term produces 5. So we get 1 - 5 = -4.


    SHORT EXPLANATION

    For term to parse as (1 - 2) + 3, prod should consume 1 - 2, which doesn't because prod involves no $-.