3 PGE/Util.pir - useful rules for working with PGE grammars
7 This module defines a number of useful rules for various
8 parsing tasks using PGE.
14 .namespace [ 'PGE::Util' ]
16 .include 'cclass.pasm'
20 $P0 = subclass 'PGE::Grammar', 'PGE::Util'
26 =item die(match, [, message [, ...]] )
28 Throws an exception at the current point in the match. If message
29 doesn't end with a newline, also produces the line number and offset
35 .param pmc mob # match object
36 .param pmc list :slurpy # message arguments
41 iter = new 'Iterator', list
43 unless iter goto iter_end
49 # get a copy of the match object
52 $P0 = get_hll_global ['PGE'], 'Match'
53 (mob, pos, target) = $P0.'new'(mob)
56 $I0 = is_cclass .CCLASS_NEWLINE, message, $I0
57 if $I0 goto throw_message
60 .local pmc line_number
61 # FIXME: use 'line_number' method instead?
62 line_number = get_hll_global ['PGE::Util'], 'line_number'
63 (lines) = mob.line_number(pos)
65 message .= ' at line '
71 if $I0 < 10 goto add_position_1
74 $S0 = substr target, pos, $I0
89 =item warn(match, [, message [, ...]] )
91 Emits the list of messages to stderr.
96 .param pmc mob # match object
97 .param pmc list :slurpy # message arguments
100 .local string message
102 iter = new 'Iterator', list
104 unless iter goto iter_end
110 # get a copy of the match object
113 $P0 = get_hll_global ['PGE'], 'Match'
114 (mob, pos, target) = $P0.'new'(mob)
117 $I0 = is_cclass .CCLASS_NEWLINE, message, $I0
118 if $I0 goto emit_message
121 .local pmc line_number
122 # FIXME: use 'line_number' method instead?
123 line_number = get_hll_global ['PGE::Util'], 'line_number'
124 (lines) = mob.line_number(pos)
126 message .= ' at line '
139 =item line_number(match [, pos])
141 Return the line number and offset of the of the line corresponding to
142 offset C<pos> in the string targeted by C<match>. If C<pos> isn't
143 supplied, then use the C<from> value of C<match> as the offset.
144 For this function the line number for the first line in the
145 string is treated as '0'.
151 .param int pos :optional
152 .param int has_pos :opt_flag
154 if has_pos goto have_pos
158 # count newlines to the current position of the parse
159 .local int pos, npos, lines
161 $P99 = getattribute match, '$.target'
166 $I0 = find_cclass .CCLASS_NEWLINE, target, npos, pos
167 if $I0 >= pos goto newline_done
168 $S0 = substr target, $I0, 2
171 if $S0 != "\r\n" goto newline_loop
175 .return (lines, npos)
179 =item split(regex, string [, count])
181 Split the string where the regex matches, returning an array. Optionally limit
182 the number of splits.
191 .param int count :optional
192 .param int has_count :opt_flag
194 .local pmc result, match
197 result = new 'ResizablePMCArray'
202 match = regex(str, 'continue'=>pos)
203 ## if regex not found in target, we're done
204 unless match goto split_end
206 ## save substring up to current match
209 $S0 = substr str, pos, $I0
214 captures = match.'list'()
215 if null captures goto capture_end
216 $I0 = elements captures
219 if $I1 == $I0 goto capture_end
227 ## are we counting matches?
228 unless has_count goto split_loop
229 ## check if we've already split enough
231 if n < count goto split_loop
235 ## save string from end of last match to end of string
236 $S0 = substr str, pos
237 if $S0 == "" goto end
248 # vim: expandtab shiftwidth=4 ft=pir: