Advertisement
Guest User

perl 6 pack with length prefixes

a guest
Nov 16th, 2015
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.12 KB | None | 0 0
  1. my grammar template {
  2. token basic_unit { <[a..zA..Z]> [ \d+ | '*' ]? }
  3. token composed_unit { '(' <TOP> ')' }
  4. token prefixed_unit { <length=basic_unit> '/' <unit> }
  5. token unit { <prefixed_unit> | <composed_unit> | <basic_unit> }
  6. token TOP {
  7. <.ws>?
  8. <unit>+ %% <.ws>?
  9. }
  10. }
  11.  
  12. sub mypack ($template, *@list is copy) {
  13.  
  14. my sub count_subunits ($composed) {
  15. my $sum;
  16. for $composed<TOP><unit> -> $unit {
  17. if $unit<composed_unit> -> $subcomposed {
  18. $sum += count_subunits($subcomposed);
  19. } else {
  20. $sum++;
  21. }
  22. }
  23. return $sum;
  24. }
  25.  
  26. my @new_template;
  27. my @new_list;
  28. for template.parse($template).<unit> -> $unit {
  29. if $unit<prefixed_unit> -> $p {
  30. my $subunits = 1;
  31. my $subtemplate = $p<unit>;
  32. if ($p<unit><composed_unit>) -> $composed {
  33. $subunits = count_subunits($composed);
  34. $subtemplate = ~$composed<TOP>;
  35. }
  36.  
  37. my $packed = mypack($subtemplate, @list.splice(0, $subunits, []));
  38.  
  39. @new_template.push($p<length>);
  40. @new_list.push($packed.elems);
  41.  
  42. @new_template.push("a*");
  43. @new_list.push($packed.unpack("a*")); # srsly... :(
  44. } elsif $unit<composed_unit> -> $c {
  45. my $subunits = count_subunits($c);
  46. my @sublist = @list.splice(0, count_subunits($c), []);
  47.  
  48. if $c<TOP><unit>.grep(-> $/ { $<prefixed_unit> }) {
  49. my $packed = mypack($c<TOP>, @sublist);
  50. @new_template.push("a*");
  51. @new_list.push($packed.unpack("a*"));
  52. } else {
  53. # No length prefixes. Let regular pack handle it.
  54. @new_template.push(~$c<TOP>);
  55. @new_list.push(@sublist);
  56. }
  57. } else {
  58. @new_template.push(~$unit);
  59. @new_list.push(@list.shift);
  60. }
  61. }
  62.  
  63. return pack "{ @new_template }" , @new_list;
  64. }
  65.  
  66. say mypack("n/(a* C (C/C)) C", "aap", 65, 66, 67, 68, 69, 70);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement