-
Notifications
You must be signed in to change notification settings - Fork 1
/
HLL-s0.pir
6713 lines (6267 loc) · 180 KB
/
HLL-s0.pir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# $Id$
=head1 NAME
HLL - Parrot HLL library
=head1 DESCRIPTION
This file brings together the various modules needed for HLL::Compiler
and HLL::Grammar.
=cut
.sub '' :anon :load :init
load_bytecode 'Regex.pbc'
.end
### .include 'src/cheats/hll-compiler.pir'
# we have to overload PCT::HLLCompiler's parse method to support P6Regex grammars
.namespace ['HLL';'Compiler']
.sub 'parse' :method
.param pmc source
.param pmc options :slurpy :named
.local string tcode
tcode = options['transcode']
unless tcode goto transcode_done
.local pmc tcode_it
$P0 = split ' ', tcode
tcode_it = iter $P0
tcode_loop:
unless tcode_it goto transcode_done
tcode = shift tcode_it
push_eh tcode_enc
$I0 = find_charset tcode
$S0 = source
$S0 = trans_charset $S0, $I0
assign source, $S0
pop_eh
goto transcode_done
tcode_enc:
pop_eh
push_eh tcode_fail
$I0 = find_encoding tcode
$S0 = source
$S0 = trans_encoding $S0, $I0
assign source, $S0
pop_eh
goto transcode_done
tcode_fail:
pop_eh
goto tcode_loop
transcode_done:
.local pmc parsegrammar, parseactions, match
parsegrammar = self.'parsegrammar'()
null parseactions
$S0 = options['target']
if $S0 == 'parse' goto have_parseactions
parseactions = self.'parseactions'()
have_parseactions:
.local int rxtrace
rxtrace = options['parsetrace']
match = parsegrammar.'parse'(source, 'p'=>0, 'actions'=>parseactions, 'rxtrace'=>rxtrace)
unless match goto err_parsefail
.return (match)
err_parsefail:
self.'panic'('Unable to parse source')
.return (match)
.end
.sub 'pir' :method
.param pmc source
.param pmc adverbs :slurpy :named
$P0 = compreg 'POST'
$S0 = $P0.'to_pir'(source, adverbs :flat :named)
.return ($S0)
.end
.sub 'parse_name' :method
.param string name
# split name on ::
.local pmc ns
ns = split '::', name
# move any leading sigil to the last item
.local string sigil
$S0 = ns[0]
sigil = substr $S0, 0, 1
$I0 = index '$@%&', sigil
if $I0 < 0 goto sigil_done
substr $S0, 0, 1, ''
ns[0] = $S0
$S0 = ns[-1]
$S0 = concat sigil, $S0
ns[-1] = $S0
sigil_done:
# remove any empty items from the list
.local pmc ns_it
ns_it = iter ns
ns = new ['ResizablePMCArray']
ns_loop:
unless ns_it goto ns_done
$S0 = shift ns_it
unless $S0 > '' goto ns_loop
push ns, $S0
goto ns_loop
ns_done:
# return the result
.return (ns)
.end
### .include 'src/cheats/hll-grammar.pir'
# Copyright (C) 2009, The Perl Foundation.
=head1 TITLE
src/cheats/hll-grammar.pir -- Additional HLL::Grammar methods
=head2 Methods
=over 4
=cut
.include 'cclass.pasm'
### .include 'src/Regex/constants.pir'
.const int CURSOR_FAIL = -1
.const int CURSOR_FAIL_GROUP = -2
.const int CURSOR_FAIL_RULE = -3
.const int CURSOR_FAIL_MATCH = -4
.const int CURSOR_TYPE_SCAN = 1
.const int CURSOR_TYPE_PEEK = 2
.namespace ['HLL';'Grammar']
.sub '' :load :init
.local pmc brackets
brackets = box unicode:"<>[](){}\xab\xbb\u0f3a\u0f3b\u0f3c\u0f3d\u169b\u169c\u2045\u2046\u207d\u207e\u208d\u208e\u2329\u232a\u2768\u2769\u276a\u276b\u276c\u276d\u276e\u276f\u2770\u2771\u2772\u2773\u2774\u2775\u27c5\u27c6\u27e6\u27e7\u27e8\u27e9\u27ea\u27eb\u2983\u2984\u2985\u2986\u2987\u2988\u2989\u298a\u298b\u298c\u298d\u298e\u298f\u2990\u2991\u2992\u2993\u2994\u2995\u2996\u2997\u2998\u29d8\u29d9\u29da\u29db\u29fc\u29fd\u3008\u3009\u300a\u300b\u300c\u300d\u300e\u300f\u3010\u3011\u3014\u3015\u3016\u3017\u3018\u3019\u301a\u301b\u301d\u301e\ufd3e\ufd3f\ufe17\ufe18\ufe35\ufe36\ufe37\ufe38\ufe39\ufe3a\ufe3b\ufe3c\ufe3d\ufe3e\ufe3f\ufe40\ufe41\ufe42\ufe43\ufe44\ufe47\ufe48\ufe59\ufe5a\ufe5b\ufe5c\ufe5d\ufe5e\uff08\uff09\uff3b\uff3d\uff5b\uff5d\uff5f\uff60\uff62\uff63"
set_global '$!brackets', brackets
.end
.namespace ['HLL';'Grammar']
=item O(spec [, save])
This subrule attaches operator precedence information to
a match object (such as an operator token). A typical
invocation for the subrule might be:
token infix:sym<+> { <sym> <O( q{ %additive, :pirop<add> } )> }
This says to add all of the attribute of the C<%additive> hash
(described below) and a C<pirop> entry into the match object
returned by the C<< infix:sym<+> >> token (as the C<O> named
capture). Note that this is a alphabetic 'O", not a digit zero.
Currently the C<O> subrule accepts a string argument describing
the hash to be stored. (Note the C< q{ ... } > above. Eventually
it may be possible to omit the 'q' such that an actual (constant)
hash constructor is passed as an argument to C<O>.
The hash built via the string argument to C<O> is cached, so that
subsequent parses of the same token re-use the hash built from
previous parses of the token, rather than building a new hash
on each invocation.
The C<save> argument is used to build "hash" aggregates that can
be referred to by subsequent calls to C<O>. For example,
NQP::Grammar.O(':prec<t=>, :assoc<left>', '%additive' );
specifies the values to be associated with later references to
"%additive". Eventually it will likely be possible to use true
hashes from a package namespace, but this works for now.
Currently the only pairs recognized have the form C< :pair >,
C< :!pair >, and C<< :pair<strval> >>.
=cut
.sub 'O' :method
.param string spec
.param string save :optional
.param int has_save :opt_flag
# First, get the hash cache. Right now we have one
# cache for all grammars; eventually we may need a way to
# separate them out by cursor type.
.local pmc ohash
ohash = get_global '%!ohash'
unless null ohash goto have_ohash
ohash = new ['Hash']
set_global '%!ohash', ohash
have_ohash:
# See if we've already created a Hash for the current
# specification string -- if so, use that.
.local pmc hash
hash = ohash[spec]
unless null hash goto hash_done
# Otherwise, we need to build a new one.
hash = new ['Hash']
.local int pos, eos
pos = 0
eos = length spec
spec_loop:
pos = find_not_cclass .CCLASS_WHITESPACE, spec, pos, eos
if pos >= eos goto spec_done
$S0 = substr spec, pos, 1
if $S0 == ',' goto spec_comma
if $S0 == ':' goto spec_pair
# If whatever we found doesn't start with a colon, treat it
# as a lookup of a previously saved hash to be merged in.
.local string lookup
.local int lpos
# Find the first whitespace or comma
lpos = find_cclass .CCLASS_WHITESPACE, spec, pos, eos
$I0 = index spec, ',', pos
if $I0 < 0 goto have_lookup_lpos
if $I0 >= lpos goto have_lookup_lpos
lpos = $I0
have_lookup_lpos:
$I0 = lpos - pos
lookup = substr spec, pos, $I0
.local pmc lhash, lhash_it
lhash = ohash[lookup]
if null lhash goto err_lookup
lhash_it = iter lhash
lhash_loop:
unless lhash_it goto lhash_done
$S0 = shift lhash_it
$P0 = lhash[$S0]
hash[$S0] = $P0
goto lhash_loop
lhash_done:
pos = lpos
goto spec_loop
# We just ignore commas between elements for now.
spec_comma:
inc pos
goto spec_loop
# If we see a colon, then we want to parse whatever
# comes next like a pair.
spec_pair:
# eat colon
inc pos
.local string name
.local pmc value
value = new ['Boolean']
# If the pair is of the form :!name, then reverse the value
# and skip the colon.
$S0 = substr spec, pos, 1
$I0 = iseq $S0, '!'
pos += $I0
$I0 = not $I0
value = $I0
# Get the name of the pair.
lpos = find_not_cclass .CCLASS_WORD, spec, pos, eos
$I0 = lpos - pos
name = substr spec, pos, $I0
pos = lpos
# Look for a <...> that follows.
$S0 = substr spec, pos, 1
unless $S0 == '<' goto have_value
inc pos
lpos = index spec, '>', pos
$I0 = lpos - pos
$S0 = substr spec, pos, $I0
value = box $S0
pos = lpos + 1
have_value:
# Done processing the pair, store it in the hash.
hash[name] = value
goto spec_loop
spec_done:
# Done processing the spec string, cache the hash for later.
ohash[spec] = hash
hash_done:
# If we've been called as a subrule, then build a pass-cursor
# to indicate success and set the hash as the subrule's match object.
if has_save goto save_hash
($P0, $I0) = self.'!cursor_start'()
$P0.'!cursor_pass'($I0, '')
setattribute $P0, '$!match', hash
.return ($P0)
# save the hash under a new entry
save_hash:
ohash[save] = hash
.return (self)
err_lookup:
self.'panic'('Unknown operator precedence specification "', lookup, '"')
.end
=item panic([args :slurpy])
Throw an exception at the current cursor location. If the message
doesn't end with a newline, also output the line number and offset
of the match.
=cut
.sub 'panic' :method
.param pmc args :slurpy
.local int pos
.local pmc target
pos = self.'pos'()
target = getattribute self, '$!target'
$I1 = target.'lineof'(pos)
inc $I1
push args, ' at line '
push args, $I1
$S0 = target
$S0 = substr $S0, pos, 10
$S0 = escape $S0
push args, ', near "'
push args, $S0
push args, '"'
.local string message
message = join '', args
die message
.end
=item peek_delimiters(target, pos)
Return the start/stop delimiter pair based on peeking at C<target>
position C<pos>.
=cut
.sub 'peek_delimiters' :method
.param string target
.param int pos
.local string brackets, start, stop
$P0 = get_global '$!brackets'
brackets = $P0
# peek at the next character
start = substr target, pos, 1
# colon and word characters aren't valid delimiters
if start == ':' goto err_colon_delim
$I0 = is_cclass .CCLASS_WORD, start, 0
if $I0 goto err_word_delim
$I0 = is_cclass .CCLASS_WHITESPACE, start, 0
if $I0 goto err_ws_delim
# assume stop delim is same as start, for the moment
stop = start
# see if we have an opener or closer
$I0 = index brackets, start
if $I0 < 0 goto bracket_end
# if it's a closing bracket, that's an error also
$I1 = $I0 % 2
if $I1 goto err_close
# it's an opener, so get the closing bracket
inc $I0
stop = substr brackets, $I0, 1
# see if the opening bracket is repeated
.local int len
len = 0
bracket_loop:
inc pos
inc len
$S0 = substr target, pos, 1
if $S0 == start goto bracket_loop
if len == 1 goto bracket_end
start = repeat start, len
stop = repeat stop, len
bracket_end:
.return (start, stop, pos)
err_colon_delim:
self.'panic'('Colons may not be used to delimit quoting constructs')
err_word_delim:
self.'panic'('Alphanumeric character is not allowed as a delimiter')
err_ws_delim:
self.'panic'('Whitespace character is not allowed as a delimiter')
err_close:
self.'panic'('Use of a closing delimiter for an opener is reserved')
.end
.sub 'quote_EXPR' :method
.param pmc args :slurpy
.local pmc quotemod, true
.lex '%*QUOTEMOD', quotemod
quotemod = new ['Hash']
true = box 1
args_loop:
unless args goto args_done
.local string mod
mod = shift args
mod = substr mod, 1
quotemod[mod] = true
if mod == 'qq' goto opt_qq
if mod == 'b' goto opt_b
goto args_loop
opt_qq:
quotemod['s'] = true
quotemod['a'] = true
quotemod['h'] = true
quotemod['f'] = true
quotemod['c'] = true
quotemod['b'] = true
opt_b:
quotemod['q'] = true
goto args_loop
args_done:
.local pmc cur
.local string target
.local int pos
(cur, pos, target) = self.'!cursor_start'()
.local pmc start, stop
(start, stop) = self.'peek_delimiters'(target, pos)
.lex '$*QUOTE_START', start
.lex '$*QUOTE_STOP', stop
$P10 = cur.'quote_delimited'()
unless $P10 goto fail
cur.'!mark_push'(0, CURSOR_FAIL, 0, $P10)
$P10.'!cursor_names'('quote_delimited')
pos = $P10.'pos'()
cur.'!cursor_pass'(pos, 'quote_EXPR')
fail:
.return (cur)
.end
.sub 'quotemod_check' :method
.param string mod
$P0 = find_dynamic_lex '%*QUOTEMOD'
$P1 = $P0[mod]
unless null $P1 goto done
$P1 = new ['Undef']
done:
.return ($P1)
.end
.sub 'starter' :method
.local pmc cur
.local string target, start
.local int pos
(cur, pos, target) = self.'!cursor_start'()
$P0 = find_dynamic_lex '$*QUOTE_START'
if null $P0 goto fail
start = $P0
$I0 = length start
$S0 = substr target, pos, $I0
unless $S0 == start goto fail
pos += $I0
cur.'!cursor_pass'(pos, 'starter')
fail:
.return (cur)
.end
.sub 'stopper' :method
.local pmc cur
.local string target, stop
.local int pos
(cur, pos, target) = self.'!cursor_start'()
$P0 = find_dynamic_lex '$*QUOTE_STOP'
if null $P0 goto fail
stop = $P0
$I0 = length stop
$S0 = substr target, pos, $I0
unless $S0 == stop goto fail
pos += $I0
cur.'!cursor_pass'(pos, 'stopper')
fail:
.return (cur)
.end
.sub 'split_words' :method
.param string words
.local int pos, eos
.local pmc result
pos = 0
eos = length words
result = new ['ResizablePMCArray']
split_loop:
pos = find_not_cclass .CCLASS_WHITESPACE, words, pos, eos
unless pos < eos goto split_done
$I0 = find_cclass .CCLASS_WHITESPACE, words, pos, eos
$I1 = $I0 - pos
$S0 = substr words, pos, $I1
push result, $S0
pos = $I0
goto split_loop
split_done:
.return (result)
.end
=item EXPR(...)
An operator precedence parser.
=cut
.sub 'EXPR' :method
.param string preclim :optional
.param int has_preclim :opt_flag
if has_preclim goto have_preclim
preclim = ''
have_preclim:
.const 'Sub' reduce = 'EXPR_reduce'
.local string termishrx
termishrx = 'termish'
.local pmc opstack, termstack
opstack = new ['ResizablePMCArray']
.lex '@opstack', opstack
termstack = new ['ResizablePMCArray']
.lex '@termstack', termstack
.local pmc here, from, pos
(here, pos) = self.'!cursor_start'()
term_loop:
here = here.termishrx()
unless here goto fail
.local pmc termish
termish = here.'MATCH'()
# interleave any prefix/postfix we might have found
.local pmc termOPER, prefixish, postfixish
termOPER = termish
termOPER_loop:
$I0 = exists termOPER['OPER']
unless $I0 goto termOPER_done
termOPER = termOPER['OPER']
goto termOPER_loop
termOPER_done:
prefixish = termOPER['prefixish']
postfixish = termOPER['postfixish']
if null prefixish goto prefix_done
prepostfix_loop:
unless prefixish goto prepostfix_done
unless postfixish goto prepostfix_done
.local pmc preO, postO
.local string preprec, postprec
$P0 = prefixish[0]
$P0 = $P0['OPER']
preO = $P0['O']
preprec = preO['prec']
$P0 = postfixish[-1]
$P0 = $P0['OPER']
postO = $P0['O']
postprec = postO['prec']
if postprec < preprec goto post_shift
if postprec > preprec goto pre_shift
$S0 = postO['uassoc']
if $S0 == 'right' goto pre_shift
post_shift:
$P0 = pop postfixish
push opstack, $P0
goto prepostfix_loop
pre_shift:
$P0 = shift prefixish
push opstack, $P0
goto prepostfix_loop
prepostfix_done:
prefix_loop:
unless prefixish goto prefix_done
$P0 = shift prefixish
push opstack, $P0
goto prefix_loop
prefix_done:
delete termish['prefixish']
postfix_loop:
if null postfixish goto postfix_done
unless postfixish goto postfix_done
$P0 = pop postfixish
push opstack, $P0
goto postfix_loop
postfix_done:
delete termish['postfixish']
$P0 = termish['term']
push termstack, $P0
# Now see if we can fetch an infix operator
.local pmc infixcur, infix
here = here.'ws'()
infixcur = here.'infixish'()
unless infixcur goto term_done
infix = infixcur.'MATCH'()
.local pmc inO
$P0 = infix['OPER']
inO = $P0['O']
termishrx = inO['nextterm']
if termishrx goto have_termishrx
termishrx = 'termish'
have_termishrx:
.local string inprec, inassoc, opprec
inprec = inO['prec']
unless inprec goto err_inprec
if inprec <= preclim goto term_done
inassoc = inO['assoc']
reduce_loop:
unless opstack goto reduce_done
$P0 = opstack[-1]
$P0 = $P0['OPER']
$P0 = $P0['O']
opprec = $P0['prec']
unless opprec > inprec goto reduce_gt_done
capture_lex reduce
self.reduce(termstack, opstack)
goto reduce_loop
reduce_gt_done:
unless opprec == inprec goto reduce_done
# equal precedence, use associativity to decide
unless inassoc == 'left' goto reduce_done
# left associative, reduce immediately
capture_lex reduce
self.reduce(termstack, opstack)
reduce_done:
push opstack, infix # The Shift
here = infixcur.'ws'()
goto term_loop
term_done:
opstack_loop:
unless opstack goto opstack_done
capture_lex reduce
self.reduce(termstack, opstack)
goto opstack_loop
opstack_done:
expr_done:
.local pmc term
term = pop termstack
pos = here.'pos'()
here = self.'!cursor_start'()
setattribute here, '$!pos', pos
setattribute here, '$!match', term
here.'!reduce'('EXPR')
fail:
.return (here)
err_internal:
$I0 = termstack
here.'panic'('Internal operator parser error, @termstack == ', $I0)
err_inprec:
infixcur.'panic'('Missing infixish operator precedence')
.end
.sub 'EXPR_reduce' :method :anon
.param pmc termstack
.param pmc opstack
.local pmc op, opOPER, opO
.local string opassoc
op = pop opstack
opOPER = op['OPER']
opO = opOPER['O']
opassoc = opO['assoc']
if opassoc == 'unary' goto op_unary
if opassoc == 'list' goto op_list
op_infix:
.local pmc right, left
right = pop termstack
left = pop termstack
op[0] = left
op[1] = right
$S0 = opO['reducecheck']
unless $S0 goto op_infix_1
self.$S0(op)
op_infix_1:
self.'!reduce'('EXPR', 'INFIX', op)
goto done
op_unary:
.local pmc arg, afrom, ofrom
arg = pop termstack
op[0] = arg
afrom = arg.'from'()
ofrom = op.'from'()
if afrom < ofrom goto op_postfix
op_prefix:
self.'!reduce'('EXPR', 'PREFIX', op)
goto done
op_postfix:
self.'!reduce'('EXPR', 'POSTFIX', op)
goto done
op_list:
.local string sym
sym = opOPER['sym']
arg = pop termstack
unshift op, arg
op_sym_loop:
unless opstack goto op_sym_done
$P0 = opstack[-1]
$P0 = $P0['OPER']
$S0 = $P0['sym']
if sym != $S0 goto op_sym_done
arg = pop termstack
unshift op, arg
$P0 = pop opstack
goto op_sym_loop
op_sym_done:
arg = pop termstack
unshift op, arg
self.'!reduce'('EXPR', 'LIST', op)
goto done
done:
push termstack, op
.end
.sub 'ternary' :method
.param pmc match
$P0 = match[1]
$P1 = match['infix']
$P1 = $P1['EXPR']
match[1] = $P1
match[2] = $P0
.end
.sub 'MARKER' :method
.param pmc markname
.local pmc pos
pos = self.'pos'()
self.'!cursor_debug'('START MARKER name=', markname, ', pos=', pos)
.local pmc markhash
markhash = get_global '%!MARKHASH'
unless null markhash goto have_markhash
markhash = new ['Hash']
set_global '%!MARKHASH', markhash
have_markhash:
markhash[markname] = pos
self.'!cursor_debug'('PASS MARKER')
.return (1)
.end
.sub 'MARKED' :method
.param pmc markname
self.'!cursor_debug'('START MARKED name=', markname)
.local pmc markhash
markhash = get_global '%!MARKHASH'
if null markhash goto fail
$P0 = markhash[markname]
if null $P0 goto fail
$P1 = self.'pos'()
unless $P0 == $P1 goto fail
self.'!cursor_debug'('PASS MARKED')
.return (1)
fail:
self.'!cursor_debug'('FAIL MARKED')
.return (0)
.end
.sub 'LANG' :method
.param string lang
.param string regex
.local pmc langhash, cur, pos
langhash = find_dynamic_lex '%*LANG'
$P0 = langhash[lang]
(cur, pos) = self.'!cursor_start'($P0)
cur.'!cursor_pos'(pos)
$S0 = concat lang, '-actions'
$P0 = langhash[$S0]
.lex '$*ACTIONS', $P0
# XXX can't use tailcall here or we lose $*ACTIONS
$P1 = cur.regex()
.return ($P1)
.end
=back
=cut
# Local Variables:
# mode: pir
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4 ft=pir:
### .include 'gen/hllgrammar-grammar.pir'
.namespace []
.sub "_block11" :anon :subid("10_1267204683.33533")
.annotate "line", 0
get_hll_global $P14, ["HLL";"Grammar"], "_block13"
capture_lex $P14
.annotate "line", 5
get_hll_global $P14, ["HLL";"Grammar"], "_block13"
capture_lex $P14
$P296 = $P14()
.annotate "line", 1
.return ($P296)
.end
.namespace []
.sub "" :load :init :subid("post94") :outer("10_1267204683.33533")
.annotate "line", 0
.const 'Sub' $P12 = "10_1267204683.33533"
.local pmc block
set block, $P12
$P297 = get_root_global ["parrot"], "P6metaclass"
$P297."new_class"("HLL::Grammar", "Regex::Cursor" :named("parent"))
.end
.namespace ["HLL";"Grammar"]
.sub "_block13" :subid("11_1267204683.33533") :outer("10_1267204683.33533")
.annotate "line", 5
.const 'Sub' $P286 = "92_1267204683.33533"
capture_lex $P286
.const 'Sub' $P279 = "90_1267204683.33533"
capture_lex $P279
.const 'Sub' $P266 = "87_1267204683.33533"
capture_lex $P266
.const 'Sub' $P261 = "85_1267204683.33533"
capture_lex $P261
.const 'Sub' $P255 = "83_1267204683.33533"
capture_lex $P255
.const 'Sub' $P249 = "81_1267204683.33533"
capture_lex $P249
.const 'Sub' $P244 = "79_1267204683.33533"
capture_lex $P244
.const 'Sub' $P239 = "77_1267204683.33533"
capture_lex $P239
.const 'Sub' $P234 = "75_1267204683.33533"
capture_lex $P234
.const 'Sub' $P229 = "73_1267204683.33533"
capture_lex $P229
.const 'Sub' $P224 = "71_1267204683.33533"
capture_lex $P224
.const 'Sub' $P219 = "69_1267204683.33533"
capture_lex $P219
.const 'Sub' $P208 = "65_1267204683.33533"
capture_lex $P208
.const 'Sub' $P195 = "63_1267204683.33533"
capture_lex $P195
.const 'Sub' $P183 = "61_1267204683.33533"
capture_lex $P183
.const 'Sub' $P176 = "59_1267204683.33533"
capture_lex $P176
.const 'Sub' $P167 = "57_1267204683.33533"
capture_lex $P167
.const 'Sub' $P160 = "55_1267204683.33533"
capture_lex $P160
.const 'Sub' $P151 = "53_1267204683.33533"
capture_lex $P151
.const 'Sub' $P144 = "51_1267204683.33533"
capture_lex $P144
.const 'Sub' $P135 = "49_1267204683.33533"
capture_lex $P135
.const 'Sub' $P128 = "47_1267204683.33533"
capture_lex $P128
.const 'Sub' $P121 = "45_1267204683.33533"
capture_lex $P121
.const 'Sub' $P111 = "43_1267204683.33533"
capture_lex $P111
.const 'Sub' $P103 = "41_1267204683.33533"
capture_lex $P103
.const 'Sub' $P93 = "40_1267204683.33533"
capture_lex $P93
.const 'Sub' $P87 = "38_1267204683.33533"
capture_lex $P87
.const 'Sub' $P82 = "36_1267204683.33533"
capture_lex $P82
.const 'Sub' $P74 = "34_1267204683.33533"
capture_lex $P74
.const 'Sub' $P68 = "32_1267204683.33533"
capture_lex $P68
.const 'Sub' $P62 = "30_1267204683.33533"
capture_lex $P62
.const 'Sub' $P56 = "28_1267204683.33533"
capture_lex $P56
.const 'Sub' $P23 = "14_1267204683.33533"
capture_lex $P23
.const 'Sub' $P15 = "12_1267204683.33533"
capture_lex $P15
.annotate "line", 33
.const 'Sub' $P286 = "92_1267204683.33533"
capture_lex $P286
.annotate "line", 5
.return ($P286)
.end
.namespace ["HLL";"Grammar"]
.sub "ws" :subid("12_1267204683.33533") :method :outer("11_1267204683.33533")
.annotate "line", 5
.local string rx16_tgt
.local int rx16_pos
.local int rx16_off
.local int rx16_eos
.local int rx16_rep
.local pmc rx16_cur
(rx16_cur, rx16_pos, rx16_tgt) = self."!cursor_start"()
rx16_cur."!cursor_debug"("START ", "ws")
.lex unicode:"$\x{a2}", rx16_cur
.local pmc match
.lex "$/", match
length rx16_eos, rx16_tgt
set rx16_off, 0
lt rx16_pos, 2, rx16_start
sub rx16_off, rx16_pos, 1
substr rx16_tgt, rx16_tgt, rx16_off
rx16_start:
$I10 = self.'from'()
ne $I10, -1, rxscan19_done
goto rxscan19_scan
rxscan19_loop:
($P10) = rx16_cur."from"()
inc $P10
set rx16_pos, $P10
ge rx16_pos, rx16_eos, rxscan19_done
rxscan19_scan:
set_addr $I10, rxscan19_loop
rx16_cur."!mark_push"(0, rx16_pos, $I10)
rxscan19_done:
# rx subrule "ww" subtype=zerowidth negate=1
rx16_cur."!cursor_pos"(rx16_pos)
$P10 = rx16_cur."ww"()
if $P10, rx16_fail
# rx rxquantr20 ** 0..*
set_addr $I22, rxquantr20_done
rx16_cur."!mark_push"(0, rx16_pos, $I22)
rxquantr20_loop:
alt21_0: