Guest User

Untitled

a guest
Mar 6th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.71 KB | None | 0 0
  1. #!/usr/bin/perl
  2. use strict; use warnings;
  3. use Data::Dumper;
  4.  
  5. use Sub::Curried;
  6. use Carp qw(croak cluck);
  7.  
  8. my @stream = split /\n/, <<'EOF';
  9. method foo { say $x }
  10. EOF
  11.  
  12. my $state = {
  13. stream => \@stream,
  14. line => 1,
  15. offset => 0,
  16. selected => 0,
  17. };
  18.  
  19. curry scan_lit ($lit, %state) {
  20. my ($line) = @{ $state{stream} }
  21. or return;
  22. my $len = length $lit;
  23. my $offset_match = substr $line, $state{offset}, $len;
  24. if ($offset_match eq $lit) {
  25. return { %state,
  26. offset => $state{offset} +$len,
  27. selected => $state{selected}+$len,
  28. },
  29. $offset_match;
  30. } else {
  31. return;
  32. }
  33. }
  34.  
  35. curry scan_re ($re, %state) {
  36. my ($line) = @{ $state{stream} }
  37. or return;
  38. my $offset_line = substr $line, $state{offset};
  39. if ($offset_line=~/$re/) {
  40. my $len = $+[0] - $-[0];
  41. my $match = substr $offset_line, 0, $len;
  42. return { %state,
  43. offset => $state{offset} +$len,
  44. selected => $state{selected}+$len,
  45. },
  46. $match;
  47. } else {
  48. return;
  49. }
  50. }
  51.  
  52. curry get (%state) {
  53. my ($line) = @{ $state{stream} };
  54. my $len = $state{selected};
  55. my $start = $state{offset} - $len;
  56. return \%state, substr $line, $start, $len;
  57. }
  58. curry const ($const, $ignore) { $const }
  59.  
  60. curry skip (%state) {
  61. return { %state,
  62. selected => 0 };
  63. }
  64.  
  65. {
  66. curry replace ($text, %state) {
  67. my ($line, @rest) = @{ $state{stream} };
  68. my $len = $state{selected};
  69. my $start = $state{offset} - $len;
  70. substr $line, $start, $len, $text;
  71. return { %state,
  72. selected => 0,
  73. offset => $start+length $text,
  74. stream => [ $line, @rest ],
  75. };
  76. }
  77. no warnings 'once';
  78. *insert = replace; # synonym
  79. }
  80.  
  81. curry get_skip (%state, $what) {
  82. return skip(\%state), $what;
  83. }
  84. curry debug_line (%state) {
  85. my ($line) = @{ $state{stream} };
  86. substr $line, $state{offset}, 0, '<-- HERE';
  87. if (my $selected = $state{selected}) {
  88. substr $line, $state{offset}, 0, ']';
  89. substr $line, $state{offset}-$selected, 0, 'SEL-->[';
  90. }
  91.  
  92. return \%state, $line;
  93. }
  94.  
  95. curry try (@parsers, %state) {
  96. my $state = { %state };
  97. my @ret;
  98. for (@parsers) {
  99. ($state, @ret) = $_->($state) or return \%state;
  100. }
  101. return $state, @ret;
  102. }
  103. curry alt (@parsers, %state) {
  104. my $state = { %state };
  105. my @ret;
  106. for (@parsers) {
  107. if (($state, @ret) = $_->(\%state)) {
  108. return $state, @ret;
  109. }
  110. }
  111. return;
  112. }
  113. curry fail ($error, %state) {
  114. my (undef, $line) = debug_line \%state;
  115. croak "Parser error: $line";
  116. }
  117. curry debug ($error, %state) {
  118. my (undef, $line) = debug_line \%state;
  119. cluck "Parser state: $line";
  120. }
  121.  
  122. {
  123. # Set up some test parsers
  124. my $get_token = scan_re(qr/\w+/);
  125. my $get_skip_token = get_skip() << $get_token;
  126. my $skip_space = skip() << const() << scan_re(qr/\s*/);
  127.  
  128. # parse declarator and name
  129. ($state, my $decl) = $get_skip_token->($state);
  130. $state = $skip_space->($state);
  131. ($state, my $name) = $get_token->($state);
  132. $state = replace('', $state);
  133.  
  134. # try a (succeeding) chain of parsers
  135. $state = try [ $skip_space,
  136. scan_lit('{'),
  137. skip(),
  138. replace('do_injected_stuffs;') ],
  139. $state;
  140.  
  141. # try a (failing) chain of parsers
  142. $state = try [ scan_lit('DUMMY'),
  143. replace('This should not be seen;') ],
  144. $state;
  145.  
  146. # Show state, including currently "selected" stuff
  147. $state = try [ $skip_space,
  148. $get_token, ], # token is currently selected
  149. $state;
  150. debug("Ending", $state);
  151. }
Add Comment
Please, Sign In to add comment