summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2013-07-22 18:33:38 -0400
committerJesse Luehrs <doy@tozt.net>2013-07-22 18:33:38 -0400
commit485f6c2b0f3c69c94458b67c797e4d4eb63c6c3e (patch)
tree2a654e44a90f40d0d514c3d6005155281a42a4da
parent0cdc63eb4e5b7357b40ee7b43b1299208c375e10 (diff)
downloadparse-keyword-485f6c2b0f3c69c94458b67c797e4d4eb63c6c3e.tar.gz
parse-keyword-485f6c2b0f3c69c94458b67c797e4d4eb63c6c3e.zip
work around bugs in lex_next_chunk
-rw-r--r--Keyword.xs15
-rw-r--r--lib/Parse/Keyword.pm16
-rw-r--r--t/peek.t22
3 files changed, 52 insertions, 1 deletions
diff --git a/Keyword.xs b/Keyword.xs
index ba99b4a..eaaa9dd 100644
--- a/Keyword.xs
+++ b/Keyword.xs
@@ -95,14 +95,29 @@ lex_peek(len = 1)
UV len
CODE:
PL_curcop = &PL_compiling;
+
+ /* XXX before 5.19.2, lex_next_chunk when we aren't at the end of a line
+ * just breaks things entirely (the parser no longer sees the text that is
+ * read in). this is (i think inadvertently) fixed in 5.19.2 (21791330a),
+ * but it still screws up the line numbers of everything that follows. so,
+ * the workaround is just to not call lex_next_chunk unless we're at the
+ * end of a line. this is a bit limiting, but should rarely come up in
+ * practice.
+ */
+ /*
while (PL_parser->bufend - PL_parser->bufptr < len) {
if (!lex_next_chunk(0)) {
break;
}
}
+ */
+ if (PL_parser->bufptr == PL_parser->bufend) {
+ lex_next_chunk(0);
+ }
if (PL_parser->bufend - PL_parser->bufptr < len) {
len = PL_parser->bufend - PL_parser->bufptr;
}
+
RETVAL = newSVpvn(PL_parser->bufptr, len); /* XXX unicode? */
OUTPUT:
RETVAL
diff --git a/lib/Parse/Keyword.pm b/lib/Parse/Keyword.pm
index afb2079..78a580a 100644
--- a/lib/Parse/Keyword.pm
+++ b/lib/Parse/Keyword.pm
@@ -73,6 +73,12 @@ current position in the buffer to be parsed is not moved. See L<<
perlapi/PL_parser->linestr >> and L<perlapi/lex_next_chunk> for more
information.
+NOTE: This function currently only returns text that is on the current line,
+unless the current line has been fully read (via C<lex_read>). This is due to a
+bug in perl itself, and this restriction will hopefully be lifted in a future
+version of this module, so don't depend on it. See the L</BUGS> section for
+more information.
+
=func lex_read($n)
Moves the current position in the parsing buffer forward by C<$n> characters
@@ -147,7 +153,15 @@ sub import {
=head1 BUGS
-This module inherits the limitation from L<Devel::CallParser> that custom
+Peeking into the next line is currently (as of 5.19.2) broken in perl if the
+current line hasn't been fully consumed. This module works around this by just
+not doing that. This shouldn't be an issue for the most part, since it will
+only come up if you need to conditionally parse something based on a token that
+can span multiple lines. Just keep in mind that if you're reading in a large
+chunk of text, you'll need to alternate between calling C<lex_peek> and
+C<lex_read>, or else you'll only be able to see text on the current line.
+
+This module also inherits the limitation from L<Devel::CallParser> that custom
parsing is only triggered if the keyword is called by its unqualified name
(C<try>, not C<Try::try>, for instance).
diff --git a/t/peek.t b/t/peek.t
new file mode 100644
index 0000000..6d2d989
--- /dev/null
+++ b/t/peek.t
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+
+{
+ package Parser;
+
+ use Parse::Keyword { foo => \&parse_foo };
+
+ sub foo {}
+ sub parse_foo {
+ lex_peek(99999999);
+ return sub {};
+ }
+
+ ::is_deeply([ foo ], []);
+}
+
+is(__LINE__, 20);
+
+done_testing;