File Coverage

pperl/Marpa/PP/Perl.pm
Criterion Covered Total %
statement 160 203 78.8
branch 65 108 60.1
condition 18 30 60.0
subroutine 9 12 75.0
pod 0 4 0.0
total 252 357 70.5


line stmt bran cond sub pod time code
1             # Copyright 2012 Jeffrey Kegler
2             # This file is part of Marpa::PP. Marpa::PP is free software: you can
3             # redistribute it and/or modify it under the terms of the GNU Lesser
4             # General Public License as published by the Free Software Foundation,
5             # either version 3 of the License, or (at your option) any later version.
6             #
7             # Marpa::PP is distributed in the hope that it will be useful,
8             # but WITHOUT ANY WARRANTY; without even the implied warranty of
9             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10             # Lesser General Public License for more details.
11             #
12             # You should have received a copy of the GNU Lesser
13             # General Public License along with Marpa::PP. If not, see
14             # http://www.gnu.org/licenses/.
15              
16             package Marpa::PP::Perl;
17              
18 2     2   16347 use 5.010;
  2         10  
  2         122  
19 2     2   13 use strict;
  2         5  
  2         77  
20 2     2   12 use warnings;
  2         7  
  2         128  
21              
22             package Marpa::PP::Internal::Perl;
23              
24 2     2   1462 use charnames ':full';
  2         103560  
  2         16  
25 2     2   524 use English qw( -no_match_vars );
  2         4  
  2         18  
26              
27 2     2   2576 use Marpa::PP::Perl::Version;
  2         4  
  2         26541  
