Re: parsing in different modes

2018-08-12 Thread yary
>
> I am working with a grammar that I would like to have operate in two
> different modes. In both modes the rules are identical, but the methods
> should behave differently.

...

> As an illustration (not the actual problem), say we want to proces
> arithmetical expressions in two modes: normally we just copy the input, but
> within a pair of braces we directly calculate the result.


My first thought was to subclass the grammar, and re-use the parsing while
overriding some actions. But I didn't look into it, and saw you had an
answer that keeps track of parsing depth.

Still I wanted to try this by having different actions on the top-level vs
inner parsing. To work with the example, I started with a grammar with no
actions.

grammar Sums {
  rule TOP {  }
  token any-expr { + %  }
  token operand {  |  }
  token bracketed-expr { '{'  '}' }
  token op { <[-+]> }
  token int { \d+ }
}

and I realized that the differing actions can be hung on the different
parts of the tree. "bracketed-expr" computes "any-expr", while "TOP" simply
converts it to a string.

class do-sums {
  method TOP($/) {
make $.caps.map: { ($_ || $_.made).Str }
  }
  method operand($/)  { make $ // $.made }
  method bracketed-expr($/) { make evaluate( $/ ) }

  sub evaluate($expr) {
if $expr.caps.elems > 1 {
  return ($expr.caps).reduce: -> $left is rw, (:value(:$op),|), $right
is rw {
$left = evaluate($left) unless $left ~~ Numeric;
$right= evaluate($right);
given $op {
  when '+' { $left + $right }
  when '-' { $left - $right }
}
  }
}

return $expr ?? evaluate($expr)
!! $expr;
  }

}

# Try it out
say Sums.parse('5', actions => do-sums.new).made; # 5
say Sums.parse('{6}+{8-{9+1+2}}-5', actions => do-sums.new).made; # 6 + -4
- 5

Which is a solution to "how do I keep one grammar, but do different things
when the same token matches in different contexts." Not quite Theo's
original question of "how to make a method behave differently at different
parse depths" still it was a fun way to spend all morning...

I'd like to simplify "sub evaluate"-  in particular the deconstructed
argument $op. That positional parameter is a Pair keyed on 'op', is there a
clearer way of assigning it to $op?

-y


Re: Special token names, or my mistake

2018-08-12 Thread yary
Thanks! Timo's explanation nailed it, the problem is with the action not
defining a method for "sum" so Any.sum becomes the action.

The parsing works in grammar B without actions; "sum" is fine as a token
name in that case.

grammar B {
  rule TOP {  }
  token sum { + % '+' }
  token int { \d+ }
}

say B.parse('5');  # OK


Re: Special token names, or my mistake

2018-08-12 Thread Timo Paulssen
The grammar will never by itself try to call a subroutine, it only looks
for methods in the action object. However, there is a "sum" method that
An-Action inherits from Any. You can find it here:
https://github.com/rakudo/rakudo/blob/master/src/core/Any.pm6#L440

It's probably a good idea to put an empty method of the same name that
accepts one argument (the match object) into the action class.

The same problem occurs with any of the other methods that already exist
on Any.

You can find them like this:

    perl6 -e 'Any.^methods(:all).>>.name.put'


Re: Special token names, or my mistake

2018-08-12 Thread Laurent Rosenfeld via perl6-users
Hi Yary,

I'm not sure whether this is really the reason, but sum is the name of a
built-in function (see https://docs.perl6.org/routine/sum). It seems that
the compiler interprets your token as a subroutine call of that builtin.

HTH,
Laurent.


2018-08-12 9:28 GMT+02:00 yary :

> If I call a token "sum", this example gives an error. If I call it
> "something-else", it doesn't. I didn't expect an error in either case.
> What's going on?
>
> ~~ actions-test.p6 ~~
> grammar A {
>   rule TOP {  }
>   token something-else { + % '+' }
>   token int { \d+ }
> }
>
> grammar B {
>   rule TOP {  }
>   token sum { + % '+' }
>   token int { \d+ }
> }
>
> class An-Action {
> }
>
> say A.parse('5',actions => An-Action.new); # OK
> say B.parse('5',actions => An-Action.new); # hopes, dashed
>
> __END__
>
> The B.parse says "Too many positionals passed; expected 1 argument but got
> 2
>   in regex sum at action-test.p6 line 9
>   in regex TOP at action-test.p6 line 8
>   in block  at action-test.p6 line 17"
>
> perl6 -v
> This is Rakudo Star version 2018.06 built on MoarVM version 2018.06
>
>
> -y
>


Special token names, or my mistake

2018-08-12 Thread yary
If I call a token "sum", this example gives an error. If I call it
"something-else", it doesn't. I didn't expect an error in either case.
What's going on?

~~ actions-test.p6 ~~
grammar A {
  rule TOP {  }
  token something-else { + % '+' }
  token int { \d+ }
}

grammar B {
  rule TOP {  }
  token sum { + % '+' }
  token int { \d+ }
}

class An-Action {
}

say A.parse('5',actions => An-Action.new); # OK
say B.parse('5',actions => An-Action.new); # hopes, dashed

__END__

The B.parse says "Too many positionals passed; expected 1 argument but got 2
  in regex sum at action-test.p6 line 9
  in regex TOP at action-test.p6 line 8
  in block  at action-test.p6 line 17"

perl6 -v
This is Rakudo Star version 2018.06 built on MoarVM version 2018.06


-y