| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package JE::Parser; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | our $VERSION = '0.066'; | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 101 |  |  | 101 |  | 43477 | use strict;  # :-( | 
|  | 101 |  |  |  |  | 148 |  | 
|  | 101 |  |  |  |  | 3897 |  | 
| 6 | 101 |  |  | 101 |  | 487 | use warnings;# :-( | 
|  | 101 |  |  |  |  | 157 |  | 
|  | 101 |  |  |  |  | 2827 |  | 
| 7 | 101 |  |  | 101 |  | 459 | no warnings 'utf8'; | 
|  | 101 |  |  |  |  | 157 |  | 
|  | 101 |  |  |  |  | 3966 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 101 |  |  | 101 |  | 493 | use Scalar::Util 'blessed'; | 
|  | 101 |  |  |  |  | 211 |  | 
|  | 101 |  |  |  |  | 56785 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | require JE::Code  ; | 
| 12 |  |  |  |  |  |  | require JE::Number; # ~~~ Don't want to do this | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | import JE::Code 'add_line_number'; | 
| 15 |  |  |  |  |  |  | sub add_line_number; | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | our ($_parser, $global, @_decls, @_stms, $_vars); | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | #----------METHODS---------# | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | sub new { | 
| 22 | 2 |  |  | 2 | 1 | 659 | my %self = ( | 
| 23 |  |  |  |  |  |  | stm_names => [qw[ | 
| 24 |  |  |  |  |  |  | -function block empty if while with for switch try | 
| 25 |  |  |  |  |  |  | labelled var do continue break return throw expr | 
| 26 |  |  |  |  |  |  | ]], | 
| 27 |  |  |  |  |  |  | stm => { | 
| 28 |  |  |  |  |  |  | -function => \&function,  block    => \&block, | 
| 29 |  |  |  |  |  |  | empty    => \&empty,     if       => \&if, | 
| 30 |  |  |  |  |  |  | while    => \&while,     with     => \&with, | 
| 31 |  |  |  |  |  |  | for      => \&for,       switch   => \&switch, | 
| 32 |  |  |  |  |  |  | try      => \&try,       labelled => \&labelled, | 
| 33 |  |  |  |  |  |  | var      => \&var,       do       => \&do, | 
| 34 |  |  |  |  |  |  | continue => \&continue,  break    => \&break, | 
| 35 |  |  |  |  |  |  | return   => \&return,    throw    => \&throw, | 
| 36 |  |  |  |  |  |  | expr     => \&expr_statement, | 
| 37 |  |  |  |  |  |  | }, | 
| 38 |  |  |  |  |  |  | global => pop, | 
| 39 |  |  |  |  |  |  | ); | 
| 40 | 2 |  |  |  |  | 15 | return bless \%self, shift; | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | sub add_statement { | 
| 44 | 0 |  |  | 0 | 1 | 0 | my($self,$name,$parser) = shift; | 
| 45 | 0 |  |  |  |  | 0 | my $in_list; | 
| 46 |  |  |  |  |  |  | #	no warnings 'exiting'; | 
| 47 | 0 |  |  |  |  | 0 | grep $_ eq $name && ++$in_list && goto END_GREP, | 
| 48 | 0 |  | 0 |  |  | 0 | @{$$self{stm_names}}; | 
| 49 | 0 |  |  |  |  | 0 | END_GREP: | 
| 50 | 0 | 0 |  |  |  | 0 | $in_list or unshift @{$$self{stm_names}} ,$name; | 
| 51 | 0 |  |  |  |  | 0 | $$self{stm}{$name} = $parser; | 
| 52 | 0 |  |  |  |  | 0 | return; # Don't return anything for now, because if we return some- | 
| 53 |  |  |  |  |  |  | # thing, even if it's not documented, someone might start | 
| 54 |  |  |  |  |  |  | # relying on it. | 
| 55 |  |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | sub delete_statement { | 
| 58 | 1 |  |  | 1 | 1 | 401 | my $self = shift; | 
| 59 | 1 |  |  |  |  | 4 | for my $name (@_) { | 
| 60 | 4 |  |  |  |  | 21 | delete $$self{stm}{$name}; | 
| 61 | 4 |  |  |  |  | 22 | @{$$self{stm_names}} = | 
|  | 4 |  |  |  |  | 18 |  | 
| 62 | 4 |  |  |  |  | 5 | grep $_ ne $name, @{$$self{stm_names}}; | 
| 63 |  |  |  |  |  |  | } | 
| 64 | 1 |  |  |  |  | 3 | return $self; | 
| 65 |  |  |  |  |  |  | } | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | sub statement_list { | 
| 68 | 2 |  |  | 2 | 1 | 21 | $_[0]{stm_names}; | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | sub parse { | 
| 72 | 11 |  |  | 11 | 1 | 20 | local $_parser = shift; | 
| 73 | 11 |  |  |  |  | 23 | local(@_decls, @_stms); # Doing this here and localising it saves | 
| 74 | 11 |  |  |  |  | 13 | for(@{$_parser->{stm_names}}) { # us from having to do it multiple | 
|  | 11 |  |  |  |  | 35 |  | 
| 75 | 143 | 50 |  |  |  | 140 | push @{/^-/ ? \@_decls : \@_stms}, # times. | 
|  | 143 |  |  |  |  | 453 |  | 
| 76 |  |  |  |  |  |  | $_parser->{stm}{$_}; | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  |  | 
| 79 | 11 |  |  |  |  | 59 | JE::Code::parse($_parser->{global}, @_); | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | sub eval { | 
| 83 | 4 |  |  | 4 | 1 | 21 | shift->parse(@_)->execute | 
| 84 |  |  |  |  |  |  | } | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | #----------PARSER---------# | 
| 87 |  |  |  |  |  |  |  | 
| 88 | 101 |  |  | 101 |  | 645 | use Exporter 5.57 'import'; | 
|  | 101 |  |  |  |  | 2983 |  | 
|  | 101 |  |  |  |  | 9041 |  | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | our @EXPORT_OK = qw/ $h $n $optional_sc $ss $s $S $id_cont | 
| 91 |  |  |  |  |  |  | str num skip ident expr expr_noin statement | 
| 92 |  |  |  |  |  |  | statements expected optional_sc/; | 
| 93 |  |  |  |  |  |  | our @EXPORT_TAGS = ( | 
| 94 |  |  |  |  |  |  | vars => [qw/ $h $n $optional_sc $ss $s $S $id_cont/], | 
| 95 |  |  |  |  |  |  | functions => [qw/ str num skip ident expr expr_noin statement | 
| 96 |  |  |  |  |  |  | statements expected optional_sc /], | 
| 97 |  |  |  |  |  |  | ); | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 101 |  |  | 101 |  | 579 | use re 'taint'; | 
|  | 101 |  |  |  |  | 150 |  | 
|  | 101 |  |  |  |  | 4815 |  | 
| 100 |  |  |  |  |  |  | #use subs qw'statement statements assign assign_noin expr new'; | 
| 101 | 101 |  |  | 101 |  | 517 | use constant JECE => 'JE::Code::Expression'; | 
|  | 101 |  |  |  |  | 232 |  | 
|  | 101 |  |  |  |  | 6895 |  | 
| 102 | 101 |  |  | 101 |  | 537 | use constant JECS => 'JE::Code::Statement'; | 
|  | 101 |  |  |  |  | 162 |  | 
|  | 101 |  |  |  |  | 14935 |  | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | require JE::String; | 
| 105 |  |  |  |  |  |  | import JE::String 'desurrogify'; | 
| 106 |  |  |  |  |  |  | import JE::String 'surrogify'; | 
| 107 |  |  |  |  |  |  | sub desurrogify($); | 
| 108 |  |  |  |  |  |  | sub surrogify($); | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | # die is called with a scalar ref when the  string  contains  what  is | 
| 112 |  |  |  |  |  |  | # expected. This will be converted to a longer message afterwards, which | 
| 113 |  |  |  |  |  |  | # will read something like "Expected %s but found %s"  (probably the most | 
| 114 |  |  |  |  |  |  | # common error message, which is why there is a shorthand). Using an array | 
| 115 |  |  |  |  |  |  | # ref is the easiest way to stop the 'at ..., line ...' from being appended | 
| 116 |  |  |  |  |  |  | # when there is no line break at the end already.  die  is  called  with  a | 
| 117 |  |  |  |  |  |  | # double reference to a  string  if  the  string  is  the  complete  error | 
| 118 |  |  |  |  |  |  | # message. | 
| 119 |  |  |  |  |  |  | # ~~~ We may need a function for this second usage, in case we change the | 
| 120 |  |  |  |  |  |  | #     \\ yet again. | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | # @ret != push @ret, ...  is a funny way of pushing and then checking to | 
| 123 |  |  |  |  |  |  | # see whether anything was pushed. | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | sub expected($) { # public | 
| 127 | 21 |  |  | 21 | 0 | 205 | die \shift | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | # public vars: | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | # optional horizontal comments and whitespace | 
| 134 |  |  |  |  |  |  | our $h = qr( | 
| 135 |  |  |  |  |  |  | (?> [ \t\x0b\f\xa0\p{Zs}]* ) | 
| 136 |  |  |  |  |  |  | (?> (?>/\*[^\cm\cj\x{2028}\x{2029}]*?\*/) [ \t\x0b\f\xa0\p{Zs}]* )? | 
| 137 | 1 |  |  | 1 |  | 540 | )x; | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | # line terminators | 
| 140 |  |  |  |  |  |  | our $n = qr((?>[\cm\cj\x{2028}\x{2029}])); | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | # single space char | 
| 143 |  |  |  |  |  |  | our $ss = qr((?>[\p{Zs}\s\ck\x{2028}\x{2029}])); | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | # optional comments and whitespace | 
| 146 |  |  |  |  |  |  | our $s = qr((?> | 
| 147 |  |  |  |  |  |  | (?> $ss* ) | 
| 148 |  |  |  |  |  |  | (?> (?> //[^\cm\cj\x{2028}\x{2029}]* (?>$n|\z) | /\*.*?\*/ ) | 
| 149 |  |  |  |  |  |  | (?> $ss* ) | 
| 150 |  |  |  |  |  |  | ) * | 
| 151 |  |  |  |  |  |  | ))sx; | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | # mandatory comments/whitespace | 
| 154 |  |  |  |  |  |  | our $S = qr( | 
| 155 |  |  |  |  |  |  | (?> | 
| 156 |  |  |  |  |  |  | $ss | 
| 157 |  |  |  |  |  |  | | | 
| 158 |  |  |  |  |  |  | //[^\cm\cj\x{2028}\x{2029}]* | 
| 159 |  |  |  |  |  |  | | | 
| 160 |  |  |  |  |  |  | /\*.*?\*/ | 
| 161 |  |  |  |  |  |  | ) | 
| 162 |  |  |  |  |  |  | $s | 
| 163 |  |  |  |  |  |  | )xs; | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | our $id_cont = qr( | 
| 166 |  |  |  |  |  |  | (?> | 
| 167 |  |  |  |  |  |  | \\u([0-9A-Fa-f]{4}) | 
| 168 |  |  |  |  |  |  | | | 
| 169 |  |  |  |  |  |  | [\p{ID_Continue}\$_] | 
| 170 |  |  |  |  |  |  | ) | 
| 171 |  |  |  |  |  |  | )x; | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | # end public vars | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | sub str() { # public | 
| 177 |  |  |  |  |  |  | # For very long strings (>~45000), this pattern hits a perl bug (Complex regular subexpression recursion limit (32766) exceeded) | 
| 178 |  |  |  |  |  |  | #/\G (?: '((?>(?:[^'\\] | \\.)*))' | 
| 179 |  |  |  |  |  |  | #          | | 
| 180 |  |  |  |  |  |  | #        "((?>(?:[^"\\] | \\.)*))"  )/xcgs or return; | 
| 181 |  |  |  |  |  |  | # There are two solutions: | 
| 182 |  |  |  |  |  |  | # 1) Use the unrolling technique from the Owl Book. | 
| 183 |  |  |  |  |  |  | # 2) Use shorter patterns but more code (contributed by Kevin | 
| 184 |  |  |  |  |  |  | #    Cameron) | 
| 185 |  |  |  |  |  |  | # Number 1 should be faster, but it crashes under perl 5.8.8 on | 
| 186 |  |  |  |  |  |  | # Windows, and perhaps on other platforms, too. So we use #2 for | 
| 187 |  |  |  |  |  |  | # 5.8.x regardless of platform to be on the safe side. | 
| 188 |  |  |  |  |  |  |  | 
| 189 | 101 |  |  | 101 |  | 228300 | use constant old_perl => $] < 5.01;        # Use a constant so the | 
|  | 101 |  |  |  |  | 219 |  | 
|  | 101 |  |  |  |  | 31087 |  | 
| 190 | 42085 |  |  | 42085 | 0 | 83859 | my $yarn;                                   # if-block disappears | 
| 191 | 42085 |  |  |  |  | 36777 | if(old_perl) {                              # at compile-time. | 
| 192 |  |  |  |  |  |  | # Use a simpler pattern (but more code) to break strings up | 
| 193 |  |  |  |  |  |  | # into extents bounded by the quote or escape | 
| 194 |  |  |  |  |  |  | my $qt = substr($_,pos($_),1); | 
| 195 |  |  |  |  |  |  | $qt =~ /['"]/ or return; # not a string literal if first | 
| 196 |  |  |  |  |  |  | pos($_)++;               # char not a quote | 
| 197 |  |  |  |  |  |  | my $done = 0; | 
| 198 |  |  |  |  |  |  | while (defined(substr($_,pos($_),1))) { | 
| 199 |  |  |  |  |  |  | my ($part) = /\G([^\\$qt]*)/xcgs; | 
| 200 |  |  |  |  |  |  | defined($part) or $part = ""; | 
| 201 |  |  |  |  |  |  | $yarn .= $part; | 
| 202 |  |  |  |  |  |  | my $next = substr($_,pos($_)++,1); | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | if ($next eq "\\") { | 
| 205 |  |  |  |  |  |  | #pass on any escaped char | 
| 206 |  |  |  |  |  |  | $next = substr($_,pos($_)++,1); | 
| 207 |  |  |  |  |  |  | $yarn .= "\\$next"; | 
| 208 |  |  |  |  |  |  | } else { | 
| 209 |  |  |  |  |  |  | # handle end quote | 
| 210 |  |  |  |  |  |  | $done = 1; | 
| 211 |  |  |  |  |  |  | last; | 
| 212 |  |  |  |  |  |  | } | 
| 213 |  |  |  |  |  |  | } | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | # error if EOF before end of string | 
| 216 |  |  |  |  |  |  | return if !$done; | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  | else { | 
| 219 | 42085 | 100 |  |  |  | 205166 | /\G (?: '([^'\\]*(?:\\.[^'\\]*)*)' | 
| 220 |  |  |  |  |  |  | | | 
| 221 |  |  |  |  |  |  | "([^"\\]*(?:\\.[^"\\]*)*)"  )/xcgs or return; | 
| 222 | 9838 |  |  |  |  | 24528 | $yarn = $+; | 
| 223 |  |  |  |  |  |  | } | 
| 224 |  |  |  |  |  |  | # Get rid of that constant, as it’s no longer needed. | 
| 225 | 101 |  |  | 101 |  | 614 | BEGIN { no strict; delete ${__PACKAGE__.'::'}{old_perl}; } | 
|  | 101 |  |  | 101 |  | 171 |  | 
|  | 101 |  |  |  |  | 4640 |  | 
|  | 101 |  |  |  |  | 181 |  | 
|  | 101 |  |  |  |  | 2456 |  | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | # transform special chars | 
| 228 | 101 |  |  | 101 |  | 546 | no re 'taint'; # I need eval "qq-..." to work | 
|  | 101 |  |  |  |  | 181 |  | 
|  | 101 |  |  |  |  | 42159 |  | 
| 229 | 9838 |  |  |  |  | 19780 | $yarn =~ s/\\(?: | 
| 230 |  |  |  |  |  |  | u([0-9a-fA-F]{4}) | 
| 231 |  |  |  |  |  |  | | | 
| 232 |  |  |  |  |  |  | x([0-9a-fA-F]{2}) | 
| 233 |  |  |  |  |  |  | | | 
| 234 |  |  |  |  |  |  | (\r\n?|[\n\x{2028}\x{2029}]) | 
| 235 |  |  |  |  |  |  | | | 
| 236 |  |  |  |  |  |  | ([bfnrt]) | 
| 237 |  |  |  |  |  |  | | | 
| 238 |  |  |  |  |  |  | (v) | 
| 239 |  |  |  |  |  |  | | | 
| 240 |  |  |  |  |  |  | ([0-3][0-7]{0,2}|[4-7][0-7]?) # actually slightly looser | 
| 241 |  |  |  |  |  |  | |                    # than what ECMAScript v3 has in its | 
| 242 |  |  |  |  |  |  | (.)           # addendum (it forbids \0 when followed by 8) | 
| 243 |  |  |  |  |  |  | )/ | 
| 244 | 22012 | 100 |  |  |  | 175275 | $1 ? chr(hex $1) : | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | $2 ? chr(hex $2) : | 
| 246 |  |  |  |  |  |  | $3 ? "" :               # escaped line feed disappears | 
| 247 |  |  |  |  |  |  | $4 ? eval "qq-\\$4-" : | 
| 248 |  |  |  |  |  |  | $5 ? "\cK" : | 
| 249 |  |  |  |  |  |  | defined $6 ? chr oct $6 : | 
| 250 |  |  |  |  |  |  | $7 | 
| 251 |  |  |  |  |  |  | /sgex; | 
| 252 | 9838 |  |  |  |  | 44389 | "s$yarn"; | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | sub  num() { # public | 
| 256 | 32247 | 100 |  | 32247 | 0 | 369852 | /\G (?: | 
| 257 |  |  |  |  |  |  | 0[Xx] ([A-Fa-f0-9]+) | 
| 258 |  |  |  |  |  |  | | | 
| 259 |  |  |  |  |  |  | 0 ([01234567]+) | 
| 260 |  |  |  |  |  |  | | | 
| 261 |  |  |  |  |  |  | (?=[0-9]|\.[0-9]) | 
| 262 |  |  |  |  |  |  | ( | 
| 263 |  |  |  |  |  |  | (?:0|[1-9][0-9]*)? | 
| 264 |  |  |  |  |  |  | (?:\.[0-9]*)? | 
| 265 |  |  |  |  |  |  | (?:[Ee][+-]?[0-9]+)? | 
| 266 |  |  |  |  |  |  | ) | 
| 267 |  |  |  |  |  |  | ) /xcg | 
| 268 |  |  |  |  |  |  | or return; | 
| 269 | 21597 | 100 |  |  |  | 131163 | return defined $1 ? hex $1 : defined $2 ? oct $2 : $3; | 
|  |  | 100 |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | our $ident = qr( | 
| 273 |  |  |  |  |  |  | (?! (?: case | default )  (?!$id_cont) ) | 
| 274 |  |  |  |  |  |  | (?: | 
| 275 |  |  |  |  |  |  | \\u[0-9A-Fa-f]{4} | 
| 276 |  |  |  |  |  |  | | | 
| 277 |  |  |  |  |  |  | [\p{ID_Start}\$_] | 
| 278 |  |  |  |  |  |  | ) | 
| 279 |  |  |  |  |  |  | (?> $id_cont* ) | 
| 280 |  |  |  |  |  |  | )x; | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | sub unescape_ident($) { | 
| 283 | 23697 |  |  | 23697 | 0 | 31991 | my $ident = shift; | 
| 284 | 23697 |  |  |  |  | 31158 | $ident =~ s/\\u([0-9a-fA-F]{4})/chr hex $1/ge; | 
|  | 18 |  |  |  |  | 126 |  | 
| 285 | 23697 |  |  |  |  | 64095 | $ident = desurrogify $ident; | 
| 286 | 23697 | 100 |  |  |  | 90301 | $ident =~ /^[\p{ID_Start}\$_] | 
| 287 |  |  |  |  |  |  | [\p{ID_Continue}\$_]* | 
| 288 |  |  |  |  |  |  | \z/x | 
| 289 |  |  |  |  |  |  | or die \\"'$ident' is not a valid identifier"; | 
| 290 | 23696 |  |  |  |  | 118828 | $ident; | 
| 291 |  |  |  |  |  |  | } | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | # public | 
| 294 | 34806 |  |  | 34806 | 0 | 168471 | sub skip() { /\G$s/g } # skip whitespace | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | sub ident() { # public | 
| 297 | 6483 | 100 |  | 6483 | 0 | 44785 | return unless my($ident) = /\G($ident)/cgox; | 
| 298 | 5553 |  |  |  |  | 76073 | unescape_ident $ident; | 
| 299 |  |  |  |  |  |  | } | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | sub params() { # Only called when we know we need it, which is why it dies | 
| 302 |  |  |  |  |  |  | # on the second line | 
| 303 | 364 |  |  | 364 | 0 | 480 | my @ret; | 
| 304 | 364 | 50 |  |  |  | 1301 | /\G\(/gc or expected "'('"; | 
| 305 | 364 |  |  |  |  | 658 | &skip; | 
| 306 | 364 | 100 |  |  |  | 1853 | if (@ret != push @ret, &ident) { # first identifier (not prec. | 
| 307 |  |  |  |  |  |  | # by comma) | 
| 308 | 111 |  |  |  |  | 1540 | while (/\G$s,$s/gc) { | 
| 309 |  |  |  |  |  |  | # if there's a comma we need another ident | 
| 310 | 100 | 100 |  |  |  | 8495 | @ret != push @ret, &ident or expected 'identifier'; | 
| 311 |  |  |  |  |  |  | } | 
| 312 | 109 |  |  |  |  | 2681 | &skip; | 
| 313 |  |  |  |  |  |  | } | 
| 314 | 362 | 100 |  |  |  | 1278 | /\G\)/gc or expected "')'"; | 
| 315 | 360 |  |  |  |  | 890 | \@ret; | 
| 316 |  |  |  |  |  |  | } | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | sub term() { | 
| 319 | 61769 |  |  | 61769 | 0 | 102415 | my $pos = pos; | 
| 320 | 61769 |  |  |  |  | 52231 | my $tmp; | 
| 321 | 61769 | 100 | 100 |  |  | 439107 | if(/\Gfunction(?!$id_cont)$s/cg) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 322 | 163 |  |  |  |  | 468 | my @ret = (func => ident); | 
| 323 | 163 | 100 |  |  |  | 4264 | @ret == 2 and &skip; | 
| 324 | 163 |  |  |  |  | 387 | push @ret, ¶ms; | 
| 325 | 163 |  |  |  |  | 330 | &skip; | 
| 326 | 163 | 50 |  |  |  | 591 | /\G \{ /gcx or expected "'{'"; | 
| 327 |  |  |  |  |  |  | { | 
| 328 | 163 |  |  |  |  | 204 | local $_vars = []; | 
|  | 163 |  |  |  |  | 327 |  | 
| 329 | 163 |  |  |  |  | 394 | push @ret, &statements, $_vars; | 
| 330 |  |  |  |  |  |  | } | 
| 331 | 163 | 50 |  |  |  | 774 | /\G \} /gocx or expected "'}'"; | 
| 332 |  |  |  |  |  |  |  | 
| 333 | 163 |  |  |  |  | 1253 | return bless [[$pos, pos], @ret], JECE; | 
| 334 |  |  |  |  |  |  | } | 
| 335 |  |  |  |  |  |  | # We don’t call the ident subroutine here, | 
| 336 |  |  |  |  |  |  | # because we need to sift out null/true/false/this. | 
| 337 |  |  |  |  |  |  | elsif(($tmp)=/\G($ident)/cgox) { | 
| 338 | 20040 | 100 |  |  |  | 122225 | $tmp=~/^(?:(?:tru|fals)e|null)\z/ &&return $global->$tmp; | 
| 339 | 18271 | 100 |  |  |  | 36994 | $tmp eq 'this' and return $tmp; | 
| 340 | 18055 |  |  |  |  | 32698 | return "i" . unescape_ident $tmp; | 
| 341 |  |  |  |  |  |  | } | 
| 342 |  |  |  |  |  |  | elsif(defined($tmp = &str) or | 
| 343 |  |  |  |  |  |  | defined($tmp = &num)) { | 
| 344 | 31344 |  |  |  |  | 140153 | return $tmp; | 
| 345 |  |  |  |  |  |  | } | 
| 346 |  |  |  |  |  |  | elsif(m-\G | 
| 347 |  |  |  |  |  |  | / | 
| 348 |  |  |  |  |  |  | ( (?:[^/*\\[] | \\. | \[ (?>(?:[^]\\] | \\.)*) \] ) | 
| 349 |  |  |  |  |  |  | (?>(?:[^/\\[] | \\. | \[ (?>(?:[^]\\] | \\.)*) \] )*) ) | 
| 350 |  |  |  |  |  |  | / | 
| 351 |  |  |  |  |  |  | ($id_cont*) | 
| 352 |  |  |  |  |  |  | -cogx ) { | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | #  I have to use local *_ because | 
| 355 |  |  |  |  |  |  | # 'require JE::Object::RegExp' causes | 
| 356 |  |  |  |  |  |  | #  Scalar::Util->import() to be called (import is inherited | 
| 357 |  |  |  |  |  |  | #  from Exporter), and  &Exporter::import does  'local $_', | 
| 358 |  |  |  |  |  |  | #  which,  in p5.8.8  (though not  5.9.5)  causes  pos() | 
| 359 |  |  |  |  |  |  | #  to be reset. | 
| 360 | 317 |  |  |  |  | 488 | { local *_; require JE::Object::RegExp; } | 
|  | 317 |  |  |  |  | 755 |  | 
|  | 317 |  |  |  |  | 3172 |  | 
| 361 |  |  |  |  |  |  | # ~~~ This needs to unescape the flags. | 
| 362 | 317 |  |  |  |  | 1516 | return JE::Object::RegExp->new( $global, $1, $2); | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  | elsif(/\G\[$s/cg) { | 
| 365 | 5291 |  |  |  |  | 6620 | my $anon; | 
| 366 |  |  |  |  |  |  | my @ret; | 
| 367 | 0 |  |  |  |  | 0 | my $length; | 
| 368 |  |  |  |  |  |  |  | 
| 369 | 5291 |  |  |  |  | 5281 | while () { | 
| 370 | 20890 | 100 |  |  |  | 34222 | @ret != ($length = push @ret, &assign) and &skip; | 
| 371 | 20890 |  |  |  |  | 171778 | push @ret, bless \$anon, 'comma' while /\G,$s/cg; | 
| 372 | 20890 | 100 |  |  |  | 47567 | $length == @ret and last; | 
| 373 |  |  |  |  |  |  | } | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 5291 | 100 |  |  |  | 15656 | /\G]/cg or expected "']'"; | 
| 376 | 5287 |  |  |  |  | 49632 | return bless [[$pos, pos], array => @ret], JECE; | 
| 377 |  |  |  |  |  |  | } | 
| 378 |  |  |  |  |  |  | elsif(/\G\{$s/cg) { | 
| 379 | 552 |  |  |  |  | 6363 | my @ret; | 
| 380 |  |  |  |  |  |  |  | 
| 381 | 552 | 100 | 66 |  |  | 1093 | if($tmp = &ident or defined($tmp = &str)&&$tmp=~s/^s// or | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 382 |  |  |  |  |  |  | defined($tmp = &num)) { | 
| 383 |  |  |  |  |  |  | # first elem, not preceded by comma | 
| 384 | 125 |  |  |  |  | 251 | push @ret, $tmp; | 
| 385 | 125 |  |  |  |  | 253 | &skip; | 
| 386 | 125 | 50 |  |  |  | 1678 | /\G:$s/cggg or expected 'colon'; | 
| 387 | 125 | 50 |  |  |  | 3721 | @ret != push @ret, &assign | 
| 388 |  |  |  |  |  |  | or expected \'expression'; | 
| 389 | 125 |  |  |  |  | 290 | &skip; | 
| 390 |  |  |  |  |  |  |  | 
| 391 | 125 |  |  |  |  | 1009 | while (/\G,$s/cg) { | 
| 392 |  |  |  |  |  |  | $tmp = ident | 
| 393 |  |  |  |  |  |  | or defined($tmp = &str)&&$tmp=~s/^s// or | 
| 394 |  |  |  |  |  |  | defined($tmp = &num) | 
| 395 | 101 | 100 | 66 |  |  | 1731 | or do { | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 396 |  |  |  |  |  |  | # ECMAScript 5 allows a | 
| 397 |  |  |  |  |  |  | # trailing comma | 
| 398 | 1 | 50 |  |  |  | 10 | /\G}/cg or expected | 
| 399 |  |  |  |  |  |  | "'}', identifier, or string or ". | 
| 400 |  |  |  |  |  |  | " number literal"; | 
| 401 | 1 |  |  |  |  | 14 | return bless [[$pos, pos], | 
| 402 |  |  |  |  |  |  | hash => @ret], JECE; | 
| 403 |  |  |  |  |  |  | }; | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 100 |  |  |  |  | 230 | push @ret, $tmp; | 
| 406 | 100 |  |  |  |  | 172 | &skip; | 
| 407 | 100 | 50 |  |  |  | 755 | /\G:$s/cggg or expected 'colon'; | 
| 408 | 100 | 50 |  |  |  | 2060 | @ret != push @ret, &assign | 
| 409 |  |  |  |  |  |  | or expected 'expression'; | 
| 410 | 100 |  |  |  |  | 213 | &skip; | 
| 411 |  |  |  |  |  |  | } | 
| 412 |  |  |  |  |  |  | } | 
| 413 | 551 | 50 |  |  |  | 3598 | /\G}/cg or expected "'}'"; | 
| 414 | 551 |  |  |  |  | 5132 | return bless [[$pos, pos], hash => @ret], JECE; | 
| 415 |  |  |  |  |  |  | } | 
| 416 |  |  |  |  |  |  | elsif (/\G\($s/cg) { | 
| 417 | 812 | 50 |  |  |  | 6366 | my $ret = &expr or expected 'expression'; | 
| 418 | 812 |  |  |  |  | 1567 | &skip; | 
| 419 | 812 | 50 |  |  |  | 3268 | /\G\)/cg or expected "')'"; | 
| 420 | 812 |  |  |  |  | 3328 | return $ret; | 
| 421 |  |  |  |  |  |  | } | 
| 422 |  |  |  |  |  |  | return | 
| 423 | 3250 |  |  |  |  | 127937 | } | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | sub subscript() { # skips leading whitespace | 
| 426 | 71601 |  |  | 71601 | 0 | 97120 | my $pos = pos; | 
| 427 | 71601 |  |  |  |  | 61044 | my $subscript; | 
| 428 | 71601 | 100 |  |  |  | 790986 | if (/\G$s\[$s/cg) { | 
|  |  | 100 |  |  |  |  |  | 
| 429 | 1012 | 50 |  |  |  | 1873 | $subscript = &expr or expected 'expression'; | 
| 430 | 1012 |  |  |  |  | 1811 | &skip; | 
| 431 | 1012 | 50 |  |  |  | 3161 | /\G]/cog or expected "']'"; | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  | elsif (/\G$s\.$s/cg) { | 
| 434 | 4220 | 50 |  |  |  | 9992 | $subscript = &ident or expected 'identifier'; | 
| 435 |  |  |  |  |  |  | } | 
| 436 | 66369 |  |  |  |  | 222259 | else { return } | 
| 437 |  |  |  |  |  |  |  | 
| 438 | 5232 |  |  |  |  | 32420 | return bless [[$pos, pos], $subscript], 'JE::Code::Subscript'; | 
| 439 |  |  |  |  |  |  | } | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | sub args() { # skips leading whitespace | 
| 442 | 71569 |  |  | 71569 | 0 | 86240 | my $pos = pos; | 
| 443 | 71569 |  |  |  |  | 61429 | my @ret; | 
| 444 | 71569 | 100 |  |  |  | 793666 | /\G$s\($s/gc or return; | 
| 445 | 10414 | 100 |  |  |  | 30066 | if (@ret != push @ret, &assign) { # first expression (not prec. | 
| 446 |  |  |  |  |  |  | # by comma) | 
| 447 | 9030 |  |  |  |  | 56581 | while (/\G$s,$s/gc) { | 
| 448 |  |  |  |  |  |  | # if there's a comma we need another expression | 
| 449 | 9255 | 50 |  |  |  | 28832 | @ret != push @ret, &assign | 
| 450 |  |  |  |  |  |  | or expected 'expression'; | 
| 451 |  |  |  |  |  |  | } | 
| 452 | 9030 |  |  |  |  | 20654 | &skip; | 
| 453 |  |  |  |  |  |  | } | 
| 454 | 10414 | 100 |  |  |  | 33488 | /\G\)/gc or expected "')'"; | 
| 455 | 10412 |  |  |  |  | 81711 | return bless [[$pos, pos], @ret], 'JE::Code::Arguments'; | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | sub new_expr() { | 
| 459 | 62776 | 100 |  | 62776 | 0 | 397027 | /\G new(?!$id_cont) $s /cgx or return; | 
| 460 | 1007 |  |  |  |  | 5547 | my $ret = bless [[pos], 'new'], JECE; | 
| 461 |  |  |  |  |  |  |  | 
| 462 | 1007 |  |  |  |  | 1758 | my $pos = pos; | 
| 463 | 1007 |  | 33 |  |  | 2039 | my @member_expr = &new_expr || &term | 
| 464 |  |  |  |  |  |  | || expected "identifier, literal, 'new' or '('"; | 
| 465 |  |  |  |  |  |  |  | 
| 466 | 1007 |  |  |  |  | 2498 | 0 while @member_expr != push @member_expr, &subscript; | 
| 467 |  |  |  |  |  |  |  | 
| 468 | 1007 | 100 |  |  |  | 3311 | push @$ret, @member_expr == 1 ? @member_expr : | 
| 469 |  |  |  |  |  |  | bless [[$pos, pos], 'member/call', @member_expr], | 
| 470 |  |  |  |  |  |  | JECE; | 
| 471 | 1007 |  |  |  |  | 2065 | push @$ret, args; | 
| 472 | 1007 |  |  |  |  | 4726 | $ret; | 
| 473 |  |  |  |  |  |  | } | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | sub left_expr() { | 
| 476 | 61769 |  |  | 61769 | 0 | 73204 | my($pos,@ret) = pos; | 
| 477 | 61769 | 100 | 100 |  |  | 90232 | @ret != push @ret, &new_expr || &term or return; | 
| 478 |  |  |  |  |  |  |  | 
| 479 | 58509 |  |  |  |  | 125114 | 0 while @ret != push @ret, &subscript, &args; | 
| 480 | 58507 | 100 |  |  |  | 298985 | @ret ? @ret == 1 ? @ret : | 
|  |  | 50 |  |  |  |  |  | 
| 481 |  |  |  |  |  |  | bless([[$pos, pos], 'member/call', @ret], | 
| 482 |  |  |  |  |  |  | JECE) | 
| 483 |  |  |  |  |  |  | : return; | 
| 484 |  |  |  |  |  |  | } | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | sub postfix() { | 
| 487 | 61769 |  |  | 61769 | 0 | 87990 | my($pos,@ret) = pos; | 
| 488 | 61769 | 100 |  |  |  | 86984 | @ret != push @ret, &left_expr or return; | 
| 489 | 58507 |  |  |  |  | 209802 | push @ret, $1 while /\G $h ( \+\+ | -- ) /cogx; | 
| 490 | 58507 | 100 |  |  |  | 198567 | @ret == 1 ? @ret : bless [[$pos, pos], 'postfix', @ret], | 
| 491 |  |  |  |  |  |  | JECE; | 
| 492 |  |  |  |  |  |  | } | 
| 493 |  |  |  |  |  |  |  | 
| 494 |  |  |  |  |  |  | sub unary() { | 
| 495 | 61769 |  |  | 61769 | 0 | 72013 | my($pos,@ret) = pos; | 
| 496 | 61769 |  |  |  |  | 533589 | push @ret, $1 while /\G $s ( | 
| 497 |  |  |  |  |  |  | (?: delete | void | typeof )(?!$id_cont) | 
| 498 |  |  |  |  |  |  | | | 
| 499 |  |  |  |  |  |  | \+\+? | --? | ~ | ! | 
| 500 |  |  |  |  |  |  | ) $s /cgx; | 
| 501 | 61769 | 100 |  |  |  | 139996 | @ret != push @ret, &postfix or ( | 
|  |  | 100 |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | @ret | 
| 503 |  |  |  |  |  |  | ? expected "expression" | 
| 504 |  |  |  |  |  |  | : return | 
| 505 |  |  |  |  |  |  | ); | 
| 506 | 58507 | 100 |  |  |  | 208213 | @ret == 1 ? @ret : bless [[$pos, pos], 'prefix', @ret], | 
| 507 |  |  |  |  |  |  | JECE; | 
| 508 |  |  |  |  |  |  | } | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | sub multi() { | 
| 511 | 61549 |  |  | 61549 | 0 | 71527 | my($pos,@ret) = pos; | 
| 512 | 61549 | 100 |  |  |  | 86886 | @ret != push @ret, &unary or return; | 
| 513 | 58287 |  |  |  |  | 364953 | while(m-\G $s ( [*%](?!=) | / (?![*/=]) ) $s -cgx) { | 
| 514 | 220 |  |  |  |  | 811 | push @ret, $1; | 
| 515 | 220 | 50 |  |  |  | 361 | @ret == push @ret, &unary and expected 'expression'; | 
| 516 |  |  |  |  |  |  | } | 
| 517 | 58287 | 100 |  |  |  | 224534 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 518 |  |  |  |  |  |  | JECE; | 
| 519 |  |  |  |  |  |  | } | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | sub add() { | 
| 522 | 60271 |  |  | 60271 | 0 | 70430 | my($pos,@ret) = pos; | 
| 523 | 60271 | 100 |  |  |  | 83382 | @ret != push @ret, &multi or return; | 
| 524 | 57009 |  |  |  |  | 305741 | while(/\G $s ( \+(?![+=]) | -(?![-=]) ) $s /cgx) { | 
| 525 | 1278 |  |  |  |  | 4712 | push @ret, $1; | 
| 526 | 1278 | 50 |  |  |  | 2203 | @ret == push @ret, &multi and expected 'expression' | 
| 527 |  |  |  |  |  |  | } | 
| 528 | 57009 | 100 |  |  |  | 209897 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 529 |  |  |  |  |  |  | JECE; | 
| 530 |  |  |  |  |  |  | } | 
| 531 |  |  |  |  |  |  |  | 
| 532 |  |  |  |  |  |  | sub bitshift() { | 
| 533 | 60115 |  |  | 60115 | 0 | 68824 | my($pos,@ret) = pos; | 
| 534 | 60115 | 100 |  |  |  | 84283 | @ret == push @ret, &add and return; | 
| 535 | 56853 |  |  |  |  | 296570 | while(/\G $s (>>> | >>(?!>) | <<)(?!=) $s /cgx) { | 
| 536 | 156 |  |  |  |  | 984 | push @ret, $1; | 
| 537 | 156 | 50 |  |  |  | 278 | @ret == push @ret, &add and expected 'expression'; | 
| 538 |  |  |  |  |  |  | } | 
| 539 | 56853 | 100 |  |  |  | 214716 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 540 |  |  |  |  |  |  | JECE; | 
| 541 |  |  |  |  |  |  | } | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | sub rel() { | 
| 544 | 58581 |  |  | 58581 | 0 | 70689 | my($pos,@ret) = pos; | 
| 545 | 58581 | 100 |  |  |  | 83967 | @ret == push @ret, &bitshift and return; | 
| 546 | 55332 |  |  |  |  | 332686 | while(/\G $s ( ([<>])(?!\2|=) | [<>]= | | 
| 547 |  |  |  |  |  |  | in(?:stanceof)?(?!$id_cont) ) $s /cgx) { | 
| 548 | 957 |  |  |  |  | 3481 | push @ret, $1; | 
| 549 | 957 | 50 |  |  |  | 1855 | @ret== push @ret, &bitshift and expected 'expression'; | 
| 550 |  |  |  |  |  |  | } | 
| 551 | 55332 | 100 |  |  |  | 228735 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 552 |  |  |  |  |  |  | JECE; | 
| 553 |  |  |  |  |  |  | } | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | sub rel_noin() { | 
| 556 | 565 |  |  | 565 | 0 | 853 | my($pos,@ret) = pos; | 
| 557 | 565 | 100 |  |  |  | 915 | @ret == push @ret, &bitshift and return; | 
| 558 | 552 |  |  |  |  | 4564 | while(/\G $s ( ([<>])(?!\2|=) | [<>]= | instanceof(?!$id_cont) ) | 
| 559 |  |  |  |  |  |  | $s /cgx) { | 
| 560 | 12 |  |  |  |  | 587 | push @ret, $1; | 
| 561 | 12 | 50 |  |  |  | 26 | @ret == push @ret, &bitshift and expected 'expression'; | 
| 562 |  |  |  |  |  |  | } | 
| 563 | 552 | 100 |  |  |  | 11357 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 564 |  |  |  |  |  |  | JECE; | 
| 565 |  |  |  |  |  |  | } | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | sub equal() { | 
| 568 | 55814 |  |  | 55814 | 0 | 65532 | my($pos,@ret) = pos; | 
| 569 | 55814 | 100 |  |  |  | 80981 | @ret == push @ret, &rel and return; | 
| 570 | 52565 |  |  |  |  | 619861 | while(/\G $s ([!=]==?) $s /cgx) { | 
| 571 | 2767 |  |  |  |  | 8658 | push @ret, $1; | 
| 572 | 2767 | 50 |  |  |  | 4808 | @ret == push @ret, &rel and expected 'expression'; | 
| 573 |  |  |  |  |  |  | } | 
| 574 | 52565 | 100 |  |  |  | 208298 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 575 |  |  |  |  |  |  | JECE; | 
| 576 |  |  |  |  |  |  | } | 
| 577 |  |  |  |  |  |  |  | 
| 578 |  |  |  |  |  |  | sub equal_noin() { | 
| 579 | 555 |  |  | 555 | 0 | 833 | my($pos,@ret) = pos; | 
| 580 | 555 | 100 |  |  |  | 1030 | @ret == push @ret, &rel_noin and return; | 
| 581 | 542 |  |  |  |  | 4157 | while(/\G $s ([!=]==?) $s /cgx) { | 
| 582 | 10 |  |  |  |  | 16 | push @ret, $1; | 
| 583 | 10 | 50 |  |  |  | 16 | @ret == push @ret, &rel_noin and expected 'expression'; | 
| 584 |  |  |  |  |  |  | } | 
| 585 | 542 | 100 |  |  |  | 9482 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 586 |  |  |  |  |  |  | JECE; | 
| 587 |  |  |  |  |  |  | } | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | sub bit_and() { | 
| 590 | 55762 |  |  | 55762 | 0 | 63884 | my($pos,@ret) = pos; | 
| 591 | 55762 | 100 |  |  |  | 78273 | @ret == push @ret, &equal and return; | 
| 592 | 52513 |  |  |  |  | 1257807 | while(/\G $s &(?![&=]) $s /cgx) { | 
| 593 | 52 | 50 |  |  |  | 779 | @ret == push @ret, '&', &equal and expected 'expression'; | 
| 594 |  |  |  |  |  |  | } | 
| 595 | 52513 | 100 |  |  |  | 203692 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 596 |  |  |  |  |  |  | JECE; | 
| 597 |  |  |  |  |  |  | } | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | sub bit_and_noin() { | 
| 600 | 553 |  |  | 553 | 0 | 770 | my($pos,@ret) = pos; | 
| 601 | 553 | 100 |  |  |  | 1018 | @ret == push @ret, &equal_noin and return; | 
| 602 | 540 |  |  |  |  | 9447 | while(/\G $s &(?![&=]) $s /cgx) { | 
| 603 | 2 | 50 |  |  |  | 4 | @ret == push @ret, '&', &equal_noin | 
| 604 |  |  |  |  |  |  | and expected 'expression'; | 
| 605 |  |  |  |  |  |  | } | 
| 606 | 540 | 100 |  |  |  | 9053 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 607 |  |  |  |  |  |  | JECE; | 
| 608 |  |  |  |  |  |  | } | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | sub bit_or() { | 
| 611 | 55709 |  |  | 55709 | 0 | 64358 | my($pos,@ret) = pos; | 
| 612 | 55709 | 100 |  |  |  | 77033 | @ret == push @ret, &bit_and and return; | 
| 613 | 52460 |  |  |  |  | 1247559 | while(/\G $s \|(?![|=]) $s /cgx) { | 
| 614 | 53 | 50 |  |  |  | 541 | @ret == push @ret, '|', &bit_and and expected 'expression'; | 
| 615 |  |  |  |  |  |  | } | 
| 616 | 52460 | 100 |  |  |  | 203536 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 617 |  |  |  |  |  |  | JECE; | 
| 618 |  |  |  |  |  |  | } | 
| 619 |  |  |  |  |  |  |  | 
| 620 |  |  |  |  |  |  | sub bit_or_noin() { | 
| 621 | 551 |  |  | 551 | 0 | 856 | my($pos,@ret) = pos; | 
| 622 | 551 | 100 |  |  |  | 1235 | @ret == push @ret, &bit_and_noin and return; | 
| 623 | 538 |  |  |  |  | 9560 | while(/\G $s \|(?![|=]) $s /cgx) { | 
| 624 | 2 | 50 |  |  |  | 8 | @ret == push @ret, '|', &bit_and_noin | 
| 625 |  |  |  |  |  |  | and expected 'expression'; | 
| 626 |  |  |  |  |  |  | } | 
| 627 | 538 | 100 |  |  |  | 9536 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 628 |  |  |  |  |  |  | JECE; | 
| 629 |  |  |  |  |  |  | } | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | sub bit_xor() { | 
| 632 | 55657 |  |  | 55657 | 0 | 63649 | my($pos,@ret) = pos; | 
| 633 | 55657 | 100 |  |  |  | 80194 | @ret == push @ret, &bit_or and return; | 
| 634 | 52408 |  |  |  |  | 1175297 | while(/\G $s \^(?!=) $s /cgx) { | 
| 635 | 52 | 50 |  |  |  | 400 | @ret == push @ret, '^', &bit_or and expected 'expression'; | 
| 636 |  |  |  |  |  |  | } | 
| 637 | 52408 | 100 |  |  |  | 214011 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 638 |  |  |  |  |  |  | JECE; | 
| 639 |  |  |  |  |  |  | } | 
| 640 |  |  |  |  |  |  |  | 
| 641 |  |  |  |  |  |  | sub bit_xor_noin() { | 
| 642 | 549 |  |  | 549 | 0 | 780 | my($pos,@ret) = pos; | 
| 643 | 549 | 100 |  |  |  | 1067 | @ret == push @ret, &bit_or_noin and return; | 
| 644 | 536 |  |  |  |  | 9527 | while(/\G $s \^(?!=) $s /cgx) { | 
| 645 | 2 | 50 |  |  |  | 5 | @ret == push @ret, '^', &bit_or_noin | 
| 646 |  |  |  |  |  |  | and expected 'expression'; | 
| 647 |  |  |  |  |  |  | } | 
| 648 | 536 | 100 |  |  |  | 9428 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 649 |  |  |  |  |  |  | JECE; | 
| 650 |  |  |  |  |  |  | } | 
| 651 |  |  |  |  |  |  |  | 
| 652 |  |  |  |  |  |  | sub and_expr() { # If I just call it 'and', then I have to write | 
| 653 |  |  |  |  |  |  | # CORE::and for the operator! (Far too cumbersome.) | 
| 654 | 55180 |  |  | 55180 | 0 | 64983 | my($pos,@ret) = pos; | 
| 655 | 55180 | 100 |  |  |  | 81937 | @ret == push @ret, &bit_xor and return; | 
| 656 | 51931 |  |  |  |  | 884036 | while(/\G $s && $s /cgx) { | 
| 657 | 477 | 50 |  |  |  | 1634 | @ret == push @ret, '&&', &bit_xor | 
| 658 |  |  |  |  |  |  | and expected 'expression'; | 
| 659 |  |  |  |  |  |  | } | 
| 660 | 51931 | 100 |  |  |  | 201793 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 661 |  |  |  |  |  |  | JECE; | 
| 662 |  |  |  |  |  |  | } | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | sub and_noin() { | 
| 665 | 547 |  |  | 547 | 0 | 834 | my($pos,@ret) = pos; | 
| 666 | 547 | 100 |  |  |  | 907 | @ret == push @ret, &bit_xor_noin and return; | 
| 667 | 534 |  |  |  |  | 6340 | while(/\G $s && $s /cgx) { | 
| 668 | 2 | 50 |  |  |  | 4 | @ret == push @ret, '&&', &bit_xor_noin | 
| 669 |  |  |  |  |  |  | and expected 'expression'; | 
| 670 |  |  |  |  |  |  | } | 
| 671 | 534 | 100 |  |  |  | 9342 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 672 |  |  |  |  |  |  | JECE; | 
| 673 |  |  |  |  |  |  | } | 
| 674 |  |  |  |  |  |  |  | 
| 675 |  |  |  |  |  |  | sub or_expr() { | 
| 676 | 55100 |  |  | 55100 | 0 | 68212 | my($pos,@ret) = pos; | 
| 677 | 55100 | 100 |  |  |  | 77481 | @ret == push @ret, &and_expr and return; | 
| 678 | 51851 |  |  |  |  | 859495 | while(/\G $s \|\| $s /cgx) { | 
| 679 | 80 | 50 |  |  |  | 176 | @ret == push @ret, '||', &and_expr | 
| 680 |  |  |  |  |  |  | and expected 'expression'; | 
| 681 |  |  |  |  |  |  | } | 
| 682 | 51851 | 100 |  |  |  | 210603 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 683 |  |  |  |  |  |  | JECE; | 
| 684 |  |  |  |  |  |  | } | 
| 685 |  |  |  |  |  |  |  | 
| 686 |  |  |  |  |  |  | sub or_noin() { | 
| 687 | 545 |  |  | 545 | 0 | 1107 | my($pos,@ret) = pos; | 
| 688 | 545 | 100 |  |  |  | 1000 | @ret == push @ret, &and_noin and return; | 
| 689 | 532 |  |  |  |  | 6181 | while(/\G $s \|\| $s /cgx) { | 
| 690 | 2 | 50 |  |  |  | 5 | @ret == push @ret, '||', &and_noin | 
| 691 |  |  |  |  |  |  | and expected 'expression'; | 
| 692 |  |  |  |  |  |  | } | 
| 693 | 532 | 100 |  |  |  | 10788 | @ret == 1 ? @ret : bless [[$pos, pos], 'lassoc', @ret], | 
| 694 |  |  |  |  |  |  | JECE; | 
| 695 |  |  |  |  |  |  | } | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | sub assign() { | 
| 698 | 53482 |  |  | 53482 | 0 | 119218 | my($pos,@ret) = pos; | 
| 699 | 53482 | 100 |  |  |  | 79249 | @ret == push @ret, &or_expr and return; | 
| 700 | 50234 |  |  |  |  | 652209 | while(m@\G $s ((?>(?: [-*/%+&^|] | << | >>>? )?)=) $s @cgx) { | 
| 701 | 1618 |  |  |  |  | 11459 | push @ret, $1; | 
| 702 | 1618 | 50 |  |  |  | 3161 | @ret == push @ret, &or_expr and expected 'expression'; | 
| 703 |  |  |  |  |  |  | } | 
| 704 | 50233 | 100 |  |  |  | 1386090 | if(/\G$s\?$s/cg) { | 
| 705 | 48 | 50 |  |  |  | 127 | @ret == push @ret, &assign and expected 'expression'; | 
| 706 | 48 |  |  |  |  | 111 | &skip; | 
| 707 | 48 | 50 |  |  |  | 790 | /\G:$s/cg or expected "colon"; | 
| 708 | 48 | 50 |  |  |  | 1678 | @ret == push @ret, &assign and expected 'expression'; | 
| 709 |  |  |  |  |  |  | } | 
| 710 | 50233 | 100 |  |  |  | 311579 | @ret == 1 ? @ret : bless [[$pos, pos], 'assign', @ret], | 
| 711 |  |  |  |  |  |  | JECE; | 
| 712 |  |  |  |  |  |  | } | 
| 713 |  |  |  |  |  |  |  | 
| 714 |  |  |  |  |  |  | sub assign_noin() { | 
| 715 | 321 |  |  | 321 | 0 | 2962 | my($pos,@ret) = pos; | 
| 716 | 321 | 100 |  |  |  | 726 | @ret == push @ret, &or_noin and return; | 
| 717 | 308 |  |  |  |  | 3245 | while(m~\G $s ((?>(?: [-*/%+&^|] | << | >>>? )?)=) $s ~cgx) { | 
| 718 | 224 |  |  |  |  | 3974 | push @ret, $1; | 
| 719 | 224 | 50 |  |  |  | 404 | @ret == push @ret, &or_noin and expected 'expression'; | 
| 720 |  |  |  |  |  |  | } | 
| 721 | 308 | 100 |  |  |  | 6853 | if(/\G$s\?$s/cg) { | 
| 722 | 6 | 50 |  |  |  | 14 | @ret == push @ret, &assign and expected 'expression'; | 
| 723 | 6 |  |  |  |  | 10 | &skip; | 
| 724 | 6 | 50 |  |  |  | 61 | /\G:$s/cg or expected "colon"; | 
| 725 | 6 | 50 |  |  |  | 237 | @ret == push @ret, &assign_noin and expected 'expression'; | 
| 726 |  |  |  |  |  |  | } | 
| 727 | 308 | 100 |  |  |  | 9836 | @ret == 1 ? @ret : bless [[$pos, pos], 'assign', @ret], | 
| 728 |  |  |  |  |  |  | JECE; | 
| 729 |  |  |  |  |  |  | } | 
| 730 |  |  |  |  |  |  |  | 
| 731 |  |  |  |  |  |  | sub expr() { # public | 
| 732 | 11988 |  |  | 11988 | 0 | 47907 | my $ret = bless [[pos], 'expr'], JECE; | 
| 733 | 11988 | 100 |  |  |  | 23417 | @$ret == push @$ret, &assign and return; | 
| 734 | 10292 |  |  |  |  | 63002 | while(/\G$s,$s/cg) { | 
| 735 | 304 | 50 |  |  |  | 1490 | @$ret == push @$ret,& assign and expected 'expression'; | 
| 736 |  |  |  |  |  |  | } | 
| 737 | 10292 |  |  |  |  | 39552 | push @{$$ret[0]},pos; | 
|  | 10292 |  |  |  |  | 25099 |  | 
| 738 | 10292 |  |  |  |  | 32790 | $ret; | 
| 739 |  |  |  |  |  |  | } | 
| 740 |  |  |  |  |  |  |  | 
| 741 |  |  |  |  |  |  | sub expr_noin() { # public | 
| 742 | 237 |  |  | 237 | 0 | 5089 | my $ret = bless [[pos], 'expr'], JECE; | 
| 743 | 237 | 100 |  |  |  | 639 | @$ret == push @$ret, &assign_noin and return; | 
| 744 | 224 |  |  |  |  | 2252 | while(/\G$s,$s/cg) { | 
| 745 | 22 | 50 |  |  |  | 42 | @$ret == push @$ret, &assign_noin | 
| 746 |  |  |  |  |  |  | and expected 'expression'; | 
| 747 |  |  |  |  |  |  | } | 
| 748 | 224 |  |  |  |  | 6764 | push @{$$ret[0]},pos; | 
|  | 224 |  |  |  |  | 590 |  | 
| 749 | 224 |  |  |  |  | 788 | $ret; | 
| 750 |  |  |  |  |  |  | } | 
| 751 |  |  |  |  |  |  |  | 
| 752 |  |  |  |  |  |  | sub vardecl() { # vardecl is only called when we *know* we need it, so it | 
| 753 |  |  |  |  |  |  | # will die when it can't get the first identifier, instead | 
| 754 |  |  |  |  |  |  | # of returning undef | 
| 755 | 385 |  |  | 385 | 0 | 518 | my @ret; | 
| 756 | 385 | 50 |  |  |  | 841 | @ret == push @ret, &ident and expected 'identifier'; | 
| 757 | 385 | 100 | 33 |  |  | 5154 | /\G$s=$s/cg and | 
| 758 |  |  |  |  |  |  | (@ret != push @ret, &assign or expected 'expression'); | 
| 759 | 385 |  |  |  |  | 4084 | push @$_vars, $ret[0]; | 
| 760 | 385 |  |  |  |  | 4781 | \@ret; | 
| 761 |  |  |  |  |  |  | } | 
| 762 |  |  |  |  |  |  |  | 
| 763 |  |  |  |  |  |  | sub vardecl_noin() { | 
| 764 | 118 |  |  | 118 | 0 | 145 | my @ret; | 
| 765 | 118 | 50 |  |  |  | 297 | @ret == push @ret, &ident and expected 'identifier'; | 
| 766 | 118 | 100 | 33 |  |  | 1538 | /\G$s=$s/cg and | 
| 767 |  |  |  |  |  |  | (@ret != push @ret, &assign_noin or expected 'expression'); | 
| 768 | 118 |  |  |  |  | 3224 | push @$_vars, $ret[0]; | 
| 769 | 118 |  |  |  |  | 366 | \@ret; | 
| 770 |  |  |  |  |  |  | } | 
| 771 |  |  |  |  |  |  |  | 
| 772 |  |  |  |  |  |  | sub finish_for_sc_sc() {  # returns the last two expressions of a for (;;) | 
| 773 |  |  |  |  |  |  | # loop header | 
| 774 | 301 |  |  | 301 | 0 | 593 | my @ret; | 
| 775 |  |  |  |  |  |  | my $msg; | 
| 776 | 301 | 100 |  |  |  | 662 | if(@ret != push @ret, expr) { | 
| 777 | 260 |  |  |  |  | 403 | $msg = ''; | 
| 778 | 260 |  |  |  |  | 537 | &skip | 
| 779 |  |  |  |  |  |  | } else { | 
| 780 | 41 |  |  |  |  | 81 | push @ret, 'empty'; | 
| 781 | 41 |  |  |  |  | 69 | $msg = 'expression or ' | 
| 782 |  |  |  |  |  |  | } | 
| 783 | 301 | 50 |  |  |  | 2172 | /\G;$s/cg or expected "${msg}semicolon"; | 
| 784 | 301 | 100 |  |  |  | 3918 | if(@ret != push @ret, expr) { | 
| 785 | 194 |  |  |  |  | 338 | $msg = ''; | 
| 786 | 194 |  |  |  |  | 531 | &skip | 
| 787 |  |  |  |  |  |  | } else { | 
| 788 | 107 |  |  |  |  | 183 | push @ret, 'empty'; | 
| 789 | 107 |  |  |  |  | 163 | $msg = 'expression or ' | 
| 790 |  |  |  |  |  |  | } | 
| 791 | 301 | 50 |  |  |  | 2326 | /\G\)$s/cg or expected "${msg}')'"; | 
| 792 |  |  |  |  |  |  |  | 
| 793 | 301 |  |  |  |  | 4328 | @ret; | 
| 794 |  |  |  |  |  |  | } | 
| 795 |  |  |  |  |  |  |  | 
| 796 |  |  |  |  |  |  | # ----------- Statement types ------------ # | 
| 797 |  |  |  |  |  |  | #        (used by custom parsers) | 
| 798 |  |  |  |  |  |  |  | 
| 799 |  |  |  |  |  |  | our $optional_sc = # public | 
| 800 |  |  |  |  |  |  | qr-\G (?: | 
| 801 |  |  |  |  |  |  | $s (?: \z | ; $s | (?=\}) ) | 
| 802 |  |  |  |  |  |  | | | 
| 803 |  |  |  |  |  |  |  | 
| 804 |  |  |  |  |  |  | # optional horizontal whitespace | 
| 805 |  |  |  |  |  |  | # then a line terminator or a comment containing one | 
| 806 |  |  |  |  |  |  | # then optional trailing whitespace | 
| 807 |  |  |  |  |  |  | $h | 
| 808 |  |  |  |  |  |  | (?: $n | //[^\cm\cj\x{2028}\x{2029}]* $n | | 
| 809 |  |  |  |  |  |  | /\* [^*\cm\cj\x{2028}\x{2029}]* | 
| 810 |  |  |  |  |  |  | (?: \*(?!/) [^*\cm\cj\x{2028}\x{2029}] )* | 
| 811 |  |  |  |  |  |  | $n | 
| 812 |  |  |  |  |  |  | (?s:.)*? | 
| 813 |  |  |  |  |  |  | \*/ | 
| 814 |  |  |  |  |  |  | ) | 
| 815 |  |  |  |  |  |  | $s | 
| 816 |  |  |  |  |  |  | )-x; | 
| 817 |  |  |  |  |  |  |  | 
| 818 |  |  |  |  |  |  | sub optional_sc() { | 
| 819 | 9 | 100 |  | 9 | 0 | 84 | /$optional_sc/gc or expected "semicolon, '}' or end of line"; | 
| 820 |  |  |  |  |  |  | } | 
| 821 |  |  |  |  |  |  |  | 
| 822 |  |  |  |  |  |  | sub block() { | 
| 823 | 16 | 50 |  | 16 | 0 | 102 | /\G\{/gc or return; | 
| 824 | 0 |  |  |  |  | 0 | my $ret = [[pos()-1], 'statements']; | 
| 825 | 0 |  |  |  |  | 0 | &skip; | 
| 826 | 0 |  |  |  |  | 0 | while() { # 'last' does not work when 'while' is a | 
| 827 |  |  |  |  |  |  | # statement modifier | 
| 828 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &statement and last; | 
| 829 |  |  |  |  |  |  | } | 
| 830 | 0 | 0 |  |  |  | 0 | expected "'}'" unless /\G\}$s/gc; | 
| 831 |  |  |  |  |  |  |  | 
| 832 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 833 |  |  |  |  |  |  |  | 
| 834 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 835 |  |  |  |  |  |  | } | 
| 836 |  |  |  |  |  |  |  | 
| 837 |  |  |  |  |  |  | sub empty() { | 
| 838 | 16 |  |  | 16 | 0 | 28 | my $pos = pos; | 
| 839 | 16 | 50 |  |  |  | 142 | /\G;$s/cg or return; | 
| 840 | 0 |  |  |  |  | 0 | bless [[$pos,pos], 'empty'], JECS; | 
| 841 |  |  |  |  |  |  | } | 
| 842 |  |  |  |  |  |  |  | 
| 843 |  |  |  |  |  |  | sub function() { | 
| 844 | 7070 |  |  | 7070 | 0 | 10845 | my $pos = pos; | 
| 845 | 7070 | 100 |  |  |  | 47781 | /\Gfunction$S/cg or return; | 
| 846 | 132 |  |  |  |  | 6595 | my $ret = [[$pos], 'function']; | 
| 847 | 132 | 50 |  |  |  | 429 | @$ret == push @$ret, &ident | 
| 848 |  |  |  |  |  |  | and expected "identifier"; | 
| 849 | 132 |  |  |  |  | 324 | &skip; | 
| 850 | 132 |  |  |  |  | 5395 | push @$ret, ¶ms; | 
| 851 | 132 |  |  |  |  | 270 | &skip; | 
| 852 | 132 | 50 |  |  |  | 481 | /\G \{ /gcx or expected "'{'"; | 
| 853 |  |  |  |  |  |  | { | 
| 854 | 132 |  |  |  |  | 169 | local $_vars = []; | 
|  | 132 |  |  |  |  | 241 |  | 
| 855 | 132 |  |  |  |  | 319 | push @$ret, &statements, $_vars; | 
| 856 |  |  |  |  |  |  | } | 
| 857 | 132 | 50 |  |  |  | 1910 | /\G \}$s /gcx or expected "'}'"; | 
| 858 |  |  |  |  |  |  |  | 
| 859 | 132 |  |  |  |  | 7352 | push @{$$ret[0]},pos; | 
|  | 132 |  |  |  |  | 380 |  | 
| 860 |  |  |  |  |  |  |  | 
| 861 | 132 |  |  |  |  | 291 | push @$_vars, $ret; | 
| 862 |  |  |  |  |  |  |  | 
| 863 | 132 |  |  |  |  | 849 | bless $ret, JECS; | 
| 864 |  |  |  |  |  |  | } | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | sub if() { | 
| 867 | 16 |  |  | 16 | 0 | 26 | my $pos = pos; | 
| 868 | 16 | 50 |  |  |  | 128 | /\Gif$s\($s/cg or return; | 
| 869 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'if']; | 
| 870 |  |  |  |  |  |  |  | 
| 871 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 872 |  |  |  |  |  |  | and expected 'expression'; | 
| 873 | 0 |  |  |  |  | 0 | &skip; | 
| 874 | 0 | 0 |  |  |  | 0 | /\G\)$s/gc or expected "')'"; | 
| 875 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &statement | 
| 876 |  |  |  |  |  |  | or expected 'statement'; | 
| 877 | 0 | 0 |  |  |  | 0 | if (/\Gelse(?!$id_cont)$s/cg) { | 
| 878 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &statement | 
| 879 |  |  |  |  |  |  | and expected 'statement'; | 
| 880 |  |  |  |  |  |  | } | 
| 881 |  |  |  |  |  |  |  | 
| 882 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 883 |  |  |  |  |  |  |  | 
| 884 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 885 |  |  |  |  |  |  | } | 
| 886 |  |  |  |  |  |  |  | 
| 887 |  |  |  |  |  |  | sub while() { | 
| 888 | 0 |  |  | 0 | 0 | 0 | my $pos = pos; | 
| 889 | 0 | 0 |  |  |  | 0 | /\Gwhile$s\($s/cg or return; | 
| 890 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'while']; | 
| 891 |  |  |  |  |  |  |  | 
| 892 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 893 |  |  |  |  |  |  | and expected 'expression'; | 
| 894 | 0 |  |  |  |  | 0 | &skip; | 
| 895 | 0 | 0 |  |  |  | 0 | /\G\)$s/gc or expected "')'"; | 
| 896 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &statement | 
| 897 |  |  |  |  |  |  | or expected 'statement'; | 
| 898 |  |  |  |  |  |  |  | 
| 899 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 900 |  |  |  |  |  |  |  | 
| 901 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 902 |  |  |  |  |  |  | } | 
| 903 |  |  |  |  |  |  |  | 
| 904 |  |  |  |  |  |  | sub for() { | 
| 905 | 0 |  |  | 0 | 1 | 0 | my $pos = pos; | 
| 906 | 0 | 0 |  |  |  | 0 | /\Gfor$s\($s/cg or return; | 
| 907 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'for']; | 
| 908 |  |  |  |  |  |  |  | 
| 909 | 0 | 0 |  |  |  | 0 | if (/\G var$S/cgx) { | 
|  |  | 0 |  |  |  |  |  | 
| 910 | 0 |  |  |  |  | 0 | push @$ret, my $var = bless | 
| 911 |  |  |  |  |  |  | [[pos() - length $1], 'var'], | 
| 912 |  |  |  |  |  |  | 'JE::Code::Statement'; | 
| 913 |  |  |  |  |  |  |  | 
| 914 | 0 |  |  |  |  | 0 | push @$var, &vardecl_noin; | 
| 915 | 0 |  |  |  |  | 0 | &skip; | 
| 916 | 0 | 0 |  |  |  | 0 | if (/\G([;,])$s/gc) { | 
| 917 |  |  |  |  |  |  | # if there's a comma or sc then | 
| 918 |  |  |  |  |  |  | # this is a for(;;) loop | 
| 919 | 0 | 0 |  |  |  | 0 | if ($1 eq ',') { | 
| 920 |  |  |  |  |  |  | # finish getting the var | 
| 921 |  |  |  |  |  |  | # decl list | 
| 922 | 0 |  |  |  |  | 0 | do{ | 
| 923 | 0 | 0 |  |  |  | 0 | @$var == | 
| 924 |  |  |  |  |  |  | push @$var, &vardecl | 
| 925 |  |  |  |  |  |  | and expected | 
| 926 |  |  |  |  |  |  | 'identifier' | 
| 927 |  |  |  |  |  |  | } while (/\G$s,$s/gc); | 
| 928 | 0 |  |  |  |  | 0 | &skip; | 
| 929 | 0 | 0 |  |  |  | 0 | /\G;$s/cg | 
| 930 |  |  |  |  |  |  | or expected 'semicolon'; | 
| 931 |  |  |  |  |  |  | } | 
| 932 | 0 |  |  |  |  | 0 | push @$ret, &finish_for_sc_sc; | 
| 933 |  |  |  |  |  |  | } | 
| 934 |  |  |  |  |  |  | else { | 
| 935 | 0 | 0 |  |  |  | 0 | /\Gin$s/cg or expected | 
| 936 |  |  |  |  |  |  | "'in', comma or semicolon"; | 
| 937 | 0 |  |  |  |  | 0 | push @$ret, 'in'; | 
| 938 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 939 |  |  |  |  |  |  | and expected 'expresssion'; | 
| 940 | 0 |  |  |  |  | 0 | &skip; | 
| 941 | 0 | 0 |  |  |  | 0 | /\G\)$s/cg or expected "')'"; | 
| 942 |  |  |  |  |  |  | } | 
| 943 |  |  |  |  |  |  | } | 
| 944 |  |  |  |  |  |  | elsif(@$ret != push @$ret, &expr_noin) { | 
| 945 | 0 |  |  |  |  | 0 | &skip; | 
| 946 | 0 | 0 |  |  |  | 0 | if (/\G;$s/gc) { | 
| 947 |  |  |  |  |  |  | # if there's a semicolon then | 
| 948 |  |  |  |  |  |  | # this is a for(;;) loop | 
| 949 | 0 |  |  |  |  | 0 | push @$ret, &finish_for_sc_sc; | 
| 950 |  |  |  |  |  |  | } | 
| 951 |  |  |  |  |  |  | else { | 
| 952 | 0 | 0 |  |  |  | 0 | /\Gin$s/cg or expected | 
| 953 |  |  |  |  |  |  | "'in' or semicolon"; | 
| 954 | 0 |  |  |  |  | 0 | push @$ret, 'in'; | 
| 955 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 956 |  |  |  |  |  |  | and expected 'expresssion'; | 
| 957 | 0 |  |  |  |  | 0 | &skip; | 
| 958 | 0 | 0 |  |  |  | 0 | /\G\)$s/cg or expected "')'"; | 
| 959 |  |  |  |  |  |  | } | 
| 960 |  |  |  |  |  |  | } | 
| 961 |  |  |  |  |  |  | else { | 
| 962 | 0 |  |  |  |  | 0 | push @$ret, 'empty'; | 
| 963 | 0 | 0 |  |  |  | 0 | /\G;$s/cg | 
| 964 |  |  |  |  |  |  | or expected 'expression or semicolon'; | 
| 965 | 0 |  |  |  |  | 0 | push @$ret, &finish_for_sc_sc; | 
| 966 |  |  |  |  |  |  | } | 
| 967 |  |  |  |  |  |  |  | 
| 968 |  |  |  |  |  |  | # body of the for loop | 
| 969 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &statement | 
| 970 |  |  |  |  |  |  | or expected 'statement'; | 
| 971 |  |  |  |  |  |  |  | 
| 972 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 973 |  |  |  |  |  |  |  | 
| 974 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 975 |  |  |  |  |  |  | } | 
| 976 |  |  |  |  |  |  |  | 
| 977 |  |  |  |  |  |  | sub with() { # almost identical to while | 
| 978 | 16 |  |  | 16 | 0 | 27 | my $pos = pos; | 
| 979 | 16 | 50 |  |  |  | 125 | /\Gwith$s\($s/cg or return; | 
| 980 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'with']; | 
| 981 |  |  |  |  |  |  |  | 
| 982 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 983 |  |  |  |  |  |  | and expected 'expression'; | 
| 984 | 0 |  |  |  |  | 0 | &skip; | 
| 985 | 0 | 0 |  |  |  | 0 | /\G\)$s/gc or expected "')'"; | 
| 986 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &statement | 
| 987 |  |  |  |  |  |  | or expected 'statement'; | 
| 988 |  |  |  |  |  |  |  | 
| 989 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 990 |  |  |  |  |  |  |  | 
| 991 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 992 |  |  |  |  |  |  | } | 
| 993 |  |  |  |  |  |  |  | 
| 994 |  |  |  |  |  |  | sub switch() { | 
| 995 | 16 |  |  | 16 | 0 | 26 | my $pos = pos; | 
| 996 | 16 | 50 |  |  |  | 130 | /\Gswitch$s\($s/cg or return; | 
| 997 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'switch']; | 
| 998 |  |  |  |  |  |  |  | 
| 999 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 1000 |  |  |  |  |  |  | and expected 'expression'; | 
| 1001 | 0 |  |  |  |  | 0 | &skip; | 
| 1002 | 0 | 0 |  |  |  | 0 | /\G\)$s/gc or expected "')'"; | 
| 1003 | 0 | 0 |  |  |  | 0 | /\G\{$s/gc or expected "'{'"; | 
| 1004 |  |  |  |  |  |  |  | 
| 1005 | 0 |  |  |  |  | 0 | while (/\G case(?!$id_cont) $s/cgx) { | 
| 1006 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 1007 |  |  |  |  |  |  | and expected 'expression'; | 
| 1008 | 0 |  |  |  |  | 0 | &skip; | 
| 1009 | 0 | 0 |  |  |  | 0 | /\G:$s/cg or expected 'colon'; | 
| 1010 | 0 |  |  |  |  | 0 | push @$ret, &statements; | 
| 1011 |  |  |  |  |  |  | } | 
| 1012 | 0 |  |  |  |  | 0 | my $default=0; | 
| 1013 | 0 | 0 |  |  |  | 0 | if (/\G default(?!$id_cont) $s/cgx) { | 
| 1014 | 0 | 0 |  |  |  | 0 | /\G : $s /cgx or expected 'colon'; | 
| 1015 | 0 |  |  |  |  | 0 | push @$ret, default => &statements; | 
| 1016 | 0 |  |  |  |  | 0 | ++$default; | 
| 1017 |  |  |  |  |  |  | } | 
| 1018 | 0 |  |  |  |  | 0 | while (/\G case(?!$id_cont) $s/cgx) { | 
| 1019 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr | 
| 1020 |  |  |  |  |  |  | and expected 'expression'; | 
| 1021 | 0 |  |  |  |  | 0 | &skip; | 
| 1022 | 0 | 0 |  |  |  | 0 | /\G:$s/cg or expected 'colon'; | 
| 1023 | 0 |  |  |  |  | 0 | push @$ret, &statements; | 
| 1024 |  |  |  |  |  |  | } | 
| 1025 | 0 | 0 |  |  |  | 0 | /\G \} $s /cgx or expected ( | 
|  |  | 0 |  |  |  |  |  | 
| 1026 |  |  |  |  |  |  | $default | 
| 1027 |  |  |  |  |  |  | ? "'}' or 'case'" | 
| 1028 |  |  |  |  |  |  | : "'}', 'case' or 'default'" | 
| 1029 |  |  |  |  |  |  | ); | 
| 1030 |  |  |  |  |  |  |  | 
| 1031 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1034 |  |  |  |  |  |  | } | 
| 1035 |  |  |  |  |  |  |  | 
| 1036 |  |  |  |  |  |  | sub try() { | 
| 1037 | 16 |  |  | 16 | 0 | 21 | my $pos = pos; | 
| 1038 | 16 | 50 |  |  |  | 125 | /\Gtry$s\{$s/cg or return; | 
| 1039 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'try', &statements]; | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 | 0 | 0 |  |  |  | 0 | /\G \} $s /cgx or expected "'}'"; | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 | 0 |  |  |  |  | 0 | $pos = pos; | 
| 1044 |  |  |  |  |  |  |  | 
| 1045 | 0 | 0 |  |  |  | 0 | if(/\Gcatch$s/cg) { | 
| 1046 | 0 | 0 |  |  |  | 0 | /\G \( $s /cgx or expected "'('"; | 
| 1047 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &ident | 
| 1048 |  |  |  |  |  |  | and expected 'identifier'; | 
| 1049 | 0 |  |  |  |  | 0 | &skip; | 
| 1050 | 0 | 0 |  |  |  | 0 | /\G \) $s /cgx or expected "')'"; | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 | 0 | 0 |  |  |  | 0 | /\G \{ $s /cgx or expected "'{'"; | 
| 1053 | 0 |  |  |  |  | 0 | push @$ret, &statements; | 
| 1054 | 0 | 0 |  |  |  | 0 | /\G \} $s /cgx or expected "'}'"; | 
| 1055 |  |  |  |  |  |  | } | 
| 1056 | 0 | 0 |  |  |  | 0 | if(/\Gfinally$s/cg) { | 
| 1057 | 0 | 0 |  |  |  | 0 | /\G \{ $s /cgx or expected "'{'"; | 
| 1058 | 0 |  |  |  |  | 0 | push @$ret, &statements; | 
| 1059 | 0 | 0 |  |  |  | 0 | /\G \} $s /cgx or expected "'}'"; | 
| 1060 |  |  |  |  |  |  | } | 
| 1061 |  |  |  |  |  |  |  | 
| 1062 | 0 | 0 |  |  |  | 0 | pos eq $pos and expected "'catch' or 'finally'"; | 
| 1063 |  |  |  |  |  |  |  | 
| 1064 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1065 |  |  |  |  |  |  |  | 
| 1066 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1067 |  |  |  |  |  |  | } | 
| 1068 |  |  |  |  |  |  |  | 
| 1069 |  |  |  |  |  |  | sub labelled() { | 
| 1070 | 16 |  |  | 16 | 0 | 23 | my $pos = pos; | 
| 1071 | 16 | 50 |  |  |  | 160 | /\G ($ident) $s : $s/cgx or return; | 
| 1072 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'labelled', unescape_ident $1]; | 
| 1073 |  |  |  |  |  |  |  | 
| 1074 | 0 |  |  |  |  | 0 | while (/\G($ident)$s:$s/cg) { | 
| 1075 | 0 |  |  |  |  | 0 | push @$ret, unescape_ident $1; | 
| 1076 |  |  |  |  |  |  | } | 
| 1077 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &statement | 
| 1078 |  |  |  |  |  |  | or expected 'statement'; | 
| 1079 |  |  |  |  |  |  |  | 
| 1080 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1081 |  |  |  |  |  |  |  | 
| 1082 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1083 |  |  |  |  |  |  | } | 
| 1084 |  |  |  |  |  |  |  | 
| 1085 |  |  |  |  |  |  | sub var() { | 
| 1086 | 16 |  |  | 16 | 0 | 25 | my $pos = pos; | 
| 1087 | 16 | 50 |  |  |  | 124 | /\G var $S/cgx or return; | 
| 1088 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'var']; | 
| 1089 |  |  |  |  |  |  |  | 
| 1090 | 0 |  |  |  |  | 0 | do{ | 
| 1091 | 0 |  |  |  |  | 0 | push @$ret, &vardecl; | 
| 1092 |  |  |  |  |  |  | } while(/\G$s,$s/gc); | 
| 1093 |  |  |  |  |  |  |  | 
| 1094 | 0 |  |  |  |  | 0 | optional_sc; | 
| 1095 |  |  |  |  |  |  |  | 
| 1096 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1097 |  |  |  |  |  |  |  | 
| 1098 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1099 |  |  |  |  |  |  | } | 
| 1100 |  |  |  |  |  |  |  | 
| 1101 |  |  |  |  |  |  | sub do() { | 
| 1102 | 0 |  |  | 0 | 0 | 0 | my $pos = pos; | 
| 1103 | 0 | 0 |  |  |  | 0 | /\G do(?!$id_cont)$s/cgx or return; | 
| 1104 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'do']; | 
| 1105 |  |  |  |  |  |  |  | 
| 1106 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &statement | 
| 1107 |  |  |  |  |  |  | or expected 'statement'; | 
| 1108 | 0 | 0 |  |  |  | 0 | /\Gwhile$s/cg               or expected "'while'"; | 
| 1109 | 0 | 0 |  |  |  | 0 | /\G\($s/cg                or expected "'('"; | 
| 1110 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &expr | 
| 1111 |  |  |  |  |  |  | or expected 'expression'; | 
| 1112 | 0 |  |  |  |  | 0 | &skip; | 
| 1113 | 0 | 0 |  |  |  | 0 | /\G\)/cog or expected "')'"; | 
| 1114 |  |  |  |  |  |  |  | 
| 1115 | 0 |  |  |  |  | 0 | optional_sc; | 
| 1116 |  |  |  |  |  |  |  | 
| 1117 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1118 |  |  |  |  |  |  |  | 
| 1119 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1120 |  |  |  |  |  |  | } | 
| 1121 |  |  |  |  |  |  |  | 
| 1122 |  |  |  |  |  |  | sub continue() { | 
| 1123 | 16 |  |  | 16 | 0 | 27 | my $pos = pos; | 
| 1124 | 16 | 50 |  |  |  | 81 | /\G continue(?!$id_cont)/cogx or return; | 
| 1125 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'continue']; | 
| 1126 |  |  |  |  |  |  |  | 
| 1127 | 0 | 0 |  |  |  | 0 | /\G$h($ident)/cog | 
| 1128 |  |  |  |  |  |  | and push @$ret, unescape_ident $1; | 
| 1129 |  |  |  |  |  |  |  | 
| 1130 | 0 |  |  |  |  | 0 | optional_sc; | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1133 |  |  |  |  |  |  |  | 
| 1134 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1135 |  |  |  |  |  |  | } | 
| 1136 |  |  |  |  |  |  |  | 
| 1137 |  |  |  |  |  |  | sub break() { # almost identical to continue | 
| 1138 | 16 |  |  | 16 | 0 | 29 | my $pos = pos; | 
| 1139 | 16 | 50 |  |  |  | 79 | /\G break(?!$id_cont)/cogx or return; | 
| 1140 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'break']; | 
| 1141 |  |  |  |  |  |  |  | 
| 1142 | 0 | 0 |  |  |  | 0 | /\G$h($ident)/cog | 
| 1143 |  |  |  |  |  |  | and push @$ret, unescape_ident $1; | 
| 1144 |  |  |  |  |  |  |  | 
| 1145 | 0 |  |  |  |  | 0 | optional_sc; | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1148 |  |  |  |  |  |  |  | 
| 1149 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1150 |  |  |  |  |  |  | } | 
| 1151 |  |  |  |  |  |  |  | 
| 1152 |  |  |  |  |  |  | sub return() { | 
| 1153 | 16 |  |  | 16 | 0 | 19 | my $pos = pos; | 
| 1154 | 16 | 50 |  |  |  | 81 | /\G return(?!$id_cont)/cogx or return; | 
| 1155 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'return']; | 
| 1156 |  |  |  |  |  |  |  | 
| 1157 | 0 |  |  |  |  | 0 | $pos = pos; | 
| 1158 | 0 |  |  |  |  | 0 | /\G$h/g; # skip horz ws | 
| 1159 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr and pos = $pos; | 
| 1160 |  |  |  |  |  |  | # reverse to before the white space if | 
| 1161 |  |  |  |  |  |  | # there is no expr | 
| 1162 |  |  |  |  |  |  |  | 
| 1163 | 0 |  |  |  |  | 0 | optional_sc; | 
| 1164 |  |  |  |  |  |  |  | 
| 1165 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1166 |  |  |  |  |  |  |  | 
| 1167 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1168 |  |  |  |  |  |  | } | 
| 1169 |  |  |  |  |  |  |  | 
| 1170 |  |  |  |  |  |  | sub throw() { | 
| 1171 | 16 |  |  | 16 | 0 | 22 | my $pos = pos; | 
| 1172 | 16 | 50 |  |  |  | 72 | /\G throw(?!$id_cont)/cogx | 
| 1173 |  |  |  |  |  |  | or return; | 
| 1174 | 0 |  |  |  |  | 0 | my $ret = [[$pos], 'throw']; | 
| 1175 |  |  |  |  |  |  |  | 
| 1176 | 0 |  |  |  |  | 0 | /\G$h/g; # skip horz ws | 
| 1177 | 0 | 0 |  |  |  | 0 | @$ret == push @$ret, &expr and expected 'expression'; | 
| 1178 |  |  |  |  |  |  |  | 
| 1179 | 0 |  |  |  |  | 0 | optional_sc; | 
| 1180 |  |  |  |  |  |  |  | 
| 1181 | 0 |  |  |  |  | 0 | push @{$$ret[0]},pos; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1182 |  |  |  |  |  |  |  | 
| 1183 | 0 |  |  |  |  | 0 | bless $ret, JECS; | 
| 1184 |  |  |  |  |  |  | } | 
| 1185 |  |  |  |  |  |  |  | 
| 1186 |  |  |  |  |  |  | sub expr_statement() { | 
| 1187 | 16 | 100 |  | 16 | 0 | 34 | my $ret = &expr or return; | 
| 1188 | 9 |  |  |  |  | 23 | optional_sc; # the only difference in behaviour between | 
| 1189 |  |  |  |  |  |  | # this and &expr | 
| 1190 | 5 |  |  |  |  | 21 | $ret; | 
| 1191 |  |  |  |  |  |  | } | 
| 1192 |  |  |  |  |  |  |  | 
| 1193 |  |  |  |  |  |  |  | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 |  |  |  |  |  |  | # -------- end of statement types----------# | 
| 1196 |  |  |  |  |  |  |  | 
| 1197 |  |  |  |  |  |  | # This takes care of trailing white space. | 
| 1198 |  |  |  |  |  |  | sub statement_default() { | 
| 1199 | 10955 |  |  | 10955 | 0 | 24087 | my $ret = [[pos]]; | 
| 1200 |  |  |  |  |  |  |  | 
| 1201 |  |  |  |  |  |  | # Statements that do not have an optional semicolon | 
| 1202 | 10955 | 100 |  |  |  | 128548 | if (/\G (?: | 
| 1203 |  |  |  |  |  |  | ( \{ | ; ) | 
| 1204 |  |  |  |  |  |  | | | 
| 1205 |  |  |  |  |  |  | (function)$S | 
| 1206 |  |  |  |  |  |  | | | 
| 1207 |  |  |  |  |  |  | ( if | w(?:hile|ith) | for | switch ) $s \( $s | 
| 1208 |  |  |  |  |  |  | | | 
| 1209 |  |  |  |  |  |  | ( try $s \{ $s ) | 
| 1210 |  |  |  |  |  |  | | | 
| 1211 |  |  |  |  |  |  | ($ident) $s : $s | 
| 1212 |  |  |  |  |  |  | ) /xgc) { | 
| 1213 | 101 |  |  | 101 |  | 812958 | no warnings 'uninitialized'; | 
|  | 101 |  |  |  |  | 247 |  | 
|  | 101 |  |  |  |  | 231201 |  | 
| 1214 | 1222 | 100 |  |  |  | 28208 | if($1 eq '{') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 1215 | 166 |  |  |  |  | 374 | push @$ret, 'statements'; | 
| 1216 | 166 |  |  |  |  | 345 | &skip; | 
| 1217 | 166 |  |  |  |  | 586 | while() { # 'last' does not work when 'while' is a | 
| 1218 |  |  |  |  |  |  | # statement modifier | 
| 1219 | 509 | 100 |  |  |  | 1278 | @$ret == push @$ret, | 
| 1220 |  |  |  |  |  |  | &statement_default and last; | 
| 1221 |  |  |  |  |  |  | } | 
| 1222 |  |  |  |  |  |  |  | 
| 1223 | 165 | 50 |  |  |  | 2346 | expected "'}'" unless /\G\}$s/gc; | 
| 1224 |  |  |  |  |  |  | } | 
| 1225 |  |  |  |  |  |  | elsif($1 eq ';') { | 
| 1226 | 156 |  |  |  |  | 306 | push @$ret, 'empty'; | 
| 1227 | 156 |  |  |  |  | 307 | &skip; | 
| 1228 |  |  |  |  |  |  | } | 
| 1229 |  |  |  |  |  |  | elsif($2) { | 
| 1230 | 34 |  |  |  |  | 51 | push @$ret, 'function'; | 
| 1231 | 34 | 50 |  |  |  | 74 | @$ret == push @$ret, &ident | 
| 1232 |  |  |  |  |  |  | and expected "identifier"; | 
| 1233 | 34 |  |  |  |  | 57 | &skip; | 
| 1234 | 34 |  |  |  |  | 51 | push @$ret, ¶ms; | 
| 1235 | 34 |  |  |  |  | 52 | &skip; | 
| 1236 | 34 | 50 |  |  |  | 94 | /\G \{ /gcx or expected "'{'"; | 
| 1237 |  |  |  |  |  |  | { | 
| 1238 | 34 |  |  |  |  | 34 | local $_vars = []; | 
|  | 34 |  |  |  |  | 53 |  | 
| 1239 | 34 |  |  |  |  | 67 | push @$ret, &statements, $_vars; | 
| 1240 |  |  |  |  |  |  | } | 
| 1241 | 34 | 50 |  |  |  | 287 | /\G \}$s /gcx or expected "'}'"; | 
| 1242 | 34 |  |  |  |  | 653 | push @$_vars, $ret; | 
| 1243 |  |  |  |  |  |  | } | 
| 1244 |  |  |  |  |  |  | elsif($3 eq 'if') { | 
| 1245 | 84 |  |  |  |  | 203 | push @$ret, 'if'; | 
| 1246 | 84 | 50 |  |  |  | 202 | @$ret == push @$ret, &expr | 
| 1247 |  |  |  |  |  |  | and expected 'expression'; | 
| 1248 | 84 |  |  |  |  | 192 | &skip; | 
| 1249 | 84 | 50 |  |  |  | 1096 | /\G\)$s/gc or expected "')'"; | 
| 1250 | 84 | 50 |  |  |  | 2579 | @$ret != push @$ret, &statement_default | 
| 1251 |  |  |  |  |  |  | or expected 'statement'; | 
| 1252 | 84 | 100 |  |  |  | 886 | if (/\Gelse(?!$id_cont)$s/cg) { | 
| 1253 | 29 | 50 |  |  |  | 806 | @$ret == push @$ret, | 
| 1254 |  |  |  |  |  |  | &statement_default | 
| 1255 |  |  |  |  |  |  | and expected 'statement'; | 
| 1256 |  |  |  |  |  |  | } | 
| 1257 |  |  |  |  |  |  | } | 
| 1258 |  |  |  |  |  |  | elsif($3 eq 'while') { | 
| 1259 | 22 |  |  |  |  | 50 | push @$ret, 'while'; | 
| 1260 | 22 | 50 |  |  |  | 51 | @$ret == push @$ret, &expr | 
| 1261 |  |  |  |  |  |  | and expected 'expression'; | 
| 1262 | 22 |  |  |  |  | 46 | &skip; | 
| 1263 | 22 | 50 |  |  |  | 425 | /\G\)$s/gc or expected "')'"; | 
| 1264 | 22 | 50 |  |  |  | 927 | @$ret != push @$ret, &statement_default | 
| 1265 |  |  |  |  |  |  | or expected 'statement'; | 
| 1266 |  |  |  |  |  |  | } | 
| 1267 |  |  |  |  |  |  | elsif($3 eq 'for') { | 
| 1268 | 355 |  |  |  |  | 853 | push @$ret, 'for'; | 
| 1269 | 355 | 100 |  |  |  | 3230 | if (/\G var$S/cgx) { | 
|  |  | 100 |  |  |  |  |  | 
| 1270 | 118 |  |  |  |  | 4682 | push @$ret, my $var = bless | 
| 1271 |  |  |  |  |  |  | [[pos() - length $1], 'var'], | 
| 1272 |  |  |  |  |  |  | 'JE::Code::Statement'; | 
| 1273 |  |  |  |  |  |  |  | 
| 1274 | 118 |  |  |  |  | 305 | push @$var, &vardecl_noin; | 
| 1275 | 118 |  |  |  |  | 272 | &skip; | 
| 1276 | 118 | 100 |  |  |  | 1198 | if (/\G([;,])$s/gc) { | 
| 1277 |  |  |  |  |  |  | # if there's a comma or sc then | 
| 1278 |  |  |  |  |  |  | # this is a for(;;) loop | 
| 1279 | 85 | 100 |  |  |  | 1738 | if ($1 eq ',') { | 
| 1280 |  |  |  |  |  |  | # finish getting the var | 
| 1281 |  |  |  |  |  |  | # decl list | 
| 1282 | 34 |  |  |  |  | 44 | do{ | 
| 1283 | 34 | 50 |  |  |  | 84 | @$var == | 
| 1284 |  |  |  |  |  |  | push @$var, &vardecl | 
| 1285 |  |  |  |  |  |  | and expected | 
| 1286 |  |  |  |  |  |  | 'identifier' | 
| 1287 |  |  |  |  |  |  | } while (/\G$s,$s/gc); | 
| 1288 | 34 |  |  |  |  | 1002 | &skip; | 
| 1289 | 34 | 50 |  |  |  | 271 | /\G;$s/cg | 
| 1290 |  |  |  |  |  |  | or expected 'semicolon'; | 
| 1291 |  |  |  |  |  |  | } | 
| 1292 | 85 |  |  |  |  | 594 | push @$ret, &finish_for_sc_sc; | 
| 1293 |  |  |  |  |  |  | } | 
| 1294 |  |  |  |  |  |  | else { | 
| 1295 | 33 | 50 |  |  |  | 1466 | /\Gin$s/cg or expected | 
| 1296 |  |  |  |  |  |  | "'in', comma or semicolon"; | 
| 1297 | 33 |  |  |  |  | 1675 | push @$ret, 'in'; | 
| 1298 | 33 | 50 |  |  |  | 89 | @$ret == push @$ret, &expr | 
| 1299 |  |  |  |  |  |  | and expected 'expresssion'; | 
| 1300 | 33 |  |  |  |  | 124 | &skip; | 
| 1301 | 33 | 50 |  |  |  | 487 | /\G\)$s/cg or expected "')'"; | 
| 1302 |  |  |  |  |  |  | } | 
| 1303 |  |  |  |  |  |  | } | 
| 1304 |  |  |  |  |  |  | elsif(@$ret != push @$ret, &expr_noin) { | 
| 1305 | 224 |  |  |  |  | 424 | &skip; | 
| 1306 | 224 | 100 |  |  |  | 2547 | if (/\G;$s/gc) { | 
| 1307 |  |  |  |  |  |  | # if there's a semicolon then | 
| 1308 |  |  |  |  |  |  | # this is a for(;;) loop | 
| 1309 | 203 |  |  |  |  | 2483 | push @$ret, &finish_for_sc_sc; | 
| 1310 |  |  |  |  |  |  | } | 
| 1311 |  |  |  |  |  |  | else { | 
| 1312 | 21 | 50 |  |  |  | 1709 | /\Gin$s/cg or expected | 
| 1313 |  |  |  |  |  |  | "'in' or semicolon"; | 
| 1314 | 21 |  |  |  |  | 1739 | push @$ret, 'in'; | 
| 1315 | 21 | 50 |  |  |  | 65 | @$ret == push @$ret, &expr | 
| 1316 |  |  |  |  |  |  | and expected 'expresssion'; | 
| 1317 | 21 |  |  |  |  | 57 | &skip; | 
| 1318 | 21 | 50 |  |  |  | 301 | /\G\)$s/cg or expected "')'"; | 
| 1319 |  |  |  |  |  |  | } | 
| 1320 |  |  |  |  |  |  | } | 
| 1321 |  |  |  |  |  |  | else { | 
| 1322 | 13 |  |  |  |  | 30 | push @$ret, 'empty'; | 
| 1323 | 13 | 50 |  |  |  | 129 | /\G;$s/cg | 
| 1324 |  |  |  |  |  |  | or expected 'expression or semicolon'; | 
| 1325 | 13 |  |  |  |  | 214 | push @$ret, &finish_for_sc_sc; | 
| 1326 |  |  |  |  |  |  | } | 
| 1327 |  |  |  |  |  |  |  | 
| 1328 |  |  |  |  |  |  | # body of the for loop | 
| 1329 | 355 | 50 |  |  |  | 4498 | @$ret != push @$ret, &statement_default | 
| 1330 |  |  |  |  |  |  | or expected 'statement'; | 
| 1331 |  |  |  |  |  |  | } | 
| 1332 |  |  |  |  |  |  | elsif($3 eq 'with') { | 
| 1333 | 18 |  |  |  |  | 42 | push @$ret, 'with'; | 
| 1334 | 18 | 50 |  |  |  | 48 | @$ret == push @$ret, &expr | 
| 1335 |  |  |  |  |  |  | and expected 'expression'; | 
| 1336 | 18 |  |  |  |  | 39 | &skip; | 
| 1337 | 18 | 50 |  |  |  | 461 | /\G\)$s/gc or expected "')'"; | 
| 1338 | 18 | 50 |  |  |  | 1200 | @$ret != push @$ret, &statement_default | 
| 1339 |  |  |  |  |  |  | or expected 'statement'; | 
| 1340 |  |  |  |  |  |  | } | 
| 1341 |  |  |  |  |  |  | elsif($3 eq 'switch') { | 
| 1342 | 33 |  |  |  |  | 70 | push @$ret, 'switch'; | 
| 1343 | 33 | 50 |  |  |  | 69 | @$ret == push @$ret, &expr | 
| 1344 |  |  |  |  |  |  | and expected 'expression'; | 
| 1345 | 33 |  |  |  |  | 59 | &skip; | 
| 1346 | 33 | 50 |  |  |  | 469 | /\G\)$s/gc or expected "')'"; | 
| 1347 | 33 | 50 |  |  |  | 777 | /\G\{$s/gc or expected "'{'"; | 
| 1348 |  |  |  |  |  |  |  | 
| 1349 | 33 |  |  |  |  | 630 | while (/\G case(?!$id_cont) $s/cgx) { | 
| 1350 | 31 | 50 |  |  |  | 361 | @$ret == push @$ret, &expr | 
| 1351 |  |  |  |  |  |  | and expected 'expression'; | 
| 1352 | 31 |  |  |  |  | 52 | &skip; | 
| 1353 | 31 | 50 |  |  |  | 193 | /\G:$s/cg or expected 'colon'; | 
| 1354 | 31 |  |  |  |  | 537 | push @$ret, &statements; | 
| 1355 |  |  |  |  |  |  | } | 
| 1356 | 33 |  |  |  |  | 447 | my $default=0; | 
| 1357 | 33 | 100 |  |  |  | 236 | if (/\G default(?!$id_cont) $s/cgx) { | 
| 1358 | 20 | 50 |  |  |  | 461 | /\G : $s /cgx or expected 'colon'; | 
| 1359 | 20 |  |  |  |  | 592 | push @$ret, default => &statements; | 
| 1360 | 20 |  |  |  |  | 31 | ++$default; | 
| 1361 |  |  |  |  |  |  | } | 
| 1362 | 33 |  |  |  |  | 637 | while (/\G case(?!$id_cont) $s/cgx) { | 
| 1363 | 19 | 50 |  |  |  | 352 | @$ret == push @$ret, &expr | 
| 1364 |  |  |  |  |  |  | and expected 'expression'; | 
| 1365 | 19 |  |  |  |  | 35 | &skip; | 
| 1366 | 19 | 50 |  |  |  | 172 | /\G:$s/cg or expected 'colon'; | 
| 1367 | 19 |  |  |  |  | 604 | push @$ret, &statements; | 
| 1368 |  |  |  |  |  |  | } | 
| 1369 | 33 | 0 |  |  |  | 674 | /\G \} $s /cgx or expected ( | 
|  |  | 50 |  |  |  |  |  | 
| 1370 |  |  |  |  |  |  | $default | 
| 1371 |  |  |  |  |  |  | ? "'}' or 'case'" | 
| 1372 |  |  |  |  |  |  | : "'}', 'case' or 'default'" | 
| 1373 |  |  |  |  |  |  | ); | 
| 1374 |  |  |  |  |  |  | } | 
| 1375 |  |  |  |  |  |  | elsif($4) { # try | 
| 1376 | 316 |  |  |  |  | 973 | push @$ret, 'try', &statements; | 
| 1377 | 316 | 50 |  |  |  | 3846 | /\G \} $s /cgx or expected "'}'"; | 
| 1378 |  |  |  |  |  |  |  | 
| 1379 | 316 |  |  |  |  | 7739 | my $pos = pos; | 
| 1380 |  |  |  |  |  |  |  | 
| 1381 | 316 | 100 |  |  |  | 2467 | if(/\Gcatch$s/cg) { | 
| 1382 | 314 | 50 |  |  |  | 8358 | /\G \( $s /cgx or expected "'('"; | 
| 1383 | 314 | 50 |  |  |  | 7023 | @$ret == push @$ret, &ident | 
| 1384 |  |  |  |  |  |  | and expected 'identifier'; | 
| 1385 | 314 |  |  |  |  | 727 | &skip; | 
| 1386 | 314 | 50 |  |  |  | 3152 | /\G \) $s /cgx or expected "')'"; | 
| 1387 |  |  |  |  |  |  |  | 
| 1388 | 314 | 50 |  |  |  | 8426 | /\G \{ $s /cgx or expected "'{'"; | 
| 1389 | 314 |  |  |  |  | 6594 | push @$ret, &statements; | 
| 1390 | 314 | 50 |  |  |  | 3575 | /\G \} $s /cgx or expected "'}'"; | 
| 1391 |  |  |  |  |  |  | } | 
| 1392 | 316 | 100 |  |  |  | 8866 | if(/\Gfinally$s/cg) { | 
| 1393 | 7 | 50 |  |  |  | 289 | /\G \{ $s /cgx or expected "'{'"; | 
| 1394 | 7 |  |  |  |  | 598 | push @$ret, &statements; | 
| 1395 | 7 | 50 |  |  |  | 84 | /\G \} $s /cgx or expected "'}'"; | 
| 1396 |  |  |  |  |  |  | } | 
| 1397 |  |  |  |  |  |  |  | 
| 1398 | 316 | 50 |  |  |  | 7789 | pos eq $pos and expected "'catch' or 'finally'"; | 
| 1399 |  |  |  |  |  |  | } | 
| 1400 |  |  |  |  |  |  | else { # labelled statement | 
| 1401 | 38 |  |  |  |  | 109 | push @$ret, 'labelled', unescape_ident $5; | 
| 1402 | 38 |  |  |  |  | 641 | while (/\G($ident)$s:$s/cg) { | 
| 1403 | 21 |  |  |  |  | 1554 | push @$ret, unescape_ident $1; | 
| 1404 |  |  |  |  |  |  | } | 
| 1405 | 38 | 50 |  |  |  | 3187 | @$ret != push @$ret, &statement_default | 
| 1406 |  |  |  |  |  |  | or expected 'statement'; | 
| 1407 |  |  |  |  |  |  | } | 
| 1408 |  |  |  |  |  |  | } | 
| 1409 |  |  |  |  |  |  | # Statements that do have an optional semicolon | 
| 1410 |  |  |  |  |  |  | else { | 
| 1411 | 9733 | 100 |  |  |  | 255732 | if (/\G var$S/xcg) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 1412 | 339 |  |  |  |  | 5379 | push @$ret, 'var'; | 
| 1413 |  |  |  |  |  |  |  | 
| 1414 | 339 |  |  |  |  | 475 | do{ | 
| 1415 | 351 |  |  |  |  | 1550 | push @$ret, &vardecl; | 
| 1416 |  |  |  |  |  |  | } while(/\G$s,$s/gc); | 
| 1417 |  |  |  |  |  |  | } | 
| 1418 |  |  |  |  |  |  | elsif(/\Gdo(?!$id_cont)$s/cg) { | 
| 1419 | 25 |  |  |  |  | 364 | push @$ret, 'do'; | 
| 1420 | 25 | 50 |  |  |  | 85 | @$ret != push @$ret, &statement_default | 
| 1421 |  |  |  |  |  |  | or expected 'statement'; | 
| 1422 | 25 | 50 |  |  |  | 267 | /\Gwhile$s/cg               or expected "'while'"; | 
| 1423 | 25 | 50 |  |  |  | 934 | /\G\($s/cg                or expected "'('"; | 
| 1424 | 25 | 50 |  |  |  | 707 | @$ret != push @$ret, &expr | 
| 1425 |  |  |  |  |  |  | or expected 'expression'; | 
| 1426 | 25 |  |  |  |  | 57 | &skip; | 
| 1427 | 25 | 50 |  |  |  | 334 | /\G\)/cog or expected "')'"; | 
| 1428 |  |  |  |  |  |  | } | 
| 1429 |  |  |  |  |  |  | elsif(/\G(continue|break)(?!$id_cont)/cog) { | 
| 1430 | 109 |  |  |  |  | 1760 | push @$ret, $1; | 
| 1431 | 109 | 100 |  |  |  | 880 | /\G$h($ident)/cog | 
| 1432 |  |  |  |  |  |  | and push @$ret, unescape_ident $1; | 
| 1433 |  |  |  |  |  |  | } | 
| 1434 |  |  |  |  |  |  | elsif(/\Greturn(?!$id_cont)/cog) { | 
| 1435 | 135 |  |  |  |  | 1301 | push @$ret, 'return'; | 
| 1436 | 135 |  |  |  |  | 261 | my $pos = pos; | 
| 1437 | 135 |  |  |  |  | 1485 | /\G$h/g; # skip horz ws | 
| 1438 | 135 | 100 |  |  |  | 5858 | @$ret == push @$ret, &expr and pos = $pos; | 
| 1439 |  |  |  |  |  |  | # reverse to before the white space if | 
| 1440 |  |  |  |  |  |  | # there is no expr | 
| 1441 |  |  |  |  |  |  | } | 
| 1442 |  |  |  |  |  |  | elsif(/\Gthrow(?!$id_cont)/cog) { | 
| 1443 | 23 |  |  |  |  | 59 | push @$ret, 'throw'; | 
| 1444 | 23 |  |  |  |  | 314 | /\G$h/g; # skip horz ws | 
| 1445 | 23 | 100 |  |  |  | 1434 | @$ret == push @$ret, &expr | 
| 1446 |  |  |  |  |  |  | and expected 'expression'; | 
| 1447 |  |  |  |  |  |  | } | 
| 1448 |  |  |  |  |  |  | else { # expression statement | 
| 1449 | 9102 | 100 |  |  |  | 87691 | $ret = &expr or return; | 
| 1450 |  |  |  |  |  |  | } | 
| 1451 |  |  |  |  |  |  |  | 
| 1452 |  |  |  |  |  |  | # Check for optional semicolon | 
| 1453 | 8195 | 100 |  |  |  | 104295 | m-$optional_sc-cgx | 
| 1454 |  |  |  |  |  |  | or expected "semicolon, '}' or end of line"; | 
| 1455 |  |  |  |  |  |  | } | 
| 1456 | 9413 | 100 |  |  |  | 20670 | push @{$$ret[0]},pos unless @{$$ret[0]} == 2; # an expr will | 
|  | 1851 |  |  |  |  | 4094 |  | 
|  | 9413 |  |  |  |  | 23664 |  | 
| 1457 |  |  |  |  |  |  | # already have this | 
| 1458 |  |  |  |  |  |  |  | 
| 1459 | 9413 | 100 |  |  |  | 26732 | ref $ret eq 'ARRAY' and bless $ret, 'JE::Code::Statement'; | 
| 1460 |  |  |  |  |  |  |  | 
| 1461 | 9413 |  |  |  |  | 32727 | return $ret; | 
| 1462 |  |  |  |  |  |  | } | 
| 1463 |  |  |  |  |  |  |  | 
| 1464 |  |  |  |  |  |  | sub statement() { # public | 
| 1465 | 16 |  |  | 16 | 0 | 24 | my $ret; | 
| 1466 | 16 |  |  |  |  | 30 | for my $sub(@_stms) { | 
| 1467 | 208 | 100 |  |  |  | 4912 | defined($ret = &$sub) | 
| 1468 |  |  |  |  |  |  | and last; | 
| 1469 |  |  |  |  |  |  | } | 
| 1470 | 10 | 100 |  |  |  | 51 | defined $ret ? $ret : () | 
| 1471 |  |  |  |  |  |  | } | 
| 1472 |  |  |  |  |  |  |  | 
| 1473 |  |  |  |  |  |  | # This takes care of leading white space. | 
| 1474 |  |  |  |  |  |  | sub statements() { | 
| 1475 | 1036 |  |  | 1036 | 0 | 4937 | my $ret = bless [[pos], 'statements'], 'JE::Code::Statement'; | 
| 1476 | 1036 |  |  |  |  | 9019 | /\G$s/g; # skip initial whitespace | 
| 1477 | 1036 |  |  |  |  | 9985 | while () { # 'last' does not work when 'while' is a | 
| 1478 |  |  |  |  |  |  | # statement modifier | 
| 1479 | 2937 | 50 |  |  |  | 8830 | @$ret != push @$ret, | 
|  |  | 100 |  |  |  |  |  | 
| 1480 |  |  |  |  |  |  | $_parser ? &statement : &statement_default | 
| 1481 |  |  |  |  |  |  | or last; | 
| 1482 |  |  |  |  |  |  | } | 
| 1483 | 1036 |  |  |  |  | 1972 | push @{$$ret[0]},pos; | 
|  | 1036 |  |  |  |  | 2812 |  | 
| 1484 | 1036 |  |  |  |  | 3187 | return $ret; | 
| 1485 |  |  |  |  |  |  | } | 
| 1486 |  |  |  |  |  |  |  | 
| 1487 |  |  |  |  |  |  | sub program() { # like statements(), but it allows function declarations | 
| 1488 |  |  |  |  |  |  | # as well | 
| 1489 | 351 |  |  | 351 | 0 | 2001 | my $ret = bless [[pos], 'statements'], 'JE::Code::Statement'; | 
| 1490 | 351 |  |  |  |  | 6673 | /\G$s/g; # skip initial whitespace | 
| 1491 | 351 | 100 |  |  |  | 24841 | if($_parser) { | 
| 1492 | 11 |  |  |  |  | 14 | while () { | 
| 1493 |  |  |  |  |  |  | DECL: { | 
| 1494 | 16 |  |  |  |  | 18 | for my $sub(@_decls) { | 
|  | 16 |  |  |  |  | 65 |  | 
| 1495 | 0 | 0 |  |  |  | 0 | @$ret != push @$ret, &$sub | 
| 1496 |  |  |  |  |  |  | and redo DECL; | 
| 1497 |  |  |  |  |  |  | } | 
| 1498 |  |  |  |  |  |  | } | 
| 1499 | 16 | 100 |  |  |  | 48 | @$ret != push @$ret, &statement or last; | 
| 1500 |  |  |  |  |  |  | } | 
| 1501 |  |  |  |  |  |  | } | 
| 1502 |  |  |  |  |  |  | else { | 
| 1503 | 340 |  |  |  |  | 578 | while () { | 
| 1504 | 6938 |  |  |  |  | 7416 | while() { | 
| 1505 | 7070 | 100 |  |  |  | 16015 | @$ret == push @$ret, &function and last; | 
| 1506 |  |  |  |  |  |  | } | 
| 1507 | 6938 | 100 |  |  |  | 29774 | @$ret != push @$ret, &statement_default or last; | 
| 1508 |  |  |  |  |  |  | } | 
| 1509 |  |  |  |  |  |  | } | 
| 1510 | 330 |  |  |  |  | 801 | push @{$$ret[0]},pos; | 
|  | 330 |  |  |  |  | 991 |  | 
| 1511 | 330 |  |  |  |  | 952 | return $ret; | 
| 1512 |  |  |  |  |  |  | } | 
| 1513 |  |  |  |  |  |  |  | 
| 1514 |  |  |  |  |  |  |  | 
| 1515 |  |  |  |  |  |  | # ~~~ The second arg to add_line_number is a bit ridiculous. I may change | 
| 1516 |  |  |  |  |  |  | #     add_line_number's parameter list, perhaps so it accepts either a | 
| 1517 |  |  |  |  |  |  | #     code object, or (src,file,line) if $_[1] isn'ta JE::Code. I don't | 
| 1518 |  |  |  |  |  |  | #     know.... | 
| 1519 |  |  |  |  |  |  | sub _parse($$$;$$) { # Returns just the parse tree, not a JE::Code object. | 
| 1520 |  |  |  |  |  |  | # Actually,  it returns the source followed  by  the | 
| 1521 |  |  |  |  |  |  | # parse tree in list context, or just the parse tree | 
| 1522 |  |  |  |  |  |  | # in scalar context. | 
| 1523 | 386 |  |  | 386 |  | 792 | my ($rule, $src, $my_global, $file, $line) = @_; | 
| 1524 | 386 |  |  |  |  | 992 | local our($_source, $_file, $_line) =($src,$file,$line); | 
| 1525 |  |  |  |  |  |  |  | 
| 1526 |  |  |  |  |  |  | # Note: We *hafta* stringify the $src, because it could be an | 
| 1527 |  |  |  |  |  |  | # object  with  overloading  (e.g.,  JE::String)  and  we | 
| 1528 |  |  |  |  |  |  | # need to rely on its  pos(),  which simply cannot be | 
| 1529 |  |  |  |  |  |  | # done with an object.  Furthermore,  perl5.8.5 is | 
| 1530 |  |  |  |  |  |  | # a bit buggy and sometimes mangles the contents | 
| 1531 |  |  |  |  |  |  | # of $1 when one does $obj =~ /(...)/. | 
| 1532 | 386 | 100 | 100 |  |  | 5082 | $src = defined blessed $src && $src->isa("JE::String") | 
| 1533 |  |  |  |  |  |  | ? $src->value16 | 
| 1534 |  |  |  |  |  |  | : surrogify("$src"); | 
| 1535 |  |  |  |  |  |  |  | 
| 1536 |  |  |  |  |  |  | # remove unicode format chrs | 
| 1537 | 386 |  |  |  |  | 58172 | $src =~ s/\p{Cf}//g; | 
| 1538 |  |  |  |  |  |  |  | 
| 1539 |  |  |  |  |  |  | # In HTML mode, modify the whitespace regexps to remove HTML com- | 
| 1540 |  |  |  |  |  |  | # ment delimiters and following junk up to the end of the line. | 
| 1541 | 386 | 100 |  |  |  | 1445 | $my_global->html_mode and | 
| 1542 |  |  |  |  |  |  | local $s = qr((?> | 
| 1543 |  |  |  |  |  |  | (?> [ \t\x0b\f\xa0\p{Zs}]* ) | 
| 1544 |  |  |  |  |  |  | (?> (?> | 
| 1545 |  |  |  |  |  |  | $n | 
| 1546 |  |  |  |  |  |  | (?>(?: | 
| 1547 |  |  |  |  |  |  | (?>[ \t\x0b\f\xa0\p{Zs}]*) --> | 
| 1548 |  |  |  |  |  |  | (?>[^\cm\cj\x{2028}\x{2029}]*)(?>$n|\z) | 
| 1549 |  |  |  |  |  |  | )?) | 
| 1550 |  |  |  |  |  |  | | | 
| 1551 |  |  |  |  |  |  | ^ | 
| 1552 |  |  |  |  |  |  | (?>[ \t\x0b\f\xa0\p{Zs}]*) --> | 
| 1553 |  |  |  |  |  |  | (?>[^\cm\cj\x{2028}\x{2029}]*)(?>$n|\z) | 
| 1554 |  |  |  |  |  |  | | | 
| 1555 |  |  |  |  |  |  | (?>//| |