Added NOWDOC

This commit is contained in:
Dmitry Stogov 2008-02-12 09:28:30 +00:00
parent 70252556cc
commit 87a8f72f49
32 changed files with 845 additions and 2 deletions

View file

@ -0,0 +1,23 @@
--TEST--
basic heredoc syntax
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
This is a heredoc test.
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
This is another heredoc test.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
This is a heredoc test.
This is another heredoc test.

View file

@ -0,0 +1,23 @@
--TEST--
basic binary heredoc syntax
--FILE--
<?php
require_once 'nowdoc.inc';
print b<<<ENDOFHEREDOC
This is a heredoc test.
ENDOFHEREDOC;
$x = b<<<ENDOFHEREDOC
This is another heredoc test.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
This is a heredoc test.
This is another heredoc test.

View file

@ -0,0 +1,23 @@
--TEST--
simple variable replacement test (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
This is heredoc test #$a.
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
This is heredoc test #$b.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
This is heredoc test #1.
This is heredoc test #2.

View file

@ -0,0 +1,23 @@
--TEST--
braces variable replacement test (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
This is heredoc test #{$a}.
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
This is heredoc test #{$b}.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
This is heredoc test #1.
This is heredoc test #2.

View file

@ -0,0 +1,22 @@
--TEST--
unbraced complex variable replacement test (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
This is heredoc test #s $a, $b, $c['c'], and $d->d.
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
This is heredoc test #s $a, $b, $c['c'], and $d->d.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECTF--
Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in %sheredoc_005.php on line 6

View file

@ -0,0 +1,23 @@
--TEST--
braced complex variable replacement test (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
This is heredoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}.
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
This is heredoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
This is heredoc test #s 1, 2, 3, and 4.
This is heredoc test #s 1, 2, 3, and 4.

View file

@ -0,0 +1,23 @@
--TEST--
braced and unbraced complex variable replacement test (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
This is heredoc test #s $a, {$b}, {$c['c']}, and {$d->d}.
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
This is heredoc test #s $a, {$b}, {$c['c']}, and {$d->d}.
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
This is heredoc test #s 1, 2, 3, and 4.
This is heredoc test #s 1, 2, 3, and 4.

View file

@ -0,0 +1,17 @@
--TEST--
empty doc test (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--

View file

@ -0,0 +1,42 @@
--TEST--
Torture the T_END_HEREDOC rules (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<ENDOFHEREDOC
ENDOFHEREDOC ;
ENDOFHEREDOC;
ENDOFHEREDOC
ENDOFHEREDOC
$ENDOFHEREDOC;
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
ENDOFHEREDOC ;
ENDOFHEREDOC;
ENDOFHEREDOC
ENDOFHEREDOC
$ENDOFHEREDOC;
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECTF--
Notice: Undefined variable: ENDOFHEREDOC in %s on line %d
ENDOFHEREDOC ;
ENDOFHEREDOC;
ENDOFHEREDOC
ENDOFHEREDOC
;
Notice: Undefined variable: ENDOFHEREDOC in %s on line %d
ENDOFHEREDOC ;
ENDOFHEREDOC;
ENDOFHEREDOC
ENDOFHEREDOC
;

View file

@ -0,0 +1,32 @@
--TEST--
Torture the T_END_HEREDOC rules with variable expansions (heredoc)
--FILE--
<?php
require_once 'nowdoc.inc';
$fooledYou = '';
print <<<ENDOFHEREDOC
{$fooledYou}ENDOFHEREDOC{$fooledYou}
ENDOFHEREDOC{$fooledYou}
{$fooledYou}ENDOFHEREDOC
ENDOFHEREDOC;
$x = <<<ENDOFHEREDOC
{$fooledYou}ENDOFHEREDOC{$fooledYou}
ENDOFHEREDOC{$fooledYou}
{$fooledYou}ENDOFHEREDOC
ENDOFHEREDOC;
print "{$x}";
?>
--EXPECT--
ENDOFHEREDOC
ENDOFHEREDOC
ENDOFHEREDOC
ENDOFHEREDOC
ENDOFHEREDOC
ENDOFHEREDOC

View file

@ -0,0 +1,20 @@
--TEST--
Heredocs can NOT be used as static scalars.
--FILE--
<?php
require_once 'nowdoc.inc';
class e {
const E = <<<THISMUSTERROR
If you see this, something's wrong.
THISMUSTERROR;
};
print e::E . "\n";
?>
--EXPECTF--
Parse error: syntax error, unexpected T_START_HEREDOC in %sheredoc_011.php on line 8

11
Zend/tests/nowdoc.inc Normal file
View file

@ -0,0 +1,11 @@
<?php
// Common definitions for heredoc/nowdoc tests.
$a = 1;
$b = 2;
$c = array( 'c' => 3, );
class d { public function __construct() { $this->d = 4; } };
$d = new d;
?>

View file

@ -0,0 +1,24 @@
--TEST--
basic nowdoc syntax
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
This is a nowdoc test.
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
This is another nowdoc test.
With another line in it.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is a nowdoc test.
This is another nowdoc test.
With another line in it.

View file

@ -0,0 +1,23 @@
--TEST--
basic binary nowdoc syntax
--FILE--
<?php
require_once 'nowdoc.inc';
print b<<<'ENDOFNOWDOC'
This is a nowdoc test.
ENDOFNOWDOC;
$x = b<<<'ENDOFNOWDOC'
This is another nowdoc test.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is a nowdoc test.
This is another nowdoc test.

View file

@ -0,0 +1,23 @@
--TEST--
simple variable replacement test (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
This is nowdoc test #$a.
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
This is nowdoc test #$b.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is nowdoc test #$a.
This is nowdoc test #$b.

View file

@ -0,0 +1,23 @@
--TEST--
braces variable replacement test (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
This is nowdoc test #{$a}.
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
This is nowdoc test #{$b}.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is nowdoc test #{$a}.
This is nowdoc test #{$b}.

View file

@ -0,0 +1,23 @@
--TEST--
unbraced complex variable replacement test (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
This is nowdoc test #s $a, $b, $c['c'], and $d->d.
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
This is nowdoc test #s $a, $b, $c['c'], and $d->d.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is nowdoc test #s $a, $b, $c['c'], and $d->d.
This is nowdoc test #s $a, $b, $c['c'], and $d->d.

View file

@ -0,0 +1,23 @@
--TEST--
braced complex variable replacement test (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}.
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}.
This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}.

View file

@ -0,0 +1,23 @@
--TEST--
braced and unbraced complex variable replacement test (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}.
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}.
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}.
This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}.

View file

@ -0,0 +1,17 @@
--TEST--
empty doc test (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--

View file

@ -0,0 +1,40 @@
--TEST--
Torture the T_END_NOWDOC rules (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
print <<<'ENDOFNOWDOC'
ENDOFNOWDOC ;
ENDOFNOWDOC;
ENDOFNOWDOC
ENDOFNOWDOC
$ENDOFNOWDOC;
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
ENDOFNOWDOC ;
ENDOFNOWDOC;
ENDOFNOWDOC
ENDOFNOWDOC
$ENDOFNOWDOC;
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
ENDOFNOWDOC ;
ENDOFNOWDOC;
ENDOFNOWDOC
ENDOFNOWDOC
$ENDOFNOWDOC;
ENDOFNOWDOC ;
ENDOFNOWDOC;
ENDOFNOWDOC
ENDOFNOWDOC
$ENDOFNOWDOC;

View file

@ -0,0 +1,33 @@
--TEST--
Torture the T_END_NOWDOC rules with variable expansions (nowdoc)
--FILE--
<?php
require_once 'nowdoc.inc';
$fooledYou = '';
print <<<'ENDOFNOWDOC'
{$fooledYou}ENDOFNOWDOC{$fooledYou}
ENDOFNOWDOC{$fooledYou}
{$fooledYou}ENDOFNOWDOC
ENDOFNOWDOC;
$x = <<<'ENDOFNOWDOC'
{$fooledYou}ENDOFNOWDOC{$fooledYou}
ENDOFNOWDOC{$fooledYou}
{$fooledYou}ENDOFNOWDOC
ENDOFNOWDOC;
print "{$x}";
?>
--EXPECT--
{$fooledYou}ENDOFNOWDOC{$fooledYou}
ENDOFNOWDOC{$fooledYou}
{$fooledYou}ENDOFNOWDOC
{$fooledYou}ENDOFNOWDOC{$fooledYou}
ENDOFNOWDOC{$fooledYou}
{$fooledYou}ENDOFNOWDOC

View file

@ -0,0 +1,20 @@
--TEST--
Nowdocs CAN be used as static scalars.
--FILE--
<?php
require_once 'nowdoc.inc';
class e {
const E = <<<'THISMUSTNOTERROR'
If you DON'T see this, something's wrong.
THISMUSTNOTERROR;
};
print e::E . "\n";
?>
--EXPECTF--
If you DON'T see this, something's wrong.

View file

@ -0,0 +1,25 @@
--TEST--
Test false labels
--FILE--
<?php
require_once 'nowdoc.inc';
$x = <<<'ENDOFNOWDOC'
This is a nowdoc test.
NOTREALLYEND;
Another line
NOTENDEITHER;
ENDOFNOWDOCWILLBESOON
Now let's finish it
ENDOFNOWDOC;
print "{$x}\n";
?>
--EXPECT--
This is a nowdoc test.
NOTREALLYEND;
Another line
NOTENDEITHER;
ENDOFNOWDOCWILLBESOON
Now let's finish it

View file

@ -0,0 +1,26 @@
--TEST--
Test whitespace following end of nowdoc
--INI--
highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
--FILE--
<?php
$code = <<<'EOF'
<?php
$x = <<<'EOT'
some string
EOT
$y = 2;
?>
EOF;
highlight_string($code);
?>
--EXPECT--
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOT'<br /></span><span style="color: #0000BB">some&nbsp;string&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code>

View file

@ -0,0 +1,25 @@
--TEST--
Highliting empty nowdoc
--INI--
highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
--FILE--
<?php
$code = <<<'EOF'
<?php
$x = <<<'EOT'
EOT
$y = 2;
?>
EOF;
highlight_string($code);
?>
--EXPECT--
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOT'<br /></span><span style="color: #0000BB"></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code>

View file

@ -0,0 +1,99 @@
--TEST--
Test nowdoc and line numbering
--FILE--
<?php
function error_handler($num, $msg, $file, $line, $vars) {
echo $line,"\n";
}
set_error_handler('error_handler');
trigger_error("line", E_USER_ERROR);
$x = <<<EOF
EOF;
var_dump($x);
trigger_error("line", E_USER_ERROR);
$x = <<<'EOF'
EOF;
var_dump($x);
trigger_error("line", E_USER_ERROR);
$x = <<<EOF
test
EOF;
var_dump($x);
trigger_error("line", E_USER_ERROR);
$x = <<<'EOF'
test
EOF;
var_dump($x);
trigger_error("line", E_USER_ERROR);
$x = <<<EOF
test1
test2
test3
EOF;
var_dump($x);
trigger_error("line", E_USER_ERROR);
$x = <<<'EOF'
test1
test2
test3
EOF;
var_dump($x);
trigger_error("line", E_USER_ERROR);
echo "ok\n";
?>
--EXPECT--
6
string(0) ""
10
string(0) ""
14
string(4) "test"
19
string(4) "test"
24
string(20) "test1
test2
test3
"
34
string(20) "test1
test2
test3
"
44
ok
--UEXPECT--
6
unicode(0) ""
10
unicode(0) ""
14
unicode(4) "test"
19
unicode(4) "test"
24
unicode(20) "test1
test2
test3
"
34
unicode(20) "test1
test2
test3
"
44
ok

View file

@ -5011,6 +5011,7 @@ again:
retval = T_ECHO; retval = T_ECHO;
break; break;
case T_END_HEREDOC: case T_END_HEREDOC:
case T_END_NOWDOC:
efree(Z_STRVAL(zendlval->u.constant)); efree(Z_STRVAL(zendlval->u.constant));
break; break;
} }

View file

@ -134,6 +134,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
} }
switch (token_type) { switch (token_type) {
case T_END_HEREDOC: case T_END_HEREDOC:
case T_END_NOWDOC:
zend_html_puts(Z_STRVAL(token), Z_STRLEN(token) TSRMLS_CC); zend_html_puts(Z_STRVAL(token), Z_STRLEN(token) TSRMLS_CC);
break; break;
default: default:
@ -155,7 +156,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
efree(Z_UNIVAL(token).v); efree(Z_UNIVAL(token).v);
break; break;
} }
} else if (token_type == T_END_HEREDOC) { } else if (token_type == T_END_HEREDOC || token_type == T_END_NOWDOC) {
efree(Z_UNIVAL(token).v); efree(Z_UNIVAL(token).v);
} }
Z_TYPE(token) = 0; Z_TYPE(token) = 0;
@ -207,6 +208,7 @@ ZEND_API void zend_strip(TSRMLS_D) /* {{{ */
return; return;
case T_END_HEREDOC: case T_END_HEREDOC:
case T_END_NOWDOC:
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
efree(Z_STRVAL(token)); efree(Z_STRVAL(token));
/* read the following character, either newline or ; */ /* read the following character, either newline or ; */

