# Trouble with zend_language_parser.y

- Thread: https://externals.io/message/60315
- Original archive: https://news-web.php.net/php.internals/60315
- Started by Clint Priest on 2012-04-26T03:41:07+00:00
- Messages: 6
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #60315 — Clint Priest — 2012-04-26T03:41:07+00:00

URL: https://externals.io/message/60315#60315

I'm having some trouble setting up the re2c to allow the isset/unset.  Here are the definitions, I've added the two `T_ISSET` statements:

------------------------------------------------------------
accessors:
                                accessor_function
                                accessor_function
                                accessor_function
                                accessor_function
                |              accessor_function
                                accessor_function
                                accessor_function
                |              accessor_function
                                accessor_function
                |              accessor_function
                | /* Empty */
;

accessor_modifiers:
                                /* empty */                                                                                       { Z_LVAL($$.u.constant) = CG(access_type); }
                |              non_empty_accessor_modifiers              { $$ = $1; }
;

non_empty_accessor_modifiers:
                                accessor_modifier                                                                                                                           { $$ = $1; }
                |              non_empty_accessor_modifiers accessor_modifier        { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); }


accessor_modifier:
                                `T_PUBLIC`                                                            { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
                |              `T_PROTECTED`                                                   { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
                |              `T_PRIVATE`                                                          { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
                |              `T_STATIC`                                                             { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
                |              `T_FINAL`                                                                               { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
;

accessor_function:
                                `T_ISSET` 
                                                { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC;  zend_do_begin_accessor_declaration(&$1, CG(accessor_node), &$$, 0 TSRMLS_CC); }
                                                                '{' inner_statement_list '}'
                                                { zend_do_end_accessor_declaration(&$1, CG(accessor_node), &$$, &$3 TSRMLS_CC); }
                |              `T_ISSET` 
                                {              Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC;
                                                zend_do_begin_accessor_declaration(&$1, CG(accessor_node), &$$, 0 TSRMLS_CC);
                                                zend_do_end_accessor_declaration(&$1, CG(accessor_node), &$$, `NULL` TSRMLS_CC);
                                }
                                ';'
                |              accessor_modifiers is_reference `T_STRING` 
                                                { zend_do_begin_accessor_declaration(&$3, CG(accessor_node), &$1, $2.op_type TSRMLS_CC); }
                                                                '{' inner_statement_list '}'
                                                { zend_do_end_accessor_declaration(&$3, CG(accessor_node), &$1, &$5 TSRMLS_CC); }
                |              accessor_modifiers is_reference `T_STRING` 
                                {
                                                zend_do_begin_accessor_declaration(&$3, CG(accessor_node), &$1, $2.op_type TSRMLS_CC);
                                                zend_do_end_accessor_declaration(&$3, CG(accessor_node), &$1, `NULL` TSRMLS_CC);
                                }
                                ';'
;------------------------------------------------------------

Here is the PHP it's trying to parse:

                public $Hours {
                                get {
                                                echo "Getting Hours\r\n";
                                                return $this->Seconds / 3600;
                                }
                                set { // The variable $value holds the incoming value to be "set"
                                                echo "Setting Hours to {$value}\r\n";
                                                $this->Seconds = $value * 3600;
                                }
                                isset { return $this->Seconds != NULL; }
                                unset { $this->Seconds = NULL; }
                }

$1 of the first `T_ISSET` is matching against "\n\t\tisset {..."  (... being the rest of the set body through to the end of the script.

What's going on here?

---

## #60423 — Clint Priest — 2012-05-02T13:23:43+00:00

URL: https://externals.io/message/60315#60423 · In reply to: #60315

Anyone have any help with this?

$1 of the first `T_ISSET` is matching against "\n\t\tisset {..."  (... being the rest of the set body through to the end of the script.

-----Original Message-----
From: Clint Priest [mailto:cpriest@zerocue.com] 
Sent: Wednesday, April 25, 2012 10:41 PM
To: internals@lists.php.net
Subject: [PHP-DEV] Trouble with zend_language_parser.y

I'm having some trouble setting up the re2c to allow the isset/unset.  Here are the definitions, I've added the two `T_ISSET` statements:

------------------------------------------------------------
accessors:
                                accessor_function
                                accessor_function
                                accessor_function
                                accessor_function
                |              accessor_function
                                accessor_function
                                accessor_function
                |              accessor_function
                                accessor_function
                |              accessor_function
                | /* Empty */
;

accessor_modifiers:
                                /* empty */                                                                                       { Z_LVAL($$.u.constant) = CG(access_type); }
                |              non_empty_accessor_modifiers              { $$ = $1; }
;

non_empty_accessor_modifiers:
                                accessor_modifier                                                                                                                           { $$ = $1; }
                |              non_empty_accessor_modifiers accessor_modifier        { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); }


accessor_modifier:
                                `T_PUBLIC`                                                            { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
                |              `T_PROTECTED`                                                   { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
                |              `T_PRIVATE`                                                          { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
                |              `T_STATIC`                                                             { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
                |              `T_FINAL`                                                                               { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
;

accessor_function:
                                `T_ISSET` 
                                                { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC;  zend_do_begin_accessor_declaration(&$1, CG(accessor_node), &$$, 0 TSRMLS_CC); }
                                                                '{' inner_statement_list '}'
                                                { zend_do_end_accessor_declaration(&$1, CG(accessor_node), &$$, &$3 TSRMLS_CC); }
                |              `T_ISSET` 
                                {              Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC;
                                                zend_do_begin_accessor_declaration(&$1, CG(accessor_node), &$$, 0 TSRMLS_CC);
                                                zend_do_end_accessor_declaration(&$1, CG(accessor_node), &$$, `NULL` TSRMLS_CC);
                                }
                                ';'
                |              accessor_modifiers is_reference `T_STRING` 
                                                { zend_do_begin_accessor_declaration(&$3, CG(accessor_node), &$1, $2.op_type TSRMLS_CC); }
                                                                '{' inner_statement_list '}'
                                                { zend_do_end_accessor_declaration(&$3, CG(accessor_node), &$1, &$5 TSRMLS_CC); }
                |              accessor_modifiers is_reference `T_STRING` 
                                {
                                                zend_do_begin_accessor_declaration(&$3, CG(accessor_node), &$1, $2.op_type TSRMLS_CC);
                                                zend_do_end_accessor_declaration(&$3, CG(accessor_node), &$1, `NULL` TSRMLS_CC);
                                }
                                ';'
;------------------------------------------------------------

Here is the PHP it's trying to parse:

                public $Hours {
                                get {
                                                echo "Getting Hours\r\n";
                                                return $this->Seconds / 3600;
                                }
                                set { // The variable $value holds the incoming value to be "set"
                                                echo "Setting Hours to {$value}\r\n";
                                                $this->Seconds = $value * 3600;
                                }
                                isset { return $this->Seconds != NULL; }
                                unset { $this->Seconds = NULL; }
                }

$1 of the first `T_ISSET` is matching against "\n\t\tisset {..."  (... being the rest of the set body through to the end of the script.

What's going on here?

---

## #60463 — Etienne Kneuss — 2012-05-05T15:07:20+00:00

URL: https://externals.io/message/60315#60463 · In reply to: #60423

Hi Clint,


> Anyone have any help with this?

hard to say like this with this partial patch, do you have some git
branch I can pull from to reproduce and analyze this?
Alternatively, the complete an up-to-date patch?

Best Regards,

---

## #60512 — Clint Priest — 2012-05-07T19:16:03+00:00

URL: https://externals.io/message/60315#60512 · In reply to: #60463

Alright, I'm new to git but I believe I have a branch off my fork which demonstrates the issue.

https://github.com/cpriest/php-src/tree/isset-unset-issue

This branch also features just code necessary to produce the results, if you search in zend_compile.h for ISSUE-ISSET-LANGUAGE-PARSER you'll see further contextual notes on what I'm seeing that's the issue.

It seems the function_token is getting the rest of the script stuffed into it.

> -----Original Message-----
> From: ekneuss@gmail.com [mailto:ekneuss@gmail.com] On Behalf Of Etienne Kneuss
> Sent: Saturday, May 05, 2012 10:07 AM
> To: Clint Priest
> Cc: internals@lists.php.net
> Subject: Re: [PHP-DEV] RE: Trouble with zend_language_parser.y
> 
> Hi Clint,
> 
> 
> > […]
> 
> hard to say like this with this partial patch, do you have some git branch I can pull from to reproduce and analyze this?
> Alternatively, the complete an up-to-date patch?
> 
> Best Regards,

---

## #60513 — Nikita Popov — 2012-05-07T19:26:31+00:00

URL: https://externals.io/message/60315#60513 · In reply to: #60512

> Alright, I'm new to git but I believe I have a branch off my fork which demonstrates the issue.
>
> https://github.com/cpriest/php-src/tree/isset-unset-issue
>
> This branch also features just code necessary to produce the results, if you search in zend_compile.h for ISSUE-ISSET-LANGUAGE-PARSER you'll see further contextual notes on what I'm seeing that's the issue.
>
> It seems the function_token is getting the rest of the script stuffed into it.
When you write $1 (where 1 references a terminal) you are accessing
the zendlval of the token. Not all tokens define an lval. Only tokens
which have a meaningful value (like numbers, strings, etc). So when
accessing the value of `T_ISSET` you just get some junk (as it does not
set a value).

Not sure that's really right, but that would be my guess :)

Nikita

---

## #60514 — Clint Priest — 2012-05-07T23:07:40+00:00

URL: https://externals.io/message/60315#60514 · In reply to: #60513

That makes complete sense, it is indeed a LONG type that's getting to that point, thank you!


> -----Original Message-----
> From: Nikita Popov [mailto:nikita.ppv@googlemail.com]
> Sent: Monday, May 07, 2012 2:27 PM
> To: Clint Priest
> Cc: Etienne Kneuss; Felipe Pena (felipensp@gmail.com); internals@lists.php.net
> Subject: Re: [PHP-DEV] RE: Trouble with zend_language_parser.y
> 
> 
> > […]
> PARSER you'll see further contextual notes on what I'm seeing that's the issue.
> > […]
> When you write $1 (where 1 references a terminal) you are accessing the zendlval of the token. Not all tokens define an lval. Only
> tokens which have a meaningful value (like numbers, strings, etc). So when accessing the value of `T_ISSET` you just get some junk (as
> it does not set a value).
> 
> Not sure that's really right, but that would be my guess :)
> 
> Nikita