28              
29             # This code is about Perl GRAMMAR.
30             # If you're looking here
31             # for a Perl SEMANTICS here,
32             # you won't find one.
33              
34             my $reference_grammar = <<'END_OF_GRAMMAR';
35              
36             # This is taken from perly.y for Perl 5.12.1
37             prog: prog ::= lineseq ;
38              
39             # /* An ordinary block */
40             block: block ::= '{' lineseq '}' ;
41              
42             mblock ::= '{' lineseq '}' ;
43              
44             # /* A collection of "lines" in the program */
45             lineseq_t: lineseq ::= ;
46             lineseq__decl: lineseq ::= lineseq decl ;
47             lineseq__line: lineseq ::= lineseq line ;
48              
49             # /* A "line" in the program */
50             line ::= label cond ;
51             line ::= loop ; # /* loops add their own labels */
52             line ::= switch ; # /* ... and so do switches */
53             line ::= label case ;
54             line ::= label ';' ;
55             line__sideff: line ::= label sideff ';' ;
56             line ::= label PLUGSTMT ;
57              
58             /* An expression which may have a side-effect */
59             sideff ::= error ;
60             sideff: sideff ::= expr ;
61             sideff ::= expr IF expr ;
62             sideff ::= expr UNLESS expr ;
63             sideff ::= expr WHILE expr ;
64             sideff ::= expr UNTIL iexpr ;
65             sideff ::= expr FOR expr ;
66             sideff ::= expr WHEN expr ;
67              
68             /* else and elsif blocks */
69             else ::= ; /* NULL */
70             else ::= ELSE mblock ;
71             else ::= ELSIF '(' mexpr ')' mblock else ;
72              
73             /* Real conditional expressions */
74             cond ::= IF '(' mexpr ')' mblock else ;
75             cond ::= UNLESS '(' miexpr ')' mblock else ;
76              
77             /* Cases for a switch statement */
78             case ::= WHEN '(' remember mexpr ')' mblock ;
79             case ::= DEFAULT block ;
80              
81             /* Continue blocks */
82             cont ::= ; /* NULL */
83             cont ::= CONTINUE block ;
84              
85             /* Loops: while, until, for, and a bare block */
86             loop ::= label WHILE '(' remember texpr ')' mintro mblock cont ;
87             loop ::= label UNTIL '(' remember iexpr ')' mintro mblock cont ;
88             loop ::= label FOR MY remember my_scalar '(' mexpr ')' mblock cont ;
89             loop ::= label FOR scalar '(' remember mexpr ')' mblock cont ;
90             loop ::= label FOR '(' remember mexpr ')' mblock cont ;
91             loop ::= label FOR '(' remember mnexpr ';' texpr ';' mintro mnexpr ')' mblock ;
92             /* basically fake up an initialize-while lineseq */
93             loop ::= label block cont ; /* a block is a loop that happens once */
94              
95             /* Switch blocks */
96             switch ::= label GIVEN '(' remember mydefsv mexpr ')' mblock ;
97              
98             /* determine whether there are any new my declarations */
99             mintro ::= ; /* NULL */
100              
101             /* Normal expression */
102             nexpr ::= ;
103             nexpr ::= sideff ;
104              
105             /* Boolean expression */
106             texpr ::= ; /* NULL means true */
107             texpr ::= expr ;
108              
109             /* Inverted boolean expression */
110             iexpr ::= expr ;
111              
112             /* Expression with its own lexical scope */
113             mexpr ::= expr ;
114              
115             mnexpr ::= nexpr ;
116              
117             miexpr ::= iexpr ;
118              
119             /* Optional "MAIN:"-style loop labels */
120             label ::= ; /* empty */
121             label ::= LABEL ;
122              
123             /* Some kind of declaration - just hang on peg in the parse tree */
124             decl ::= format ;
125             decl ::= subrout ;
126             decl ::= mysubrout ;
127             decl ::= package ;
128             decl ::= use ;
129             decl ::= peg ;
130              
131             peg ::= PEG ;
132              
133             format ::= FORMAT startformsub formname block ;
134              
135             formname ::= WORD ;
136             formname ::= ; /* NULL */
137              
138             /* Unimplemented "my sub foo { }" */
139             mysubrout ::= MYSUB startsub subname proto subattrlist subbody ;
140              
141             /* Subroutine definition */
142             subrout ::= SUB startsub subname proto subattrlist subbody ;
143              
144             startsub ::= ; /* NULL */ /* start a regular subroutine scope */
145              
146             startanonsub ::= ; /* NULL */ /* start an anonymous subroutine scope */
147              
148             startformsub ::= ; /* NULL */ /* start a format subroutine scope */
149              
150             /* Name of a subroutine - must be a bareword, could be special */
151             subname ::= WORD ;
152              
153             /* Subroutine prototype */
154             proto ::= ; /* NULL */
155             proto ::= THING ;
156              
157             /* Optional list of subroutine attributes */
158             subattrlist ::= ; /* NULL */
159             subattrlist ::= COLONATTR THING ;
160             subattrlist ::= COLONATTR ;
161              
162             /* List of attributes for a "my" variable declaration */
163             myattrlist ::= COLONATTR THING ;
164             myattrlist ::= COLONATTR ;
165              
166             /* Subroutine body - either null or a block */
167             subbody ::= block ;
168             subbody ::= ';' ;
169              
170             package ::= PACKAGE WORD WORD ';' ;
171              
172             use ::= USE startsub WORD WORD listexpr ';' ;
173              
174             /* Ordinary expressions; logical combinations */
175              
176             expr: expr ::= or_expr;
177              
178             # %left OROP DOROP
179             or_expr: or_expr ::= or_expr OROP and_expr ;
180             or_expr__dor: or_expr ::= or_expr DOROP and_expr ;
181             or_expr__t : or_expr ::= and_expr ;
182              
183             # %left ANDOP
184             and_expr: and_expr ::= and_expr ANDOP argexpr ;
185             and_expr__t: and_expr ::= argexpr ;
186              
187             /* Expressions are a list of terms joined by commas */
188             argexpr__comma: argexpr ::= argexpr ',' ;
189             argexpr: argexpr ::= argexpr ',' term ;
190             argexpr__t: argexpr ::= term ;
191              
192             /* Names of methods. May use $object->$methodname */
193             method ::= METHOD ;
194             method ::= scalar ;
195              
196              
197             # %nonassoc PREC_LOW
198             # %nonassoc LOOPEX
199             # %left OROP DOROP
200             # %left ANDOP
201             # %right NOTOP
202             # %nonassoc LSTOP LSTOPSUB
203             # %left ','
204             # %right ASSIGNOP
205             # %right '?' ':'
206             # %nonassoc DOTDOT YADAYADA
207             # %left OROR DORDOR
208             # %left ANDAND
209             # %left BITOROP
210             # %left BITANDOP
211             # %nonassoc EQOP
212             # %nonassoc RELOP
213             # %nonassoc UNIOP UNIOPSUB
214             # %nonassoc REQUIRE
215             # %left SHIFTOP
216             # %left ADDOP
217             # %left MULOP
218             # %left MATCHOP
219             # %right '!' '~' UMINUS REFGEN
220             # %right POWOP
221             # %nonassoc PREINC PREDEC POSTINC POSTDEC
222             # %left ARROW
223             # %nonassoc ')'
224             # %left '('
225             # %left '[' '{'
226              
227             # %nonassoc PREC_LOW
228             # no terms
229              
230             # %nonassoc LOOPEX
231             term__t: term ::= term_notop ;
232             term ::= LOOPEX ; /* loop exiting command (goto, last, dump, etc) */
233             term ::= LOOPEX term_notop ;
234              
235             # %left OROP DOROP
236             # %left ANDOP
237             # no terms, just expr's
238              
239             # %right NOTOP
240             term_notop__t: term_notop ::= term_listop ;
241             term_notop ::= NOTOP argexpr ; /* not $foo */
242              
243             # %nonassoc LSTOP LSTOPSUB
244             /* List operators */
245             term_listop__t: term_listop ::= term_assign ;
246             term_listop ::= LSTOP indirob argexpr ; /* map {...} @args or print $fh @args */
247             term_lstop: term_listop ::= LSTOP listexpr ; /* print @args */
248             term_listop ::= LSTOPSUB startanonsub block listexpr ;
249             term_listop ::= METHOD indirob listexpr ; /* new Class @args */
250             term_assign_lstop: term_listop ::= term_cond ASSIGNOP term_listop ; /* $x = bless $x, $y */
251              
252             # /* sub f(&@); f { foo } ... */ /* ... @bar */
253              
254             # %left ','
255             # no terms
256              
257             # %right ASSIGNOP
258             /* Binary operators between terms */
259             term_assign__t: term_assign ::= term_cond ;
260             # $x = $y
261             term_assign: term_assign ::= term_cond ASSIGNOP term_assign ;
262              
263             # %right '?' ':'
264             term_cond__t: term_cond ::= term_dotdot ;
265             term_cond: term_cond ::= term_dotdot '?' term_cond ':' term_cond ;
266              
267             # %nonassoc DOTDOT YADAYADA
268             term_dotdot__t: term_dotdot ::= term_oror ;
269             # $x..$y, $x...$y */
270             term_dotdot: term_dotdot ::= term_oror DOTDOT term_oror ;
271             YADAYADA: term_dotdot ::= YADAYADA ;
272              
273             # %left OROR DORDOR
274             term_oror__t: term_oror ::= term_andand ;
275             term_oror ::= term_oror OROR term_andand ; /* $x || $y */
276             term_oror ::= term_oror DORDOR term_andand ; /* $x // $y */
277              
278             # %left ANDAND
279             term_andand__t: term_andand ::= term_bitorop ;
280             term_andand ::= term_andand ANDAND term_bitorop ; /* $x && $y */
281              
282             # %left BITOROP
283             term_bitorop__t: term_bitorop ::= term_bitandop;
284             term_bitorop ::= term_bitorop BITOROP term_bitandop ; /* $x | $y */
285              
286             # %left BITANDOP
287             term_bitandop__t: term_bitandop ::= term_eqop ;
288             term_bitandop ::= term_bitandop BITANDOP term_eqop ; /* $x & $y */
289              
290             # %nonassoc EQOP
291             term_eqop__t: term_eqop ::= term_relop ;
292             term_eqop ::= term_relop EQOP term_relop ; /* $x == $y, $x eq $y */
293              
294             # %nonassoc RELOP
295             term_relop__t: term_relop ::= term_uniop ;
296             term_relop ::= term_uniop RELOP term_uniop ; /* $x > $y, etc. */
297              
298             # %nonassoc UNIOP UNIOPSUB
299             term_uniop__t: term_uniop ::= term_require ;
300             uniop: term_uniop ::= UNIOP ; /* Unary op, $_ implied */
301             term_uniop ::= UNIOP block ; /* eval { foo }* */
302             term_uniop ::= UNIOP term_require ; /* Unary op */
303             term_uniop ::= UNIOPSUB ;
304             term_uniop ::= UNIOPSUB term_require ; /* Sub treated as unop */
305             /* Things called with "do" */
306             term_uniop ::= DO term_require ; /* do $filename */
307             /* "my" declarations, with optional attributes */
308             # MY has no precedence
309             # so apparently %prec UNIOP for term ::= myattrterm does the job
310             term_myattr: term_uniop ::= MY myterm myattrlist ;
311             term_my: term_uniop ::= MY myterm ;
312             term_local: term_uniop ::= LOCAL term_require ;
313              
314             # %nonassoc REQUIRE
315             term_require__t: term_require ::= term_shiftop ;
316             term_require ::= REQUIRE ; /* require, $_ implied */
317             term_require ::= REQUIRE term_shiftop ; /* require Foo */
318              
319             # %left SHIFTOP
320             term_shiftop__t: term_shiftop ::= term_addop ;
321             term_shiftop ::= term_shiftop SHIFTOP term_addop ; /* $x >> $y, $x << $y */
322              
323             # %left ADDOP
324             term_addop__t: term_addop ::= term_mulop ;
325             term_addop ::= term_addop ADDOP term_mulop ; /* $x + $y */
326              
327             # %left MULOP
328             term_mulop__t: term_mulop ::= term_matchop ;
329             term_mulop ::= term_mulop MULOP term_matchop ; /* $x * $y, $x x $y */
330              
331             # %left MATCHOP
332             term_matchop__t: term_matchop ::= term_uminus ;
333             term_matchop ::= term_matchop MATCHOP term_uminus ; /* $x =~ /$y/ */
334              
335             # %right '!' '~' UMINUS REFGEN
336             term_uminus__t: term_uminus ::= term_powop ;
337             term_uminus ::= '!' term_uminus ; /* !$x */
338             term_uminus ::= '~' term_uminus ; /* ~$x */
339             /* Unary operators and terms */
340             term_uminus ::= '-' term_uminus ; /* -$x */
341             term_uminus ::= '+' term_uminus ; /* +$x */
342             refgen: term_uminus ::= REFGEN term_uminus ; /* \$x, \@y, \%z */
343              
344             # %right POWOP
345             term_powop__t: term_powop ::= term_increment ;
346             term_powop ::= term_increment POWOP term_powop ; /* $x ** $y */
347              
348             # %nonassoc PREINC PREDEC POSTINC POSTDEC
349             term_increment__t: term_increment ::= term_arrow ;
350             term_increment ::= term_arrow POSTINC ; /* $x++ */
351             term_increment ::= term_arrow POSTDEC ; /* $x-- */
352             term_increment ::= PREINC term_arrow ; /* ++$x */
353             term_increment ::= PREDEC term_arrow ; /* --$x */
354              
355             # %left ARROW
356             term_arrow__t: term_arrow ::= term_hi ;
357             term_arrow ::= term_arrow ARROW method '(' listexprcom ')' ; /* $foo->bar(list) */
358             term_arrow ::= term_arrow ARROW method ; /* $foo->bar */
359              
360             # Able to collapse the last few
361             # because no RHS terms
362             # %nonassoc ')'
363             # %left '('
364             # %left '[' '{' -- no terms at this precedence
365              
366             term_hi ::= DO WORD '(' ')' ; /* do somesub() */
367             term_hi ::= DO WORD '(' expr ')' ; /* do somesub(@args) */
368             term_hi ::= DO scalar '(' ')' ; /* do $subref () */
369             term_hi ::= DO scalar '(' expr ')' ; /* do $subref (@args) */
370             term_hi__parens: term_hi ::= '(' expr ')' ;
371             term_hi ::= '(' ')' ;
372             term_hi ::= amper '(' ')' ; /* &foo() */
373             term_hi ::= amper '(' expr ')' ; /* &foo(@args) */
374             term_hi ::= FUNC0 '(' ')' ;
375             term_hi ::= FUNC1 '(' ')' ; /* not () */
376             term_hi ::= FUNC1 '(' expr ')' ; /* not($foo) */
377             term_hi ::= PMFUNC '(' argexpr ')' ; /* m//, s///, tr/// */
378             term_hi ::= FUNC '(' indirob expr ')' ; /* print ($fh @args */
379             term_hi ::= FUNCMETH indirob '(' listexprcom ')' ; /* method $object (@args) */
380             term_hi ::= FUNC '(' listexprcom ')' ; /* print (@args) */
381             anon_hash: term_hi ::= HASHBRACK expr ';' '}' ; /* { foo => "Bar" } */
382             anon_empty_hash: term_hi ::= HASHBRACK ';' '}' ; /* { } (';' by tokener) */
383             term_hi ::= ANONSUB startanonsub proto subattrlist block ;
384             do_block: term_hi ::= DO block ; /* do { code */
385             term_hi__scalar: term_hi ::= scalar ;
386             term_hi__star: term_hi ::= star ;
387             term_hi__hsh: term_hi ::= hsh ;
388             term_hi__ary: term_hi ::= ary ;
389             # $#x, $#{ something }
390             term_hi__arylen: term_hi ::= arylen ;
391             term_hi__subscripted: term_hi ::= subscripted ;
392             term_hi__THING: term_hi ::= THING ;
393             /* Constructors for anonymous data */
394             term_hi__anon_array: term_hi ::= '[' expr ']' ;
395             term_hi__anon_empty_array: term_hi ::= '[' ']' ;
396              
397             # Some kind of subscripted expression
398             subscripted ::= star '{' expr ';' '}' ; /* *main::{something} */
399             array_index: subscripted ::= scalar '[' expr ']' ; /* $array[$element] */
400             term_hi__arrow_array: subscripted ::= term_hi ARROW '[' expr ']' ; /* somearef->[$element] */
401             array_index_r: subscripted ::= subscripted '[' expr ']' ; /* $foo->[$bar]->[$baz] */
402             hash_index: subscripted ::= scalar '{' expr ';' '}' ; /* $foo->{bar();} */
403             term_hi__arrow_hash: subscripted ::= term_hi ARROW '{' expr ';' '}' ; /* somehref->{bar();} */
404             hash_index_r: subscripted ::= subscripted '{' expr ';' '}' ; /* $foo->[bar]->{baz;} */
405             subscripted ::= term_hi ARROW '(' ')' ; /* $subref->() */
406             subscripted ::= term_hi ARROW '(' expr ')' ; /* $subref->(@args) */
407             subscripted ::= subscripted '(' expr ')' ; /* $foo->{bar}->(@args) */
408             subscripted ::= subscripted '(' ')' ; /* $foo->{bar}->() */
409             subscripted ::= '(' expr ')' '[' expr ']' ; /* list slice */
410             subscripted ::= '(' ')' '[' expr ']' ; /* empty list slice! */
411              
412             term_hi ::= ary '[' expr ']' ; /* array slice */
413             term_hi ::= ary '{' expr ';' '}' ; /* @hash{@keys} */
414              
415             term_hi ::= amper ; /* &foo; */
416             term_hi ::= NOAMP WORD listexpr ; /* foo(@args) */
417             term_hi ::= FUNC0 ; /* Nullary operator */
418             term_hi ::= FUNC0SUB ; /* Sub treated as nullop */
419             term_hi ::= WORD ;
420             term_hi ::= PLUGEXPR ;
421              
422             # End of list of terms
423              
424             /* Things that can be "my"'d */
425             myterm_scalar: myterm ::= scalar ;
426             myterm_hash: myterm ::= hsh ;
427             myterm_array: myterm ::= ary ;
428              
429             /* Basic list expressions */
430             # Essentially, a listexpr is a nullable argexpr
431             listexpr_t: listexpr ::= ; /* NULL */
432             listexpr: listexpr ::= argexpr ;
433              
434             # In perly.y listexprcom occurs only inside parentheses
435             listexprcom ::= ; /* NULL */
436             listexprcom ::= expr ;
437             listexprcom ::= expr ',' ;
438              
439             /* A little bit of trickery to make "for my $foo (@bar)" actually be lexical */
440             my_scalar ::= scalar ;
441              
442             amper ::= '&' indirob ;
443              
444             scalar: scalar ::= '$' indirob ;
445              
446             ary ::= '@' indirob ;
447              
448             hsh ::= '%' indirob ;
449              
450             arylen ::= DOLSHARP indirob ;
451              
452             star ::= '*' indirob ;
453              
454             /* Indirect objects */
455             indirob__WORD: indirob ::= WORD ;
456             indirob ::= scalar ;
457             indirob__block: indirob ::= block ;
458             indirob ::= PRIVATEREF ;
459             END_OF_GRAMMAR
460              
461             ## no critic (ValuesAndExpressions::RequireInterpolationOfMetachars)
462              
463             my %symbol_name = (
464             q{'~'} => 'TILDE',
465             q{'-'} => 'MINUS',
466             q{','} => 'COMMA',
467             q{';'} => 'SEMI',
468             q{':'} => 'COLON',
469             q{'!'} => 'BANG',
470             q{'?'} => 'QUESTION',
471             q{'('} => 'LPAREN',
472             q{')'} => 'RPAREN',
473             q{'['} => 'LSQUARE',
474             q{']'} => 'RSQUARE',
475             q['{'] => 'LCURLY',
476             q['}'] => 'RCURLY',
477             q{'@'} => 'ATSIGN',
478             q{'$'} => 'DOLLAR',
479             q{'*'} => 'ASTERISK',
480             q{'&'} => 'AMPERSAND',
481             q{'%'} => 'PERCENT',
482             q{'+'} => 'PLUS',
483             );
484              
485             my %perl_type_by_cast = (
486             q{\\} => 'REFGEN',
487             q{$} => 'DOLLAR',
488             q{@} => 'ATSIGN',
489             q{%} => 'PERCENT',
490             );
491              
492             my %perl_type_by_structure = (
493             q{(} => 'LPAREN',
494             q{)} => 'RPAREN',
495             q{[} => 'LSQUARE',
496             q{]} => 'RSQUARE',
497             q[{] => 'LCURLY',
498             q[}] => 'RCURLY',
499             q{;} => 'SEMI',
500             );
501              
502             my %perl_type_by_op = (
503             q{->} => 'ARROW', # 1
504             q{--} => 'PREDEC', # 2
505             q{++} => 'PREINC', # 2
506             q{**} => 'POWOP', # 3
507             q{~} => 'TILDE', # 4
508             q{!} => 'BANG', # 4
509             q{\\} => 'REFGEN', # 4
510             q{=~} => 'MATCHOP', # 5
511             q{!~} => 'MATCHOP', # 5
512             q{/} => 'MULOP', # 6
513             q{*} => 'MULOP', # 6
514             q{%} => 'MULOP', # 6
515             q{x} => 'MULOP', # 6
516             q{-} => 'MINUS', # 7
517             q{.} => 'ADDOP', # 7
518             q{+} => 'PLUS', # 7
519             q{<<} => 'SHIFTOP', # 8
520             q{>>} => 'SHIFTOP', # 8
521             q{-A} => 'UNIOP', # 9
522             q{-b} => 'UNIOP', # 9
523             q{-B} => 'UNIOP', # 9
524             q{-c} => 'UNIOP', # 9
525             q{-C} => 'UNIOP', # 9
526             q{-d} => 'UNIOP', # 9
527             q{-e} => 'UNIOP', # 9
528             q{-f} => 'UNIOP', # 9
529             q{-g} => 'UNIOP', # 9
530             q{-k} => 'UNIOP', # 9
531             q{-l} => 'UNIOP', # 9
532             q{-M} => 'UNIOP', # 9
533             q{-o} => 'UNIOP', # 9
534             q{-O} => 'UNIOP', # 9
535             q{-p} => 'UNIOP', # 9
536             q{-r} => 'UNIOP', # 9
537             q{-R} => 'UNIOP', # 9
538             q{-s} => 'UNIOP', # 9
539             q{-S} => 'UNIOP', # 9
540             q{-t} => 'UNIOP', # 9
541             q{-T} => 'UNIOP', # 9
542             q{-u} => 'UNIOP', # 9
543             q{-w} => 'UNIOP', # 9
544             q{-W} => 'UNIOP', # 9
545             q{-x} => 'UNIOP', # 9
546             q{-X} => 'UNIOP', # 9
547             q{-z} => 'UNIOP', # 9
548             q{ge} => 'RELOP', # 10
549             q{gt} => 'RELOP', # 10
550             q{le} => 'RELOP', # 10
551             q{lt} => 'RELOP', # 10
552             q{<=} => 'RELOP', # 10
553             q{<} => 'RELOP', # 10
554             q{>=} => 'RELOP', # 10
555             q{>} => 'RELOP', # 10
556             q{cmp} => 'EQOP', # 11
557             q{eq} => 'EQOP', # 11
558             q{ne} => 'EQOP', # 11
559             q{~~} => 'EQOP', # 11
560             q{<=>} => 'EQOP', # 11
561             q{==} => 'EQOP', # 11
562             q{!=} => 'EQOP', # 11
563             q{&} => 'BITANDOP', # 12
564             q{^} => 'BITOROP', # 13
565             q{|} => 'BITOROP', # 13
566             q{&&} => 'ANDAND', # 14
567             q{||} => 'OROR', # 15
568             q{//} => 'DORDOR', # 15
569             q{..} => 'DOTDOT', # 16
570             q{...} => 'YADAYADA', # 17
571             q{:} => 'COLON', # 18
572             q{?} => 'QUESTION', # 18
573             q{^=} => 'ASSIGNOP', # 19
574             q{<<=} => 'ASSIGNOP', # 19
575             q{=} => 'ASSIGNOP', # 19
576             q{>>=} => 'ASSIGNOP', # 19
577             q{|=} => 'ASSIGNOP', # 19
578             q{||=} => 'ASSIGNOP', # 19
579             q{-=} => 'ASSIGNOP', # 19
580             q{/=} => 'ASSIGNOP', # 19
581             q{.=} => 'ASSIGNOP', # 19
582             q{*=} => 'ASSIGNOP', # 19
583             q{**=} => 'ASSIGNOP', # 19
584             q{&=} => 'ASSIGNOP', # 19
585             q{&&=} => 'ASSIGNOP', # 19
586             q{%=} => 'ASSIGNOP', # 19
587             q{+=} => 'ASSIGNOP', # 19
588             q{x=} => 'ASSIGNOP', # 19
589             q{,} => 'COMMA', # 20
590             q{=>} => 'COMMA', # 20
591             q{not} => 'NOTOP', # 22
592             q{and} => 'ANDOP', # 23
593             q{or} => 'OROP', # 24
594             q{xor} => 'DOROP', # 24
595             );
596              
597             my %perl_type_by_word = (
598             'AUTOLOAD' => 'PHASER -- TO BE DETERMINED',
599             'BEGIN' => 'PHASER -- TO BE DETERMINED',
600             'CHECK' => 'PHASER -- TO BE DETERMINED',
601             'CORE' => 'TO_BE_DETERMINED',
602             'DESTROY' => 'PHASER -- TO BE DETERMINED',
603             'END' => 'PHASER -- TO BE DETERMINED',
604             'INIT' => 'PHASER -- TO BE DETERMINED',
605             'NULL' => 'TO_BE_DETERMINED',
606             'UNITCHECK' => 'PHASER -- TO BE DETERMINED',
607             '__DATA__' => 'TO_BE_DETERMINED',
608             '__END__' => 'TO_BE_DETERMINED',
609             '__FILE__' => 'THING',
610             '__LINE__' => 'THING',
611             '__PACKAGE__' => 'THING',
612             'abs' => 'UNIOP',
613             'accept' => 'LSTOP',
614             'alarm' => 'UNIOP',
615             'atan2' => 'LSTOP',
616             'bind' => 'LSTOP',
617             'binmode' => 'LSTOP',
618             'bless' => 'LSTOP',
619             'bless' => 'LSTOP',
620             'break' => 'LOOPEX',
621             'caller' => 'UNIOP',
622             'chdir' => 'UNIOP',
623             'chmod' => 'LSTOP',
624             'chomp' => 'UNIOP',
625             'chop' => 'UNIOP',
626             'chown' => 'LSTOP',
627             'chr' => 'UNIOP',
628             'chroot' => 'UNIOP',
629             'close' => 'UNIOP',
630             'closedir' => 'UNIOP',
631             'connect' => 'LSTOP',
632             'continue' => 'CONTINUE',
633             'cos' => 'UNIOP',
634             'crypt' => 'LSTOP',
635             'dbmclose' => 'UNIOP',
636             'dbmopen' => 'LSTOP',
637             'default' => 'DEFAULT',
638             'defined' => 'UNIOP',
639             'delete' => 'UNIOP',
640             'die' => 'LSTOP',
641             'do' => 'DO',
642             'dump' => 'UNIOP',
643             'each' => 'UNIOP',
644             'else' => 'ELSE',
645             'elsif' => 'ELSIF',
646             'endgrent' => 'FUNC0',
647             'endhostent' => 'FUNC0',
648             'endnetent' => 'FUNC0',
649             'endprotoent' => 'FUNC0',
650             'endpwent' => 'FUNC0',
651             'endservent' => 'FUNC0',
652             'eof' => 'UNIOP',
653             'eval' => 'UNIOP',
654             'exec' => 'LSTOP',
655             'exists' => 'UNIOP',
656             'exit' => 'UNIOP',
657             'exp' => 'UNIOP',
658             'fcntl' => 'LSTOP',
659             'fileno' => 'UNIOP',
660             'flock' => 'LSTOP',
661             'for' => 'FOR',
662             'foreach' => 'FOR',
663             'fork' => 'FUNC0',
664             'format' => 'FUNC0',
665             'formline' => 'LSTOP',
666             'getc' => 'UNIOP',
667             'getgrent' => 'FUNC0',
668             'getgrgid' => 'UNIOP',
669             'getgrnam' => 'UNIOP',
670             'gethostbyaddr' => 'LSTOP',
671             'gethostbyname' => 'UNIOP',
672             'gethostent' => 'FUNC0',
673             'getlogin' => 'FUNC0',
674             'getnetbyaddr' => 'LSTOP',
675             'getnetbyname' => 'UNIOP',
676             'getnetent' => 'FUNC0',
677             'getpeername' => 'UNIOP',
678             'getpgrp' => 'UNIOP',
679             'getppid' => 'FUNC0',
680             'getpriority' => 'LSTOP',
681             'getprotobyname' => 'UNIOP',
682             'getprotobynumber' => 'UNIOP',
683             'getprotoent' => 'FUNC0',
684             'getpwent' => 'FUNC0',
685             'getpwnam' => 'UNIOP',
686             'getpwuid' => 'UNIOP',
687             'getservbyname' => 'LSTOP',
688             'getservbyport' => 'LSTOP',
689             'getservent' => 'FUNC0',
690             'getsockname' => 'UNIOP',
691             'getsockopt' => 'LSTOP',
692             'given' => 'GIVEN',
693             'glob' => 'UNIOP',
694             'gmtime' => 'UNIOP',
695             'goto' => 'LOOPEX',
696             'grep' => 'LSTOP',
697             'hex' => 'UNIOP',
698             'if' => 'IF',
699             'import' => 'LSTOP', # not really a keyword, but make it a LSTOP
700             'index' => 'LSTOP',
701             'int' => 'UNIOP',
702             'ioctl' => 'LSTOP',
703             'join' => 'LSTOP',
704             'keys' => 'UNIOP',
705             'kill' => 'LSTOP',
706             'last' => 'LOOPEX',
707             'lc' => 'UNIOP',
708             'lcfirst' => 'UNIOP',
709             'length' => 'UNIOP',
710             'link' => 'LSTOP',
711             'listen' => 'LSTOP',
712             'local' => 'LOCAL',
713             'localtime' => 'UNIOP',
714             'lock' => 'UNIOP',
715             'log' => 'UNIOP',
716             'lstat' => 'UNIOP',
717             'm' => 'QUOTEABLE -- TO BE DETERMINED',
718             'map' => 'LSTOP',
719             'mkdir' => 'LSTOP',
720             'msgctl' => 'LSTOP',
721             'msgget' => 'LSTOP',
722             'msgrcv' => 'LSTOP',
723             'msgsnd' => 'LSTOP',
724             'my' => 'MY',
725             'my' => 'MY',
726             'next' => 'LOOPEX',
727             'no' => 'USE',
728             'oct' => 'UNIOP',
729             'open' => 'LSTOP',
730             'opendir' => 'LSTOP',
731             'ord' => 'UNIOP',
732             'our' => 'MY',
733             'pack' => 'LSTOP',
734             'package' => 'PACKAGE',
735             'pipe' => 'LSTOP',
736             'pop' => 'UNIOP',
737             'pos' => 'UNIOP',
738             'print' => 'LSTOP',
739             'printf' => 'LSTOP',
740             'prototype' => 'UNIOP',
741             'push' => 'LSTOP',
742             'q' => 'QUOTEABLE -- TO BE DETERMINED',
743             'qq' => 'QUOTEABLE -- TO BE DETERMINED',
744             'qr' => 'QUOTEABLE -- TO BE DETERMINED',
745             'quotemeta' => 'UNIOP',
746             'qw' => 'QUOTEABLE -- TO BE DETERMINED',
747             'qx' => 'QUOTEABLE -- TO BE DETERMINED',
748             'rand' => 'UNIOP',
749             'read' => 'LSTOP',
750             'readdir' => 'UNIOP',
751             'readline' => 'UNIOP',
752             'readlink' => 'UNIOP',
753             'readpipe' => 'UNIOP',
754             'recv' => 'LSTOP',
755             'redo' => 'LOOPEX',
756             'ref' => 'UNIOP',
757             'rename' => 'LSTOP',
758             'require' => 'REQUIRE',
759             'reset' => 'UNIOP',
760             'return' => 'LSTOP',
761             'reverse' => 'LSTOP',
762             'rewinddir' => 'UNIOP',
763             'rindex' => 'LSTOP',
764             'rmdir' => 'UNIOP',
765             's' => 'QUOTEABLE -- TO BE DETERMINED',
766             'say' => 'LSTOP',
767             'scalar' => 'UNIOP',
768             'seek' => 'LSTOP',
769             'seekdir' => 'LSTOP',
770             'select' => 'LSTOP',
771             'semctl' => 'LSTOP',
772             'semget' => 'LSTOP',
773             'semop' => 'LSTOP',
774             'send' => 'LSTOP',
775             'setgrent' => 'FUNC0',
776             'sethostent' => 'UNIOP',
777             'setnetent' => 'UNIOP',
778             'setpgrp' => 'LSTOP',
779             'setpriority' => 'LSTOP',
780             'setprotoent' => 'UNIOP',
781             'setpwent' => 'FUNC0',
782             'setservent' => 'UNIOP',
783             'setsockopt' => 'LSTOP',
784             'shift' => 'UNIOP',
785             'shmctl' => 'LSTOP',
786             'shmget' => 'LSTOP',
787             'shmread' => 'LSTOP',
788             'shmwrite' => 'LSTOP',
789             'shutdown' => 'LSTOP',
790             'sin' => 'UNIOP',
791             'sleep' => 'UNIOP',
792             'socket' => 'LSTOP',
793             'socketpair' => 'LSTOP',
794             'sort' => 'LSTOP',
795             'splice' => 'LSTOP',
796             'split' => 'LSTOP',
797             'sprintf' => 'LSTOP',
798             'sqrt' => 'UNIOP',
799             'srand' => 'UNIOP',
800             'stat' => 'UNIOP',
801             'state' => 'MY',
802             'study' => 'UNIOP',
803             'sub' => 'SUB',
804             'substr' => 'LSTOP',
805             'symlink' => 'LSTOP',
806             'syscall' => 'LSTOP',
807             'sysopen' => 'LSTOP',
808             'sysread' => 'LSTOP',
809             'sysseek' => 'LSTOP',
810             'system' => 'LSTOP',
811             'syswrite' => 'LSTOP',
812             'tell' => 'UNIOP',
813             'telldir' => 'UNIOP',
814             'tie' => 'LSTOP',
815             'tied' => 'UNIOP',
816             'time' => 'FUNC0',
817             'times' => 'FUNC0',
818             'tr' => 'QUOTEABLE -- TO BE DETERMINED',
819             'truncate' => 'LSTOP',
820             'uc' => 'UNIOP',
821             'ucfirst' => 'UNIOP',
822             'umask' => 'UNIOP',
823             'undef' => 'UNIOP',
824             'undef' => 'UNIOP',
825             'unless' => 'UNLESS',
826             'unlink' => 'LSTOP',
827             'unpack' => 'LSTOP',
828             'unshift' => 'LSTOP',
829             'untie' => 'UNIOP',
830             'until' => 'UNTIL',
831             'use' => 'USE',
832             'utime' => 'LSTOP',
833             'values' => 'UNIOP',
834             'vec' => 'LSTOP',
835             'wait' => 'FUNC0',
836             'waitpid' => 'LSTOP',
837             'wantarray' => 'FUNC0',
838             'warn' => 'LSTOP',
839             'when' => 'WHEN',
840             'while' => 'WHILE',
841             'write' => 'UNIOP',
842             'y' => 'QUOTEABLE -- TO BE DETERMINED',
843             );
844              
845             ## use critic
846              
847             sub Marpa::PP::Perl::new {
848 2     2 0 779 my ( $class, $gen_closure ) = @_;
849              
850 2         7 my %symbol = ();
851 2         5 my @rules;
852             my %closure;
853 0         0 my $has_ranking_action;
854              
855             LINE:
856 2         277 for my $line ( split /\n/xms, $reference_grammar ) {
857 848         5702 chomp $line;
858 848         2125 $line =~ s/ [#] .* \z //xms;
859 848         1968 $line =~ s/ [\/][*] .* \z //xms;
860 848         1317 $line =~ s/ \A \s+ //xms;
861 848 100       2013 next LINE if $line eq q{};
862 446 50       1889 Carp::croak("Misformed line: $line")
863             if $line !~ / [:][:][=] .* [;] \s* \z /xms;
864 446         1714 my ($action_name) = ( $line =~ /\A (\w+) \s* [:] [^:] /gxms );
865 446         12002 my ( $lhs, $rhs_string ) =
866             ( $line =~ / \s* (\w+) \s* [:][:][=] \s* (.*) [;] \s* \z/xms );
867 446   66     1203 my @rhs = map { $symbol_name{$_} // $_ } split q{ }, $rhs_string;
  1072         6080  
868              
869 446         1128 for my $symbol ( $lhs, @rhs ) {
870 1518   100     7014 $symbol{$symbol} //= 0;
871 1518 50       4581 if ( $symbol =~ /\W/xms ) {
872 0         0 Carp::croak("Misformed symbol: $symbol");
873             }
874             } ## end for my $symbol ( $lhs, @rhs )
875 446         700 $symbol{$lhs}++;
876              
877             # only create action for non-empty rules
878 446         636 my @action_arg = ();
879 446 100       924 if ( scalar @rhs ) {
880 416   66     2194 $action_name ||= 'MyAction::rule_' . scalar @rules;
881 416         2267 my ( $action, $ranking_action ) =
882             $gen_closure->( $lhs, \@rhs, $action_name );
883 416 100       10716 if ( defined $action ) {
884 208         617 $closure{"!$action_name"} = $action;
885 208         462 push @action_arg, action => "!$action_name";
886             }
887 416 100       1071 if ( defined $ranking_action ) {
888 2         10 $closure{"!r!$action_name"} = $ranking_action;
889 2         20 push @action_arg, ranking_action => "!r!$action_name";
890 2         4 $has_ranking_action++;
891             }
892             } ## end if ( scalar @rhs )
893 446         11625 push @rules, { lhs => $lhs, rhs => \@rhs, @action_arg };
894             } ## end for my $line ( split /\n/xms, $reference_grammar )
895              
896 2         162 my $grammar = Marpa::PP::Grammar->new(
897             { start => 'prog',
898             rules => \@rules,
899             lhs_terminals => 0,
900             strip => 0
901             }
902             );
903              
904 2         22 $grammar->precompute();
905              
906 2         511 return bless {
907             grammar => $grammar,
908             closure => \%closure,
909             has_ranking_action => $has_ranking_action
910             }, $class;
911              
912             } ## end sub Marpa::PP::Perl::new
913              
914             my @RECCE_NAMED_ARGUMENTS =
915             qw(trace_tasks trace_terminals trace_values trace_actions);
916              
917             sub token_not_accepted {
918 0     0   0 my ( $ppi_token, $token_name, $token_value, $length ) = @_;
919 0         0 local $Data::Dumper::Maxdepth = 2;
920 0         0 local $Data::Dumper::Terse = 1;
921 0 0       0 say {*STDERR} $Marpa::PP::Perl::RECOGNIZER->show_progress()
  0         0  
922             or die "say: $ERRNO";
923 0         0 my $perl_token_desc;
924 0 0       0 if ( not defined $token_name ) {
925 0         0 $perl_token_desc = 'Undefined Perl token was not accepted: ';
926             }
927             else {
928 0         0 $perl_token_desc = qq{Perl token "$token_name" was not accepted: };
929             }
930 0 0 0     0 if ( defined $length and $length != 1 ) {
931 0         0 $perl_token_desc .= ' length=' . $length;
932             }
933 0         0 $perl_token_desc .= Data::Dumper::Dumper($token_value);
934 0         0 Carp::croak(
935             "$perl_token_desc", 'PPI token is ',
936             ( ref $ppi_token ), q{: },
937             $ppi_token->logical_filename(), q{:},
938             $ppi_token->logical_line_number(), q{:},
939             $ppi_token->column_number(), q{, },
940             q{content="}, $ppi_token->content(),
941             q{"}
942             );
943             } ## end sub token_not_accepted
944              
945             sub unknown_ppi_token {
946 0     0   0 my ($ppi_token) = @_;
947 0         0 die 'Failed at Token: ', Data::Dumper::Dumper($ppi_token),
948             'Marpa::PP::Perl did not know how to process token',
949             Marpa::PP::Perl::default_show_location($ppi_token), "\n";
950             } ## end sub unknown_ppi_token
951              
952             sub Marpa::PP::Perl::parse {
953              
954 16     16 0 168430 my ( $parser, $input, $hash_arg ) = @_;
955              
956 16   50     152 $hash_arg //= {};
957              
958 16         54 my @recce_args = ();
959 16         39 HASH_ARG: while ( my ( $arg, $value ) = each %{$hash_arg} ) {
  16         112  
960 0 0       0 if ( $arg ~~ \@RECCE_NAMED_ARGUMENTS ) {
961 0         0 push @recce_args, $arg, $value;
962 0         0 next HASH_ARG;
963             }
964 0         0 Carp::croak("Unknown hash arg: $arg");
965             } ## end while ( my ( $arg, $value ) = each %{$hash_arg} )
966              
967 16         75 my $grammar = $parser->{grammar};
968 16 100       93 $parser->{has_ranking_action}
969             and push @recce_args, ranking_method => 'constant';
970              
971 16         233 my $recce = Marpa::PP::Recognizer->new(
972             { grammar => $grammar,
973             mode => 'stream',
974             closures => $parser->{closure},
975             @recce_args
976             }
977             );
978              
979             # This is convenient for making the recognizer available to
980             # error messages
981 16         74 local $Marpa::PP::Perl::RECOGNIZER = $recce;
982              
983 16         187 my $document = PPI::Document->new($input);
984 16         191067 $document->index_locations();
985 16         56788 my @PPI_tokens = $document->tokens();
986 16         4473 my @earleme_to_PPI_token;
987             my $perl_type;
988              
989 16         68 local $Marpa::PP::Perl::Internal::CONTEXT =
990             [ \@PPI_tokens, \@earleme_to_PPI_token ];
991             TOKEN:
992 16         97 for (
993             my $PPI_token_ix = 0;
994             $PPI_token_ix <= $#PPI_tokens;
995             $PPI_token_ix++
996             )
997             {
998 943         4721 my $current_earleme = $recce->current_earleme();
999 943   100     5988 $earleme_to_PPI_token[$current_earleme] //= $PPI_token_ix;
1000 943         5012 my $token = $PPI_tokens[$PPI_token_ix];
1001 943         4444 my $PPI_type = ref $token;
1002 943 100       4074 next TOKEN if $PPI_type eq 'PPI::Token::Whitespace';
1003 637 50       1539 next TOKEN if $PPI_type eq 'PPI::Token::Comment';
1004 637         1663 my $last_perl_type = $perl_type;
1005 637         1085 $perl_type = undef;
1006              
1007 637 100       1965 if ( $PPI_type eq 'PPI::Token::Symbol' ) {
1008 71         1181 my ( $sigil, $word ) =
1009             ( $token->{content} =~ / \A ([\$]) (\w*) \z /xms );
1010 71 50 33     701 if ( not defined $sigil or $sigil ne q{$} ) {
1011 0         0 Carp::croak( 'Unknown symbol type: ',
1012             Data::Dumper::Dumper($token) );
1013 0         0 next TOKEN;
1014             }
1015 71 50       475 defined $recce->read( 'DOLLAR', $sigil )
1016             or token_not_accepted( $token, 'DOLLAR', $sigil );
1017 71 50       357 defined $recce->read( 'WORD', $word )
1018             or token_not_accepted( $token, 'WORD', $word );
1019 71         521 next TOKEN;
1020             } ## end if ( $PPI_type eq 'PPI::Token::Symbol' )
1021              
1022 566 100       1524 if ( $PPI_type eq 'PPI::Token::Cast' ) {
1023 30         1276 my $content = $token->{content};
1024 30         53 my $token_found;
1025 30         156 for my $cast ( split //xms, $content ) {
1026 30         92 $perl_type = $perl_type_by_cast{$content};
1027 30 50       96 if ( not defined $perl_type ) {
1028 0         0 die qq{Unknown $PPI_type: "$content":},
1029             Marpa::PP::Perl::default_show_location($token),
1030             "\n";
1031             }
1032 30         55 $token_found = 1;
1033 30 50       164 defined $recce->read( $perl_type, $cast )
1034             or token_not_accepted( $token, $perl_type, $cast );
1035             } ## end for my $cast ( split //xms, $content )
1036 30 50       101 defined $token_found or unknown_ppi_token($token);
1037 30         150 next TOKEN;
1038             } ## end if ( $PPI_type eq 'PPI::Token::Cast' )
1039              
1040 536 100       1182 if ( $PPI_type eq 'PPI::Token::Word' ) {
1041 18         73 my $content = $token->{content};
1042 18   50     99 $perl_type = $perl_type_by_word{$content} // 'WORD';
1043 18 50       106 defined $recce->read( $perl_type, $content )
1044             or token_not_accepted( $token, $perl_type, $content );
1045 18         105 next TOKEN;
1046             } ## end if ( $PPI_type eq 'PPI::Token::Word' )
1047              
1048 518 100       2041 if ( $PPI_type eq 'PPI::Token::Operator' ) {
1049 123         497 my $content = $token->{content};
1050 123         441 $perl_type = $perl_type_by_op{$content};
1051 123 50       304 if ( not defined $perl_type ) {
1052 0         0 die qq{Unknown $PPI_type: "$content":},
1053             Marpa::PP::Perl::default_show_location($token),
1054             "\n";
1055             }
1056 123 100       392 if ( $perl_type eq 'PLUS' ) {
1057              
1058             # Apply the "ruby slippers"
1059             # Make the plus sign be whatever the parser
1060             # wishes it was
1061 1         5 my @potential_types = qw(ADDOP PLUS);
1062 1         6 my $expected_tokens = $recce->terminals_expected();
1063 1         3 my $token_found;
1064 1         3 TYPE: for my $type (@potential_types) {
1065 2 100       19 next TYPE if not $type ~~ $expected_tokens;
1066 1         3 $token_found = 1;
1067 1 50       6 defined $recce->alternative( $type, $content, 1 )
1068             or token_not_accepted( $token, $type, $content, 1 );
1069             } ## end for my $type (@potential_types)
1070 1 50       5 defined $token_found or unknown_ppi_token($token);
1071 1         6 $recce->earleme_complete();
1072 1         10 next TOKEN;
1073             } ## end if ( $perl_type eq 'PLUS' )
1074 122 50       300 if ( $perl_type eq 'MINUS' ) {
1075              
1076             # Apply the "ruby slippers"
1077             # Make the plus sign be whatever the parser
1078             # wishes it was
1079 0         0 my $expected_tokens = $recce->terminals_expected();
1080 0         0 my @potential_types = qw(ADDOP UMINUS);
1081 0         0 my $token_found;
1082 0         0 TYPE: for my $type (@potential_types) {
1083 0 0       0 next TYPE if not $type ~~ $expected_tokens;
1084 0         0 $token_found = 1;
1085 0 0       0 defined $recce->alternative( $type, $content, 1 )
1086             or token_not_accepted( $token, $type, $content, 1 );
1087             } ## end for my $type (@potential_types)
1088 0 0       0 defined $token_found or unknown_ppi_token($token);
1089 0         0 $recce->earleme_complete();
1090 0         0 next TOKEN;
1091             } ## end if ( $perl_type eq 'MINUS' )
1092 122 50       652 defined $recce->read( $perl_type, $content )
1093             or token_not_accepted( $token, $perl_type, $content );
1094 122         3024 next TOKEN;
1095             } ## end if ( $PPI_type eq 'PPI::Token::Operator' )
1096              
1097 395 100       1232 if ( $PPI_type eq 'PPI::Token::Structure' ) {
1098 282         1066 my $content = $token->{content};
1099 282         971 $perl_type = $perl_type_by_structure{$content};
1100 282         1490 my $expected_tokens = $recce->terminals_expected();
1101 282 50       742 if ( not defined $perl_type ) {
1102 0         0 die qq{Unknown $PPI_type: "$content":},
1103             Marpa::PP::Perl::default_show_location($token),
1104             "\n";
1105             }
1106 282 100       897 if ( $perl_type eq 'RCURLY' ) {
1107 65 50 66     749 if (( not defined $last_perl_type
      33        
1108             or $last_perl_type ne 'SEMI'
1109             )
1110             and 'SEMI' ~~ $expected_tokens
1111             )
1112             {
1113 65 50       403 defined $recce->read( 'SEMI', q{;} )
1114             or token_not_accepted( $token, 'SEMI', q{;} );
1115             } ## end if ( ( not defined $last_perl_type or ...))
1116 65 50       378 defined $recce->read( $perl_type, $content )
1117             or token_not_accepted( $token, $perl_type, $content );
1118 65         833 next TOKEN;
1119             } ## end if ( $perl_type eq 'RCURLY' )
1120 217 100       689 if ( $perl_type eq 'LCURLY' ) {
1121 65         188 my @potential_types = ();
1122 65         136 push @potential_types, 'LCURLY';
1123 65 100 100     528 if ( not defined $last_perl_type
1124             or $last_perl_type ne 'DO' )
1125             {
1126 58         145 push @potential_types, 'HASHBRACK';
1127             }
1128 65         157 my $token_found;
1129 65         154 TYPE: for my $type (@potential_types) {
1130 123 100       811 next TYPE if not $type ~~ $expected_tokens;
1131 72         128 $token_found = 1;
1132 72 50       314 defined $recce->alternative( $type, $content, 1 )
1133             or token_not_accepted( $token, $type, $content, 1 );
1134             } ## end for my $type (@potential_types)
1135 65 50       205 defined $token_found or unknown_ppi_token($token);
1136 65         695 $recce->earleme_complete();
1137 65         654 next TOKEN;
1138             } ## end if ( $perl_type eq 'LCURLY' )
1139 152 50       795 defined $recce->read( $perl_type, $content )
1140             or token_not_accepted( $token, $perl_type, $content );
1141 152         1549 next TOKEN;
1142             } ## end if ( $PPI_type eq 'PPI::Token::Structure' )
1143              
1144 113 100       325 if ( $PPI_type eq 'PPI::Token::Number' ) {
1145 59         168 my $content = $token->{content};
1146 59 50       376 defined $recce->read( 'THING', $content + 0 )
1147             or token_not_accepted( $token, 'THING', $content + 0 );
1148 59         385 next TOKEN;
1149             } ## end if ( $PPI_type eq 'PPI::Token::Number' )
1150 54 50       191 if ( $PPI_type eq 'PPI::Token::Quote::Single' ) {
1151 54         261 my $content = $token->{content};
1152             ## no critic (BuiltinFunctions::ProhibitStringyEval)
1153 54         7166 my $string = eval $content;
1154             ## use critic
1155 54 50       503 Carp::Croak("eval failed: $EVAL_ERROR")
1156             if not defined $string;
1157 54 50       568 defined $recce->read( 'THING', $string )
1158             or token_not_accepted( $token, 'THING', $string );
1159 54         660 next TOKEN;
1160             } ## end if ( $PPI_type eq 'PPI::Token::Quote::Single' )
1161              
1162 0         0 unknown_ppi_token($token);
1163              
1164             } ## end for ( my $PPI_token_ix = 0; $PPI_token_ix <= $#PPI_tokens...)
1165              
1166 16         108 $recce->end_input();
1167 16 100       57 if (wantarray) {
1168 4         8 my @values = ();
1169 4         31 while ( defined( my $value_ref = $recce->value() ) ) {
1170 0         0 push @values, ${$value_ref};
  0         0  
1171             }
1172 4         120 return @values;
1173             } ## end if (wantarray)
1174             else {
1175 12         119 my $value_ref = $recce->value();
1176 12         1149 return $value_ref;
1177             }
1178              
1179             } ## end sub Marpa::PP::Perl::parse
1180              
1181             # Context-sensitive callback for
1182             # application-provided closures to use.
1183             sub Marpa::PP::Perl::token {
1184 58 50   58 0 654 Marpa::PP::exception('No Perl context for token callback')
1185             if not my $context = $Marpa::PP::Perl::Internal::CONTEXT;
1186 58         61 my ( $PPI_tokens, $earleme_to_token ) = @{$context};
  58         102  
1187 58         195 my $earleme = Marpa::PP::location();
1188 58         279 return $PPI_tokens->[ $earleme_to_token->[$earleme] ];
1189             } ## end sub Marpa::PP::Perl::token
1190              
1191             sub Marpa::PP::Perl::default_show_location {
1192 0     0 0   my ($token) = @_;
1193 0           my $file_name = $token->logical_filename();
1194 0 0         my $file_description = $file_name ? qq{ file "$file_name"} : q{};
1195             return
1196 0           "$file_description at line "
1197             . $token->logical_line_number()
1198             . q{, column }
1199             . $token->column_number();
1200             } ## end sub Marpa::PP::Perl::default_show_location
1201              
1202             1;