View file

@ -149,6 +149,8 @@
%token T_NAMESPACE %token T_NAMESPACE
%token T_NS_C %token T_NS_C
%token T_DIR %token T_DIR
%token T_START_NOWDOC
%token T_END_NOWDOC
%% /* Rules */ %% /* Rules */
@ -727,6 +729,7 @@ common_scalar:
| T_METHOD_C { $$ = $1; } | T_METHOD_C { $$ = $1; }
| T_FUNC_C { $$ = $1; } | T_FUNC_C { $$ = $1; }
| T_NS_C { $$ = $1; } | T_NS_C { $$ = $1; }
| T_START_NOWDOC T_ENCAPSED_AND_WHITESPACE T_END_NOWDOC { $$ = $2; }
; ;

View file

@ -39,6 +39,9 @@
%x ST_HEREDOC %x ST_HEREDOC
%x ST_START_HEREDOC %x ST_START_HEREDOC
%x ST_END_HEREDOC %x ST_END_HEREDOC
%x ST_NOWDOC
%x ST_START_NOWDOC
%x ST_END_NOWDOC
%x ST_LOOKING_FOR_PROPERTY %x ST_LOOKING_FOR_PROPERTY
%x ST_LOOKING_FOR_VARNAME %x ST_LOOKING_FOR_VARNAME
%x ST_VAR_OFFSET %x ST_VAR_OFFSET
@ -1411,6 +1414,8 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{DOUBLE_QUOTES_LITERAL_DOLL
BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR}) BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR})
HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({HEREDOC_NEWLINE}+({HEREDOC_NON_LABEL}|{HEREDOC_LABEL_NO_NEWLINE}))) HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({HEREDOC_NEWLINE}+({HEREDOC_NON_LABEL}|{HEREDOC_LABEL_NO_NEWLINE})))
NOWDOC_CHARS ({NEWLINE}*(([^a-zA-Z_\x7f-\xff\n\r][^\n\r]*)|({LABEL}[^a-zA-Z0-9_\x7f-\xff;\n\r][^\n\r]*)|({LABEL}[;][^\n\r]+)))
%option noyylineno %option noyylineno
%option noyywrap %option noyywrap
%% %%
@ -2589,6 +2594,109 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({
} }
%{
/* BEGIN nowdoc */
%}
<ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}[']{LABEL}[']{NEWLINE} {
int bprefix = (yytext[0] != '<') ? 1 : 0;
char *s;
CG(zend_lineno)++;
/* 3 is <<<, 2 is quotes, 1 is newline */
CG(heredoc_len) = yyleng-bprefix-3-2-1-(yytext[yyleng-2]=='\r'?1:0);
s = yytext+bprefix+3;
while ((*s == ' ') || (*s == '\t')) {
s++;
CG(heredoc_len)--;
}
s++; /* first quote */
CG(heredoc) = estrndup(s, CG(heredoc_len));
CG(literal_type) = bprefix?IS_STRING:ZEND_STR_TYPE;
BEGIN(ST_START_NOWDOC);
return T_START_NOWDOC;
}
<ST_START_NOWDOC>{ANY_CHAR} {
yyless(0);
BEGIN(ST_NOWDOC);
}
<ST_START_NOWDOC>{LABEL}";"?[\r\n] {
int label_len = yyleng - 1;
if (yytext[label_len-1]==';') {
label_len--;
}
if (label_len==CG(heredoc_len) && !memcmp(yytext, CG(heredoc), label_len)) {
yyless(label_len-1);
yyleng = 0;
BEGIN(ST_END_NOWDOC);
if (CG(literal_type) == IS_UNICODE) {
ZVAL_EMPTY_UNICODE(zendlval);
} else {
ZVAL_EMPTY_STRING(zendlval);
}
return T_ENCAPSED_AND_WHITESPACE;
} else {
yyless(label_len);
yymore();
BEGIN(ST_NOWDOC);
}
}
<ST_NOWDOC>{NOWDOC_CHARS}*{NEWLINE}+{LABEL}";"?[\n\r] {
char *end = yytext + yyleng - 1;
if (end[-1] == ';') {
end--;
yyleng--;
}
if (yyleng > CG(heredoc_len) && !memcmp(end - CG(heredoc_len), CG(heredoc), CG(heredoc_len))) {
int len = yyleng - CG(heredoc_len) - 2; /* 2 for newline before and after label */
if (len > 0 && yytext[len - 1] == '\r' && yytext[len] == '\n') {
len--;
}
/* Go back before last label char, to match in ST_END_HEREDOC state */
yyless(yyleng - 2);
/* Subtract the remaining label length. yyleng must include newline
* before label, for zend_highlight/strip, tokenizer, etc. */
yyleng -= CG(heredoc_len) - 1;
CG(increment_lineno) = 1; /* For newline before label */
BEGIN(ST_END_NOWDOC);
HANDLE_NEWLINES(yytext, len);
if (!zend_copy_scanner_string(zendlval, yytext, len, CG(literal_type), SCNG(output_conv) TSRMLS_CC)) {
return 0;
}
return T_ENCAPSED_AND_WHITESPACE;
} else {
/* Go back to end of label, so the next match works correctly in case of
* a variable or another label at the beginning of the next line */
yyless(yyleng - 1);
yymore();
}
}
<ST_END_NOWDOC>{ANY_CHAR} {
Z_STRVAL_P(zendlval) = CG(heredoc);
Z_STRLEN_P(zendlval) = CG(heredoc_len);
yytext = CG(heredoc);
yyleng = CG(heredoc_len);
CG(heredoc) = NULL;
CG(heredoc_len) = 0;
BEGIN(ST_IN_SCRIPTING);
return T_END_NOWDOC;
}
%{
/* END nowdoc */
%}
<ST_DOUBLE_QUOTES>["] { <ST_DOUBLE_QUOTES>["] {
BEGIN(ST_IN_SCRIPTING); BEGIN(ST_IN_SCRIPTING);
return '"'; return '"';

View file

@ -180,7 +180,7 @@ static void tokenize(zval *return_value TSRMLS_DC)
MAKE_STD_ZVAL(keyword); MAKE_STD_ZVAL(keyword);
array_init(keyword); array_init(keyword);
add_next_index_long(keyword, token_type); add_next_index_long(keyword, token_type);
if (token_type == T_END_HEREDOC) { if (token_type == T_END_HEREDOC || token_type == T_END_NOWDOC) {
if (CG(increment_lineno)) { if (CG(increment_lineno)) {
token_line = ++CG(zend_lineno); token_line = ++CG(zend_lineno);
CG(increment_lineno) = 0; CG(increment_lineno) = 0;