summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c100
1 files changed, 76 insertions, 24 deletions
diff --git a/toke.c b/toke.c
index 6b1b8e4a6f..c6b3f3c084 100644
--- a/toke.c
+++ b/toke.c
@@ -178,7 +178,7 @@ int yyactlevel = -1;
#define PREREF(retval) return (PL_expect = XREF,PL_bufptr = s, REPORT(retval))
#define TERM(retval) return (CLINE, PL_expect = XOPERATOR, PL_bufptr = s, REPORT(retval))
#define LOOPX(f) return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)LOOPEX))
-#define FTST(f) return (yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)UNIOP))
+#define FTST(f) return (yylval.ival=f, PL_expect=XTERMORDORDOR, PL_bufptr=s, REPORT((int)UNIOP))
#define FUN0(f) return (yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0))
#define FUN1(f) return (yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC1))
#define BOop(f) return ao((yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)BITOROP)))
@@ -193,10 +193,12 @@ int yyactlevel = -1;
/* This bit of chicanery makes a unary function followed by
* a parenthesis into a function with one argument, highest precedence.
+ * The UNIDOR macro is for unary functions that can be followed by the //
+ * operator (such as C<shift // 0>).
*/
-#define UNI(f) { \
+#define UNI2(f,x) { \
yylval.ival = f; \
- PL_expect = XTERM; \
+ PL_expect = x, \
PL_bufptr = s; \
PL_last_uni = PL_oldbufptr; \
PL_last_lop_op = f; \
@@ -205,6 +207,8 @@ int yyactlevel = -1;
s = PEEKSPACE(s); \
return REPORT( *s=='(' ? (int)FUNC1 : (int)UNIOP ); \
}
+#define UNI(f) UNI2(f,XTERM)
+#define UNIDOR(f) UNI2(f,XTERMORDORDOR)
#define UNIBRACK(f) { \
yylval.ival = f; \
@@ -376,8 +380,8 @@ S_printbuf(pTHX_ const char* fmt, const char* s)
/*
* S_ao
*
- * This subroutine detects &&= and ||= and turns an ANDAND or OROR
- * into an OP_ANDASSIGN or OP_ORASSIGN
+ * This subroutine detects &&=, ||=, and //= and turns an ANDAND, OROR or DORDOR
+ * into an OP_ANDASSIGN, OP_ORASSIGN, or OP_DORASSIGN
*/
STATIC int
@@ -389,6 +393,8 @@ S_ao(pTHX_ int toketype)
yylval.ival = OP_ANDASSIGN;
else if (toketype == OROR)
yylval.ival = OP_ORASSIGN;
+ else if (toketype == DORDOR)
+ yylval.ival = OP_DORASSIGN;
toketype = ASSIGNOP;
}
return toketype;
@@ -1240,6 +1246,9 @@ S_sublex_start(pTHX)
}
yylval.opval = (OP*)newSVOP(op_type, 0, sv);
PL_lex_stuff = NULL;
+ /* Allow <FH> // "foo" */
+ if (op_type == OP_READLINE)
+ PL_expect = XTERMORDORDOR;
return THING;
}
@@ -3398,6 +3407,7 @@ Perl_yylex(pTHX)
switch (tmp) {
case KEY_or:
case KEY_and:
+ case KEY_err:
case KEY_for:
case KEY_unless:
case KEY_if:
@@ -4011,6 +4021,9 @@ Perl_yylex(pTHX)
else if ((*s == '?' || *s == '-' || *s == '+')
&& !isSPACE(s[1]) && s[1] != '=')
PL_expect = XTERM; /* e.g. print $fh -1 */
+ else if (*s == '/' && !isSPACE(s[1]) && s[1] != '=' && s[1] != '/')
+ PL_expect = XTERM; /* e.g. print $fh /.../
+ XXX except DORDOR operator */
else if (*s == '<' && s[1] == '<' && !isSPACE(s[2])
&& s[2] != '=')
PL_expect = XTERM; /* print $fh <<"EOF" */
@@ -4053,24 +4066,40 @@ Perl_yylex(pTHX)
PL_pending_ident = '@';
TERM('@');
- case '/': /* may either be division or pattern */
+ case '/': /* may be division, defined-or, or pattern */
+ if (PL_expect == XTERMORDORDOR && s[1] == '/') {
+ s += 2;
+ AOPERATOR(DORDOR);
+ }
case '?': /* may either be conditional or pattern */
- if (PL_expect != XOPERATOR) {
+ if (PL_expect == XOPERATOR) {
+ char tmp = *s++;
+ if (tmp == '?') {
+ OPERATOR('?');
+ }
+ else {
+ tmp = *s++;
+ if (tmp == '/') {
+ /* A // operator. */
+ AOPERATOR(DORDOR);
+ }
+ else {
+ s--;
+ Mop(OP_DIVIDE);
+ }
+ }
+ }
+ else {
/* Disable warning on "study /blah/" */
if (PL_oldoldbufptr == PL_last_uni
&& (*PL_last_uni != 's' || s - PL_last_uni < 5
|| memNE(PL_last_uni, "study", 5)
- || isALNUM_lazy_if(PL_last_uni+5,UTF)))
+ || isALNUM_lazy_if(PL_last_uni+5,UTF)
+ ))
check_uni();
s = scan_pat(s,OP_MATCH);
TERM(sublex_start());
}
- {
- char tmp = *s++;
- if (tmp == '/')
- Mop(OP_DIVIDE);
- OPERATOR(tmp);
- }
case '.':
if (PL_lex_formbrack && PL_lex_brackets == PL_lex_formbrack
@@ -4181,7 +4210,9 @@ Perl_yylex(pTHX)
TERM(THING);
}
/* avoid v123abc() or $h{v1}, allow C<print v10;> */
- else if (!isALPHA(*start) && (PL_expect == XTERM || PL_expect == XREF || PL_expect == XSTATE)) {
+ else if (!isALPHA(*start) && (PL_expect == XTERM
+ || PL_expect == XREF || PL_expect == XSTATE
+ || PL_expect == XTERMORDORDOR)) {
GV *const gv = gv_fetchpvn_flags(s, start - s, 0, SVt_PVCV);
if (!gv) {
s = scan_num(s, &yylval);
@@ -4303,6 +4334,16 @@ Perl_yylex(pTHX)
{
tmp = 0; /* any sub overrides "weak" keyword */
}
+ else if (gv && !gvp
+ && tmp == -KEY_err
+ && GvCVu(gv)
+ && PL_expect != XOPERATOR
+ && PL_expect != XTERMORDORDOR)
+ {
+ /* any sub overrides the "err" keyword, except when really an
+ * operator is expected */
+ tmp = 0;
+ }
else { /* no override */
tmp = -tmp;
if (tmp == KEY_dump && ckWARN(WARN_MISC)) {
@@ -4862,6 +4903,9 @@ Perl_yylex(pTHX)
case KEY_eof:
UNI(OP_EOF);
+ case KEY_err:
+ OPERATOR(DOROP);
+
case KEY_exp:
UNI(OP_EXP);
@@ -4944,7 +4988,7 @@ Perl_yylex(pTHX)
UNI(OP_GMTIME);
case KEY_getc:
- UNI(OP_GETC);
+ UNIDOR(OP_GETC);
case KEY_getppid:
FUN0(OP_GETPPID);
@@ -5196,10 +5240,10 @@ Perl_yylex(pTHX)
LOP(OP_PUSH,XTERM);
case KEY_pop:
- UNI(OP_POP);
+ UNIDOR(OP_POP);
case KEY_pos:
- UNI(OP_POS);
+ UNIDOR(OP_POS);
case KEY_pack:
LOP(OP_PACK,XTERM);
@@ -5349,7 +5393,7 @@ Perl_yylex(pTHX)
UNI(OP_READDIR);
case KEY_readline:
- UNI(OP_READLINE);
+ UNIDOR(OP_READLINE);
case KEY_readpipe:
UNI(OP_BACKTICK);
@@ -5364,7 +5408,7 @@ Perl_yylex(pTHX)
LOP(OP_REVERSE,XTERM);
case KEY_readlink:
- UNI(OP_READLINK);
+ UNIDOR(OP_READLINK);
case KEY_ref:
UNI(OP_REF);
@@ -5431,7 +5475,7 @@ Perl_yylex(pTHX)
LOP(OP_SSOCKOPT,XTERM);
case KEY_shift:
- UNI(OP_SHIFT);
+ UNIDOR(OP_SHIFT);
case KEY_shmctl:
LOP(OP_SHMCTL,XTERM);
@@ -5668,7 +5712,7 @@ Perl_yylex(pTHX)
LOP(OP_UNLINK,XTERM);
case KEY_undef:
- UNI(OP_UNDEF);
+ UNIDOR(OP_UNDEF);
case KEY_unpack:
LOP(OP_UNPACK,XTERM);
@@ -5677,7 +5721,7 @@ Perl_yylex(pTHX)
LOP(OP_UTIME,XTERM);
case KEY_umask:
- UNI(OP_UMASK);
+ UNIDOR(OP_UMASK);
case KEY_unshift:
LOP(OP_UNSHIFT,XTERM);
@@ -6069,7 +6113,7 @@ Perl_keyword (pTHX_ char *name, I32 len)
goto unknown;
}
- case 3: /* 27 tokens of length 3 */
+ case 3: /* 28 tokens of length 3 */
switch (name[0])
{
case 'E':
@@ -6163,6 +6207,14 @@ Perl_keyword (pTHX_ char *name, I32 len)
goto unknown;
+ case 'r':
+ if (name[2] == 'r')
+ { /* err */
+ return -KEY_err;
+ }
+
+ goto unknown;
+
default:
goto unknown;
}