#define PL_lex_casestack (PL_parser->lex_casestack)
#define PL_lex_defer (PL_parser->lex_defer)
#define PL_lex_dojoin (PL_parser->lex_dojoin)
-#define PL_lex_expect (PL_parser->lex_expect)
#define PL_lex_formbrack (PL_parser->lex_formbrack)
#define PL_lex_inpat (PL_parser->lex_inpat)
#define PL_lex_inwhat (PL_parser->lex_inwhat)
#define SPACE_OR_TAB(c) isBLANK_A(c)
+#define HEXFP_PEEK(s) \
+ (((s[0] == '.') && \
+ (isXDIGIT(s[1]) || isALPHA_FOLD_EQ(s[1], 'p'))) || \
+ isALPHA_FOLD_EQ(s[0], 'p'))
+
/* LEX_* are values for PL_lex_state, the state of the lexer.
* They are arranged oddly so that the guard on the switch statement
* can get by with a single comparison (if the compiler is smart enough).
* PWop : power operator
* PMop : pattern-matching operator
* Aop : addition-level operator
+ * AopNOASSIGN : addition-level operator that is never part of .=
* Mop : multiplication-level operator
* Eop : equality-testing operator
* Rop : relational operator <= != gt
#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 POSTDEREF(f) return (PL_bufptr = s, S_postderef(aTHX_ REPORT(f),s[1]))
-#define LOOPX(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)LOOPEX))
+#define LOOPX(f) return (PL_bufptr = force_word(s,WORD,TRUE,FALSE), \
+ pl_yylval.ival=f, \
+ PL_expect = PL_nexttoke ? XOPERATOR : XTERM, \
+ REPORT((int)LOOPEX))
#define FTST(f) return (pl_yylval.ival=f, PL_expect=XTERMORDORDOR, PL_bufptr=s, REPORT((int)UNIOP))
#define FUN0(f) return (pl_yylval.ival=f, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0))
#define FUN0OP(f) return (pl_yylval.opval=f, CLINE, PL_expect=XOPERATOR, PL_bufptr=s, REPORT((int)FUNC0OP))
#define PWop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)POWOP)))
#define PMop(f) return(pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MATCHOP))
#define Aop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)ADDOP)))
+#define AopNOASSIGN(f) return (pl_yylval.ival=f, PL_bufptr=s, REPORT((int)ADDOP))
#define Mop(f) return ao((pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)MULOP)))
#define Eop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)EQOP))
#define Rop(f) return (pl_yylval.ival=f, PL_expect=XTERM, PL_bufptr=s, REPORT((int)RELOP))
/*
* S_ao
*
- * This subroutine detects &&=, ||=, and //= and turns an ANDAND, OROR or DORDOR
- * into an OP_ANDASSIGN, OP_ORASSIGN, or OP_DORASSIGN
+ * This subroutine looks for an '=' next to the operator that has just been
+ * parsed and turns it into an ASSIGNOP if it finds one.
*/
STATIC int
/*
* S_lop
* Build a list operator (or something that might be one). The rules:
- * - if we have a next token, then it's a list operator [why?]
+ * - if we have a next token, then it's a list operator (no parens) for
+ * which the next token has already been parsed; e.g.,
+ * sort foo @args
+ * sort foo (@args)
* - if the next thing is an opening paren, then it's a function
* - else it's a list operator
*/
pl_yylval.ival = f;
CLINE;
- PL_expect = x;
PL_bufptr = s;
PL_last_lop = PL_oldbufptr;
PL_last_lop_op = (OPCODE)f;
if (PL_nexttoke)
goto lstop;
+ PL_expect = x;
if (*s == '(')
return REPORT(FUNC);
s = PEEKSPACE(s);
PL_nexttoke++;
if (PL_lex_state != LEX_KNOWNEXT) {
PL_lex_defer = PL_lex_state;
- PL_lex_expect = PL_expect;
PL_lex_state = LEX_KNOWNEXT;
}
}
pl_yylval = PL_nextval[PL_nexttoke];
if (!PL_nexttoke) {
PL_lex_state = PL_lex_defer;
- PL_expect = PL_lex_expect;
PL_lex_defer = LEX_NORMAL;
}
{
PL_lex_starts = 0;
/* commas only at base level: /$a\Ub$c/ => ($a,uc(b.$c)) */
if (PL_lex_casemods == 1 && PL_lex_inpat)
- OPERATOR(',');
+ TOKEN(',');
else
- Aop(OP_CONCAT);
+ AopNOASSIGN(OP_CONCAT);
}
else
return yylex();
s = PL_bufptr;
/* commas only at base level: /$a\Ub$c/ => ($a,uc(b.$c)) */
if (!PL_lex_casemods && PL_lex_inpat)
- OPERATOR(',');
+ TOKEN(',');
else
- Aop(OP_CONCAT);
+ AopNOASSIGN(OP_CONCAT);
}
return yylex();
if (PL_lex_starts++) {
/* commas only at base level: /$a\Ub$c/ => ($a,uc(b.$c)) */
if (!PL_lex_casemods && PL_lex_inpat)
- OPERATOR(',');
+ TOKEN(',');
else
- Aop(OP_CONCAT);
+ AopNOASSIGN(OP_CONCAT);
}
else {
PL_bufptr = s;
TOKEN(0);
CLINE;
s++;
- OPERATOR(';');
+ PL_expect = XSTATE;
+ TOKEN(';');
case ')':
if (!PL_lex_allbrackets && PL_lex_fakeeof >= LEX_FAKEEOF_CLOSING)
TOKEN(0);
}
}
/* FALLTHROUGH */
- case XATTRBLOCK:
- case XBLOCK:
- PL_lex_brackstack[PL_lex_brackets++] = XSTATE;
- PL_lex_allbrackets++;
- PL_expect = XSTATE;
- break;
case XATTRTERM:
case XTERMBLOCK:
PL_lex_brackstack[PL_lex_brackets++] = XOPERATOR;
PL_lex_allbrackets++;
PL_expect = XSTATE;
break;
+ case XATTRBLOCK:
+ case XBLOCK:
+ PL_lex_brackstack[PL_lex_brackets++] = XSTATE;
+ PL_lex_allbrackets++;
+ PL_expect = XSTATE;
+ break;
case XBLOCKTERM:
PL_lex_brackstack[PL_lex_brackets++] = XTERM;
PL_lex_allbrackets++;
} else if (result == KEYWORD_PLUGIN_STMT) {
pl_yylval.opval = o;
CLINE;
- PL_expect = XSTATE;
+ if (!PL_nexttoke) PL_expect = XSTATE;
return REPORT(PLUGSTMT);
} else if (result == KEYWORD_PLUGIN_EXPR) {
pl_yylval.opval = o;
CLINE;
- PL_expect = XOPERATOR;
+ if (!PL_nexttoke) PL_expect = XOPERATOR;
return REPORT(PLUGEXPR);
} else {
Perl_croak(aTHX_ "Bad plugin affecting keyword '%s'",
UNI(OP_DBMCLOSE);
case KEY_dump:
- PL_expect = XOPERATOR;
- s = force_word(s,WORD,TRUE,FALSE);
LOOPX(OP_DUMP);
case KEY_else:
LOP(OP_GREPSTART, XREF);
case KEY_goto:
- PL_expect = XOPERATOR;
- s = force_word(s,WORD,TRUE,FALSE);
LOOPX(OP_GOTO);
case KEY_gmtime:
LOP(OP_KILL,XTERM);
case KEY_last:
- PL_expect = XOPERATOR;
- s = force_word(s,WORD,TRUE,FALSE);
LOOPX(OP_LAST);
case KEY_lc:
OPERATOR(MY);
case KEY_next:
- PL_expect = XOPERATOR;
- s = force_word(s,WORD,TRUE,FALSE);
LOOPX(OP_NEXT);
case KEY_ne:
case KEY_no:
s = tokenize_use(0, s);
- TERM(USE);
+ TOKEN(USE);
case KEY_not:
if (*s == '(' || (s = SKIPSPACE1(s), *s == '('))
s = force_word(s,WORD,FALSE,TRUE);
s = SKIPSPACE1(s);
s = force_strict_version(s);
- PL_lex_expect = XBLOCK;
- OPERATOR(PACKAGE);
+ PREBLOCK(PACKAGE);
case KEY_pipe:
LOP(OP_PIPE_OP,XTERM);
case KEY_require:
s = SKIPSPACE1(s);
- PL_expect = XOPERATOR;
if (isDIGIT(*s)) {
s = force_version(s, FALSE);
}
}
else
pl_yylval.ival = 0;
- PL_expect = XTERM;
+ PL_expect = PL_nexttoke ? XOPERATOR : XTERM;
PL_bufptr = s;
PL_last_uni = PL_oldbufptr;
PL_last_lop_op = OP_REQUIRE;
UNI(OP_RESET);
case KEY_redo:
- PL_expect = XOPERATOR;
- s = force_word(s,WORD,TRUE,FALSE);
LOOPX(OP_REDO);
case KEY_rename:
case KEY_use:
s = tokenize_use(1, s);
- OPERATOR(USE);
+ TOKEN(USE);
case KEY_values:
UNI(OP_VALUES);
/* this could be hexfp, but peek ahead
* to avoid matching ".." */
-#define HEXFP_PEEK(s) \
- (((s[0] == '.') && \
- (isXDIGIT(s[1]) || isALPHA_FOLD_EQ(s[1], 'p'))) \
- || isALPHA_FOLD_EQ(s[0], 'p'))
if (UNLIKELY(HEXFP_PEEK(s))) {
goto out;
}