File Coverage

blib/lib/JE/Parser.pm
Criterion Covered Total %
statement 554 734 75.4
branch 394 642 61.3
condition 34 49 69.3
subroutine 77 81 95.0
pod 7 66 10.6
total 1066 1572 67.8


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             (?>//|