diff --git a/package-lock.json b/package-lock.json index 85f8f072d..b3494b96f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1364,6 +1364,114 @@ "minimist": "^1.2.0" } }, + "@gerhobbelt/ast-types": { + "version": "0.9.13-4", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-types/-/ast-types-0.9.13-4.tgz", + "integrity": "sha512-V8UIj1XN6XOP014fPpecxEa7AlAB9kaTOB/wF9UbguuwIMWCHDmdA9i03JDK9zXyVDVaLWCYh42JK8F9f27AtA==", + "dev": true + }, + "@gerhobbelt/ast-util": { + "version": "0.6.1-4", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-util/-/ast-util-0.6.1-4.tgz", + "integrity": "sha512-NP7YZh7rR6CNiMLyKTF+qb2Epx0r5x/zKQ3Z14TgXl73YJurC8WkMkFM9nDj8cRXb6R+f+BEu4DqAvvYKMxbqg==", + "dev": true, + "requires": { + "@gerhobbelt/ast-types": "0.9.13-4", + "private": "0.1.7" + }, + "dependencies": { + "private": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", + "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", + "dev": true + } + } + }, + "@gerhobbelt/linewrap": { + "version": "0.2.2-3", + "resolved": "https://registry.npmjs.org/@gerhobbelt/linewrap/-/linewrap-0.2.2-3.tgz", + "integrity": "sha512-u2eUbXgNtqckBI4gxds/uiUNoytT+qIqpePmVDI5isW8A18uB3Qz1P+UxAHgFafGOZWJNrpR0IKnZhl7QhaUng==", + "dev": true + }, + "@gerhobbelt/nomnom": { + "version": "1.8.4-24", + "resolved": "https://registry.npmjs.org/@gerhobbelt/nomnom/-/nomnom-1.8.4-24.tgz", + "integrity": "sha512-spzyz2vHd1BhYNSUMXjqJOwk4AjnOIzZz3cYCOryUCzMvlqz01/+SAPEy/pjT47CrOGdWd0JgemePjru1aLYgQ==", + "dev": true, + "requires": { + "@gerhobbelt/linewrap": "0.2.2-3", + "chalk": "2.1.0", + "exit": "0.1.2" + }, + "dependencies": { + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "@gerhobbelt/recast": { + "version": "0.13.0-24", + "resolved": "https://registry.npmjs.org/@gerhobbelt/recast/-/recast-0.13.0-24.tgz", + "integrity": "sha512-WqIAY+8RwgsgZHtJjeZJK3/w60uOMGOiW3Tcrm+gE31a3lcCjMnCgmYbauHLGCUYdRtepGS+jnr29ub3MFhKCg==", + "dev": true, + "requires": { + "@gerhobbelt/ast-types": "0.10.1-15", + "@gerhobbelt/esprima": "4.0.1-15", + "core-js": "2.5.3", + "private": "0.1.8", + "source-map": "0.6.1" + }, + "dependencies": { + "@gerhobbelt/ast-types": { + "version": "0.10.1-15", + "resolved": "https://registry.npmjs.org/@gerhobbelt/ast-types/-/ast-types-0.10.1-15.tgz", + "integrity": "sha512-CXoPKXH9xqCiWza0S/4TFjXa7aS8GAA8gYenBzhMN5+VwWDFBd2QVUGESq75nRe+yxgUkzSFQvq6rtAuQLRouA==", + "dev": true + }, + "@gerhobbelt/esprima": { + "version": "4.0.1-15", + "resolved": "https://registry.npmjs.org/@gerhobbelt/esprima/-/esprima-4.0.1-15.tgz", + "integrity": "sha512-0VITWyCsgbRlNv0WjWfEszAHcgJL/iAQKSNfzU/uoJ6S7W/mgM8q4iWmzv7BDl4nmRpcYoSqW2B/BwXJNFzNMg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@gerhobbelt/xregexp": { + "version": "3.2.0-22", + "resolved": "https://registry.npmjs.org/@gerhobbelt/xregexp/-/xregexp-3.2.0-22.tgz", + "integrity": "sha512-TRu38Z67VxFSMrBP3z/ORiJVQqp56ulidZirbobtmJnVGBWLdo4GbHtihgIJFGieIZuk+LxmPkK45SY+SQsR3A==", + "dev": true + }, "@jest/console": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", @@ -1851,7 +1959,7 @@ "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "integrity": "sha1-q6CrTF7uLUx500h9hUUPsjduuw8=", "dev": true }, "acorn": { @@ -2339,13 +2447,13 @@ "browser-process-hrtime": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "integrity": "sha1-YW8A+u8d9+wbW/nP4r3DFw8mx7Q=", "dev": true }, "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "integrity": "sha1-m3y7PQ9RDky4a9vXlhJNKLWJCvY=", "dev": true, "requires": { "resolve": "1.1.7" @@ -2715,6 +2823,12 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2836,6 +2950,12 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "dev": true + }, "core-js-compat": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.1.4.tgz", @@ -2983,7 +3103,7 @@ "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "integrity": "sha1-Fe4Fgrql4iu1nHcUDaj5x2lju/4=", "dev": true, "requires": { "abab": "^2.0.0", @@ -2994,7 +3114,7 @@ "whatwg-url": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "integrity": "sha1-/ekm+lSlmfOt+C3/Jan3vgLcbt0=", "dev": true, "requires": { "lodash.sortby": "^4.7.0", @@ -3156,7 +3276,7 @@ "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "integrity": "sha1-k3RCZEymoxJh7zbj7Gd/6AVYLJA=", "dev": true, "requires": { "webidl-conversions": "^4.0.2" @@ -3290,7 +3410,7 @@ "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", "dev": true, "requires": { "is-arrayish": "^0.2.1" @@ -3299,7 +3419,7 @@ "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=", "dev": true, "requires": { "es-to-primitive": "^1.2.0", @@ -3313,7 +3433,7 @@ "es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -3349,7 +3469,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -4771,7 +4891,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -4795,7 +4915,7 @@ "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -4912,7 +5032,7 @@ "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "integrity": "sha1-5w2EuU2lOqN14R/jo1G+ZkLKRvg=", "dev": true, "requires": { "whatwg-encoding": "^1.0.1" @@ -5173,7 +5293,7 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=", "dev": true }, "is-ci": { @@ -5316,7 +5436,7 @@ "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=", "dev": true, "requires": { "has-symbols": "^1.0.0" @@ -5970,7 +6090,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true } } @@ -6033,6 +6153,265 @@ } } }, + "jison-gho": { + "version": "0.6.1-216", + "resolved": "https://registry.npmjs.org/jison-gho/-/jison-gho-0.6.1-216.tgz", + "integrity": "sha512-sBwC7puJgM1ECfBX0dbHpNo0v0+Dz4vXPoEpxUSVH8m3BiNRYLYtJeACC5vm8ACK5F4bQWrcHNacrqcVrYnWqA==", + "dev": true, + "requires": { + "@gerhobbelt/ast-util": "0.6.1-4", + "@gerhobbelt/json5": "0.5.1-21", + "@gerhobbelt/nomnom": "1.8.4-24", + "@gerhobbelt/recast": "0.13.0-24", + "@gerhobbelt/xregexp": "3.2.0-22" + }, + "dependencies": { + "@gerhobbelt/json5": { + "version": "0.5.1-21", + "resolved": "https://registry.npmjs.org/@gerhobbelt/json5/-/json5-0.5.1-21.tgz", + "integrity": "sha512-BwqwZb2iv7Iu4nwJwj1D0LKvnvKxMVXB+VgTsrwb+s36KY/xYaTmKbFq0MAoEGiMBcB8jz3/L/J6lBBdx5XqAw==", + "dev": true, + "requires": { + "yargs": "10.0.3" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz", + "integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==", + "dev": true, + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.0.0" + } + }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -6130,7 +6509,7 @@ "jsdom": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "integrity": "sha1-GoDUDd03ih3lllbp5txaO6hle8g=", "dev": true, "requires": { "abab": "^2.0.0", @@ -6265,7 +6644,7 @@ "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "integrity": "sha1-W4o6d2Xf4AEmHd6RVYnngvjJTR4=", "dev": true }, "leven": { @@ -6941,6 +7320,12 @@ "path-key": "^2.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, "nwsapi": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", @@ -7237,7 +7622,7 @@ "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "integrity": "sha1-bXhlbj2o14tOwLkG98CO8d/j9gg=", "dev": true }, "pascalcase": { @@ -7343,7 +7728,7 @@ "pn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "integrity": "sha1-4vTO8OIZ9GPBeas3Rj5OHs3Muvs=", "dev": true }, "posix-character-classes": { @@ -7439,6 +7824,12 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, "psl": { "version": "1.1.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", @@ -7935,7 +8326,7 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", "dev": true }, "schema-utils": { @@ -8024,7 +8415,7 @@ "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "integrity": "sha1-1rkYHBpI05cyTISHHvvPxz/AZUs=", "dev": true }, "signal-exit": { @@ -8231,13 +8622,13 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc=", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -8879,7 +9270,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -9173,7 +9564,7 @@ "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=", "dev": true, "requires": { "define-properties": "^1.1.2", @@ -9195,7 +9586,7 @@ "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -9262,7 +9653,7 @@ "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "integrity": "sha1-qFWYCx8LazWbodXZ+zmulB+qY60=", "dev": true }, "webpack": { @@ -9472,7 +9863,7 @@ "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "integrity": "sha1-WrrPd3wyFmpR0IXWtPPn0nET3bA=", "dev": true, "requires": { "iconv-lite": "0.4.24" @@ -9487,7 +9878,7 @@ "whatwg-url": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "integrity": "sha1-8t8Cv/F2/WUHDfdK1cy7WhmZZag=", "dev": true, "requires": { "lodash.sortby": "^4.7.0", @@ -9593,7 +9984,7 @@ "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "integrity": "sha1-3/7xSGa46NyRM1glFNG++vlumA8=", "dev": true, "requires": { "async-limiter": "~1.0.0" @@ -9602,7 +9993,7 @@ "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "integrity": "sha1-auc+Bt5NjG5H+fsYH3jWSK1FfGo=", "dev": true }, "xmlcreate": { diff --git a/package.json b/package.json index 9a11874df..06024ee7b 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "eslint": "^5.15.0", "eslint-plugin-prettier": "^3.0.1", "jest": "^24.1.0", + "jison-gho": "^0.6.1-216", "jsdoc": "^3.5.5", "jsdoc-template": "^1.2.0", "prettier": "^1.16.4", diff --git a/poc/README.md b/poc/README.md new file mode 100644 index 000000000..e018743e1 --- /dev/null +++ b/poc/README.md @@ -0,0 +1,31 @@ +The idea is to batch the update of the parser by syncing with php source. + +# Goals / Requisites : + +1. Avoid updating by hand lexer or grammar +2. Avoid forking PHP files (just keep them in sync) +3. Having exactly the same behavior (precedence, expression parsing, error messages) +4. Have a decent parsing speed + +## PHP Parser from nikic + +First approach was to use the repository https://github.com/nikic/PHP-Parser/tree/master/grammar + +It will fail as it depends on php tokenizer launched from the php runtime, and it's too specific to the php runtime plateform. + +## PHP src files + +Second approch (in progress) is to : + +- [x] Download grammar from PHP src +- [ ] Automate C specific code +- [ ] Inject javascript code +- [ ] Generate lexer & grammar files +- [ ] Generate files with JISON + +Lexer Problems : +1. Stripping bison not supported tags - should be fine, but needs maintenance on future upgrades (breaks 1 pre-requisite) +2. Stripping C code - can be done but demands reimplementation (break 3 pre-requisite) + +Grammar Problems : +@todo \ No newline at end of file diff --git a/poc/bin/build.js b/poc/bin/build.js new file mode 100644 index 000000000..7ec8c4d64 --- /dev/null +++ b/poc/bin/build.js @@ -0,0 +1,46 @@ +#!/usr/bin/node + + +const http = require('https'); +const fs = require('fs'); +const lexer = require('../grammar/lexer'); + +// 1. Downloading lexer files from PHP +const files = { + "php7": { + "lexer.l": "https://raw.githubusercontent.com/php/php-src/master/Zend/zend_language_scanner.l", + "grammar.y": "https://raw.githubusercontent.com/php/php-src/master/Zend/zend_language_parser.y" + }, + "php5": { + "lexer.l": "https://raw.githubusercontent.com/php/php-src/PHP-5.6.40/Zend/zend_language_scanner.l", + "grammar.y": "https://raw.githubusercontent.com/php/php-src/PHP-5.6.40/Zend/zend_language_parser.y" + } +}; +const target = __dirname + '/../zend'; +const dl = []; +for(let ver in files) { + for(let type in files[ver]) { + dl.push(new Promise(function(version, filename, url, done, reject) { + return done(true); // disable the download + console.log('Downloading ' + filename + ' for ' + version); + const file = fs.createWriteStream(target + '/' + version + '/' + filename); + const request = http.get(url, function(response) { + response.pipe(file); + response.on('end', function() { + done(true); + }); + response.on('error', function(e) { + reject(e); + }); + }); + }.bind(this, ver, type, files[ver][type]))); + } +} +Promise.all(dl).then(function() { + console.log('Download is ready'); + // upgrading the lexer + lexer(target + '/php7/lexer.l', null); +}).catch(function(e) { + console.error(e); + process.exit(1); +}); diff --git a/poc/grammar/ctok.js b/poc/grammar/ctok.js new file mode 100644 index 000000000..a7a5e3f4a --- /dev/null +++ b/poc/grammar/ctok.js @@ -0,0 +1,123 @@ +const tokenizer = function(str) { + let tokens = []; + let state = 0; + let token = null; + var flush = function(nextState, init) { + if (state === nextState) { + token += init; + } else { + if (token) { + tokens.push([state, token]); + } + state = nextState; + token = init; + } + } + for(let i = 0; i < str.length; i++) { + let char = str[i]; + if (char === ' ' || char === '\t' || char === '\r' || char === '\n') { + if (state === tokenizer.STATE_WS) { + token += char; + } else { + flush(tokenizer.STATE_WS, char); + } + continue; + } + if (char === '"') { + flush(tokenizer.STATE_TXT, char); + while(i < str.length) { + if (str[++i] === "\\") { + i++; + token += "\\" + str[i]; + } else { + token += str[i]; + } + if (str[i] === '"') break; + } + flush(); + continue; + } + if (char === '\'') { + flush(tokenizer.STATE_TXT, char); + while(i < str.length) { + if (str[++i] === "\\") { + i++; + token += "\\" + str[i]; + } else { + token += str[i]; + } + if (str[i] === '\'') break; + } + flush(); + continue; + } + + let ch = str.charCodeAt(i); + if ( + (ch > 96 && ch < 123) || + (ch > 64 && ch < 91) || + ch === 95 || + (ch > 47 && ch < 58) || + ch > 126 + ) { + if (state === tokenizer.STATE_ID) { + token += char; + } else { + flush(tokenizer.STATE_ID, char); + } + continue; + } + + if (token === '/') { + let next = str[i + 1]; + if (next === '/') { + flush(tokenizer.STATE_COM, char); + while(i < str.length) { + token += str[++i]; + if (str[i] === '\r') break; + if (str[i] === '\n') break; + } + flush(); + continue; + } + if (next === '*') { + flush(tokenizer.STATE_COM, char); + while(i < str.length) { + token += str[++i]; + if (str[i] === '*') { + token += str[++i]; + if (str[i] === '/') break; + } + } + flush(); + continue; + } + } + + if (token === '#') { + flush(tokenizer.STATE_DIR, char); + while(i < str.length) { + token += str[++i]; + if (str[i] === '\r') break; + if (str[i] === '\n') break; + } + flush(); + continue; + } + if (token) { + flush(tokenizer.STATE_OTHER, null); + } + tokens.push([tokenizer.STATE_OTHER, char]); + } + flush(); + return tokens; +}; + +tokenizer.STATE_WS = "whitespace"; +tokenizer.STATE_ID = "identifier"; +tokenizer.STATE_COM = "comment"; +tokenizer.STATE_TXT = "string"; +tokenizer.STATE_OTHER = "any"; +tokenizer.STATE_DIR = "directive"; + +module.exports = tokenizer; \ No newline at end of file diff --git a/poc/grammar/lexer.js b/poc/grammar/lexer.js new file mode 100644 index 000000000..aeed2aeca --- /dev/null +++ b/poc/grammar/lexer.js @@ -0,0 +1,60 @@ +/** + * This module open a lexer file and extract it's parts + */ +const lexer = require('jison-gho').lexParser; +const fs = require('fs'); +const tokenize = require('./ctok'); +module.exports = function(filename, destination) { + fs.readFile(filename, function(err, contents) { + contents = contents.toString(); + // remove header / footer + let header = contents.indexOf('/*!re2c'); + let footer = contents.indexOf('\n*/\n', header); + contents = contents.substring(header + 7, footer); + // remove macro + contents = contents.replace('re2c:yyfill:check = 0;', ''); + // remove trigger on states + contents = contents.replace(/\<\!\*\>[^;]+;\n*/g, ''); + // handle script blocks + contents = contents.replace(/(\<[^\>]+[^\n]+)\s+{\n*/g, '$1 %{\n'); + contents = contents.replace(/\n+\}\n/g, '\n%}\n'); + + // locate macros + let macro = contents.indexOf('\n<'); + contents = contents.substring(0, macro) + '\n%options case-insensitive\n\n%%\n\n' + contents.substring(macro + 1); + + // migrate each macro + let lexerTokens = []; + contents = contents.replace(/^(\<.*?\>)([^\n]+)\s+\%\{(.*?)\%\}/gms, function(text, state, tag, script) { + console.log(script); + let src = ''; + const tokens = tokenize(script); + for(let i = 0; i < tokens.length; i++) { + let token = tokens[i]; + switch(token[1]) { + case 'RETURN_TOKEN': + let tok = tokens[i + 2][1]; + src += 'return ' + tok + ';'; + if (lexerTokens.indexOf(tok) === -1) { + lexerTokens.push(tok); + } + i += 4; + break; + case 'goto': + // ignore goto + i += 3; + break; + default: + src += token[1]; + } + } + return state + tag + '\t{ \n ' + src + '\n}'; + }); + try { + const ast = lexer.parse(contents); + console.log(ast); + } catch(e) { + console.error(e.message); + } + }); +}; \ No newline at end of file diff --git a/poc/zend/php5/grammar.y b/poc/zend/php5/grammar.y new file mode 100644 index 000000000..0920eeb9e --- /dev/null +++ b/poc/zend/php5/grammar.y @@ -0,0 +1,1375 @@ +%{ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* + * LALR shift/reduce conflicts and how they are resolved: + * + * - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift. + * + */ + + +#include "zend_compile.h" +#include "zend.h" +#include "zend_list.h" +#include "zend_globals.h" +#include "zend_API.h" +#include "zend_constants.h" + +#define YYSIZE_T size_t +#define yytnamerr zend_yytnamerr +static YYSIZE_T zend_yytnamerr(char*, const char*); + +#define YYERROR_VERBOSE +#define YYSTYPE znode + +%} + +%pure_parser +%expect 3 + +%code requires { +#ifdef ZTS +# define YYPARSE_PARAM tsrm_ls +# define YYLEX_PARAM tsrm_ls +#endif +} + +%token END 0 "end of file" +%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE +%token T_INCLUDE "include (T_INCLUDE)" +%token T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)" +%token T_EVAL "eval (T_EVAL)" +%token T_REQUIRE "require (T_REQUIRE)" +%token T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)" +%left ',' +%left T_LOGICAL_OR +%token T_LOGICAL_OR "or (T_LOGICAL_OR)" +%left T_LOGICAL_XOR +%token T_LOGICAL_XOR "xor (T_LOGICAL_XOR)" +%left T_LOGICAL_AND +%token T_LOGICAL_AND "and (T_LOGICAL_AND)" +%right T_PRINT +%token T_PRINT "print (T_PRINT)" +%right T_YIELD +%token T_YIELD "yield (T_YIELD)" +%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL +%token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)" +%token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)" +%token T_MUL_EQUAL "*= (T_MUL_EQUAL)" +%token T_DIV_EQUAL "/= (T_DIV_EQUAL)" +%token T_CONCAT_EQUAL ".= (T_CONCAT_EQUAL)" +%token T_MOD_EQUAL "%= (T_MOD_EQUAL)" +%token T_AND_EQUAL "&= (T_AND_EQUAL)" +%token T_OR_EQUAL "|= (T_OR_EQUAL)" +%token T_XOR_EQUAL "^= (T_XOR_EQUAL)" +%token T_SL_EQUAL "<<= (T_SL_EQUAL)" +%token T_SR_EQUAL ">>= (T_SR_EQUAL)" +%left '?' ':' +%left T_BOOLEAN_OR +%token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)" +%left T_BOOLEAN_AND +%token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)" +%left '|' +%left '^' +%left '&' +%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL +%token T_IS_EQUAL "== (T_IS_EQUAL)" +%token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)" +%token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)" +%token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)" +%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL +%token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)" +%token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)" +%left T_SL T_SR +%token T_SL "<< (T_SL)" +%token T_SR ">> (T_SR)" +%left '+' '-' '.' +%left '*' '/' '%' +%right '!' +%nonassoc T_INSTANCEOF +%token T_INSTANCEOF "instanceof (T_INSTANCEOF)" +%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' +%right T_POW +%token T_INC "++ (T_INC)" +%token T_DEC "-- (T_DEC)" +%token T_INT_CAST "(int) (T_INT_CAST)" +%token T_DOUBLE_CAST "(double) (T_DOUBLE_CAST)" +%token T_STRING_CAST "(string) (T_STRING_CAST)" +%token T_ARRAY_CAST "(array) (T_ARRAY_CAST)" +%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)" +%token T_BOOL_CAST "(bool) (T_BOOL_CAST)" +%token T_UNSET_CAST "(unset) (T_UNSET_CAST)" +%right '[' +%nonassoc T_NEW T_CLONE +%token T_NEW "new (T_NEW)" +%token T_CLONE "clone (T_CLONE)" +%token T_EXIT "exit (T_EXIT)" +%token T_IF "if (T_IF)" +%left T_ELSEIF +%token T_ELSEIF "elseif (T_ELSEIF)" +%left T_ELSE +%token T_ELSE "else (T_ELSE)" +%left T_ENDIF +%token T_ENDIF "endif (T_ENDIF)" +%token T_LNUMBER "integer number (T_LNUMBER)" +%token T_DNUMBER "floating-point number (T_DNUMBER)" +%token T_STRING "identifier (T_STRING)" +%token T_STRING_VARNAME "variable name (T_STRING_VARNAME)" +%token T_VARIABLE "variable (T_VARIABLE)" +%token T_NUM_STRING "number (T_NUM_STRING)" +%token T_INLINE_HTML +%token T_CHARACTER +%token T_BAD_CHARACTER +%token T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)" +%token T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)" +%token T_ECHO "echo (T_ECHO)" +%token T_DO "do (T_DO)" +%token T_WHILE "while (T_WHILE)" +%token T_ENDWHILE "endwhile (T_ENDWHILE)" +%token T_FOR "for (T_FOR)" +%token T_ENDFOR "endfor (T_ENDFOR)" +%token T_FOREACH "foreach (T_FOREACH)" +%token T_ENDFOREACH "endforeach (T_ENDFOREACH)" +%token T_DECLARE "declare (T_DECLARE)" +%token T_ENDDECLARE "enddeclare (T_ENDDECLARE)" +%token T_AS "as (T_AS)" +%token T_SWITCH "switch (T_SWITCH)" +%token T_ENDSWITCH "endswitch (T_ENDSWITCH)" +%token T_CASE "case (T_CASE)" +%token T_DEFAULT "default (T_DEFAULT)" +%token T_BREAK "break (T_BREAK)" +%token T_CONTINUE "continue (T_CONTINUE)" +%token T_GOTO "goto (T_GOTO)" +%token T_FUNCTION "function (T_FUNCTION)" +%token T_CONST "const (T_CONST)" +%token T_RETURN "return (T_RETURN)" +%token T_TRY "try (T_TRY)" +%token T_CATCH "catch (T_CATCH)" +%token T_FINALLY "finally (T_FINALLY)" +%token T_THROW "throw (T_THROW)" +%token T_USE "use (T_USE)" +%token T_INSTEADOF "insteadof (T_INSTEADOF)" +%token T_GLOBAL "global (T_GLOBAL)" +%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC +%token T_STATIC "static (T_STATIC)" +%token T_ABSTRACT "abstract (T_ABSTRACT)" +%token T_FINAL "final (T_FINAL)" +%token T_PRIVATE "private (T_PRIVATE)" +%token T_PROTECTED "protected (T_PROTECTED)" +%token T_PUBLIC "public (T_PUBLIC)" +%token T_VAR "var (T_VAR)" +%token T_UNSET "unset (T_UNSET)" +%token T_ISSET "isset (T_ISSET)" +%token T_EMPTY "empty (T_EMPTY)" +%token T_HALT_COMPILER "__halt_compiler (T_HALT_COMPILER)" +%token T_CLASS "class (T_CLASS)" +%token T_TRAIT "trait (T_TRAIT)" +%token T_INTERFACE "interface (T_INTERFACE)" +%token T_EXTENDS "extends (T_EXTENDS)" +%token T_IMPLEMENTS "implements (T_IMPLEMENTS)" +%token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)" +%token T_DOUBLE_ARROW "=> (T_DOUBLE_ARROW)" +%token T_LIST "list (T_LIST)" +%token T_ARRAY "array (T_ARRAY)" +%token T_CALLABLE "callable (T_CALLABLE)" +%token T_CLASS_C "__CLASS__ (T_CLASS_C)" +%token T_TRAIT_C "__TRAIT__ (T_TRAIT_C)" +%token T_METHOD_C "__METHOD__ (T_METHOD_C)" +%token T_FUNC_C "__FUNCTION__ (T_FUNC_C)" +%token T_LINE "__LINE__ (T_LINE)" +%token T_FILE "__FILE__ (T_FILE)" +%token T_COMMENT "comment (T_COMMENT)" +%token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)" +%token T_OPEN_TAG "open tag (T_OPEN_TAG)" +%token T_OPEN_TAG_WITH_ECHO "open tag with echo (T_OPEN_TAG_WITH_ECHO)" +%token T_CLOSE_TAG "close tag (T_CLOSE_TAG)" +%token T_WHITESPACE "whitespace (T_WHITESPACE)" +%token T_START_HEREDOC "heredoc start (T_START_HEREDOC)" +%token T_END_HEREDOC "heredoc end (T_END_HEREDOC)" +%token T_DOLLAR_OPEN_CURLY_BRACES "${ (T_DOLLAR_OPEN_CURLY_BRACES)" +%token T_CURLY_OPEN "{$ (T_CURLY_OPEN)" +%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)" +%token T_NAMESPACE "namespace (T_NAMESPACE)" +%token T_NS_C "__NAMESPACE__ (T_NS_C)" +%token T_DIR "__DIR__ (T_DIR)" +%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)" +%token T_ELLIPSIS "... (T_ELLIPSIS)" +%token T_POW "** (T_POW)" +%token T_POW_EQUAL "**= (T_POW_EQUAL)" + +%% /* Rules */ + +start: + top_statement_list { zend_do_end_compilation(TSRMLS_C); } +; + +top_statement_list: + top_statement_list { zend_do_extended_info(TSRMLS_C); } top_statement { HANDLE_INTERACTIVE(); } + | /* empty */ +; + +namespace_name: + T_STRING { $$ = $1; } + | namespace_name T_NS_SEPARATOR T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); } +; + +top_statement: + statement { zend_verify_namespace(TSRMLS_C); } + | function_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); } + | class_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); } + | T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; } + | T_NAMESPACE namespace_name ';' { zend_do_begin_namespace(&$2, 0 TSRMLS_CC); } + | T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$2, 1 TSRMLS_CC); } + top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); } + | T_NAMESPACE '{' { zend_do_begin_namespace(NULL, 1 TSRMLS_CC); } + top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); } + | T_USE use_declarations ';' { zend_verify_namespace(TSRMLS_C); } + | T_USE T_FUNCTION use_function_declarations ';' { zend_verify_namespace(TSRMLS_C); } + | T_USE T_CONST use_const_declarations ';' { zend_verify_namespace(TSRMLS_C); } + | constant_declaration ';' { zend_verify_namespace(TSRMLS_C); } +; + +use_declarations: + use_declarations ',' use_declaration + | use_declaration +; + +use_declaration: + namespace_name { zend_do_use(&$1, NULL TSRMLS_CC); } + | namespace_name T_AS T_STRING { zend_do_use(&$1, &$3 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { zend_do_use(&$2, NULL TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4 TSRMLS_CC); } +; + +use_function_declarations: + use_function_declarations ',' use_function_declaration + | use_function_declaration +; + +use_function_declaration: + namespace_name { zend_do_use_function(&$1, NULL TSRMLS_CC); } + | namespace_name T_AS T_STRING { zend_do_use_function(&$1, &$3 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { zend_do_use_function(&$2, NULL TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_function(&$2, &$4 TSRMLS_CC); } +; + +use_const_declarations: + use_const_declarations ',' use_const_declaration + | use_const_declaration +; + +use_const_declaration: + namespace_name { zend_do_use_const(&$1, NULL TSRMLS_CC); } + | namespace_name T_AS T_STRING { zend_do_use_const(&$1, &$3 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { zend_do_use_const(&$2, NULL TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_const(&$2, &$4 TSRMLS_CC); } +; + +constant_declaration: + constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); } + | T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); } +; + +inner_statement_list: + inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); } + | /* empty */ +; + + +inner_statement: + statement + | function_declaration_statement + | class_declaration_statement + | T_HALT_COMPILER '(' ')' ';' { zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); } +; + + +statement: + unticked_statement { DO_TICKS(); } + | T_STRING ':' { zend_do_label(&$1 TSRMLS_CC); } +; + +unticked_statement: + '{' inner_statement_list '}' + | T_IF parenthesis_expr { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); } + | T_IF parenthesis_expr ':' { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); } + | T_WHILE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr { zend_do_while_cond(&$3, &$$ TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$4 TSRMLS_CC); } + | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE { $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr ';' { zend_do_do_while_end(&$1, &$4, &$6 TSRMLS_CC); } + | T_FOR + '(' + for_expr + ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } + for_expr + ';' { zend_do_extended_info(TSRMLS_C); zend_do_for_cond(&$6, &$7 TSRMLS_CC); } + for_expr + ')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); } + for_statement { zend_do_for_end(&$7 TSRMLS_CC); } + | T_SWITCH parenthesis_expr { zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); } + | T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); } + | T_BREAK expr ';' { zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); } + | T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); } + | T_CONTINUE expr ';' { zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); } + | T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); } + | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); } + | T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); } + | yield_expr ';' { zend_do_free(&$1 TSRMLS_CC); } + | T_GLOBAL global_var_list ';' + | T_STATIC static_var_list ';' + | T_ECHO echo_expr_list ';' + | T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); } + | expr ';' { zend_do_free(&$1 TSRMLS_CC); } + | T_UNSET '(' unset_variables ')' ';' + | T_FOREACH '(' variable T_AS + { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); } + foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } + foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } + | T_FOREACH '(' expr_without_variable T_AS + { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); } + foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } + foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } + | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); } + | ';' /* empty statement */ + | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}' + catch_statement { zend_do_bind_catch(&$1, &$6 TSRMLS_CC); } + finally_statement { zend_do_end_finally(&$1, &$6, &$8 TSRMLS_CC); } + | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } + | T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); } +; + +catch_statement: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); } + fully_qualified_class_name { zend_do_first_catch(&$2 TSRMLS_CC); } + T_VARIABLE ')' { zend_do_begin_catch(&$1, &$4, &$6, &$2 TSRMLS_CC); } + '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } + additional_catches { zend_do_mark_last_catch(&$2, &$13 TSRMLS_CC); $$ = $1;} + +finally_statement: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_FINALLY { zend_do_finally(&$1 TSRMLS_CC); } '{' inner_statement_list '}' { $$ = $1; } +; + +additional_catches: + non_empty_additional_catches { $$ = $1; } + | /* empty */ { $$.u.op.opline_num = -1; } +; + +non_empty_additional_catches: + additional_catch { $$ = $1; } + | non_empty_additional_catches additional_catch { $$ = $2; } +; + +additional_catch: + T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } +; + +unset_variables: + unset_variable + | unset_variables ',' unset_variable +; + +unset_variable: + variable { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); } +; + +function_declaration_statement: + unticked_function_declaration_statement { DO_TICKS(); } +; + +class_declaration_statement: + unticked_class_declaration_statement { DO_TICKS(); } +; + +is_reference: + /* empty */ { $$.op_type = 0; } + | '&' { $$.op_type = 1; } +; + +is_variadic: + /* empty */ { $$.op_type = 0; } + | T_ELLIPSIS { $$.op_type = 1; } +; + +unticked_function_declaration_statement: + function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); } + '(' parameter_list ')' + '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } +; + +unticked_class_declaration_statement: + class_entry_type T_STRING extends_from + { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } + implements_list + '{' + class_statement_list + '}' { zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); } + | interface_entry T_STRING + { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } + interface_extends_list + '{' + class_statement_list + '}' { zend_do_end_class_declaration(&$1, NULL TSRMLS_CC); } +; + + +class_entry_type: + T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = 0; } + | T_ABSTRACT T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; } + | T_TRAIT { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_TRAIT; } + | T_FINAL T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_FINAL_CLASS; } +; + +extends_from: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_EXTENDS fully_qualified_class_name { zend_do_fetch_class(&$$, &$2 TSRMLS_CC); } +; + +interface_entry: + T_INTERFACE { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_INTERFACE; } +; + +interface_extends_list: + /* empty */ + | T_EXTENDS interface_list +; + +implements_list: + /* empty */ + | T_IMPLEMENTS interface_list +; + +interface_list: + fully_qualified_class_name { zend_do_implements_interface(&$1 TSRMLS_CC); } + | interface_list ',' fully_qualified_class_name { zend_do_implements_interface(&$3 TSRMLS_CC); } +; + +foreach_optional_arg: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_DOUBLE_ARROW foreach_variable { $$ = $2; } +; + +foreach_variable: + variable { zend_check_writable_variable(&$1); $$ = $1; } + | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; } + | T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; } +; + +for_statement: + statement + | ':' inner_statement_list T_ENDFOR ';' +; + + +foreach_statement: + statement + | ':' inner_statement_list T_ENDFOREACH ';' +; + + +declare_statement: + statement + | ':' inner_statement_list T_ENDDECLARE ';' +; + + +declare_list: + T_STRING '=' static_scalar { zend_do_declare_stmt(&$1, &$3 TSRMLS_CC); } + | declare_list ',' T_STRING '=' static_scalar { zend_do_declare_stmt(&$3, &$5 TSRMLS_CC); } +; + + +switch_case_list: + '{' case_list '}' { $$ = $2; } + | '{' ';' case_list '}' { $$ = $3; } + | ':' case_list T_ENDSWITCH ';' { $$ = $2; } + | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } +; + + +case_list: + /* empty */ { $$.op_type = IS_UNUSED; } + | case_list T_CASE expr case_separator { zend_do_extended_info(TSRMLS_C); zend_do_case_before_statement(&$1, &$2, &$3 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; } + | case_list T_DEFAULT case_separator { zend_do_extended_info(TSRMLS_C); zend_do_default_before_statement(&$1, &$2 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; } +; + + +case_separator: + ':' + | ';' +; + + +while_statement: + statement + | ':' inner_statement_list T_ENDWHILE ';' +; + + + +elseif_list: + /* empty */ + | elseif_list T_ELSEIF parenthesis_expr { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); } +; + + +new_elseif_list: + /* empty */ + | new_elseif_list T_ELSEIF parenthesis_expr ':' { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); } +; + + +else_single: + /* empty */ + | T_ELSE statement +; + + +new_else_single: + /* empty */ + | T_ELSE ':' inner_statement_list +; + + +parameter_list: + non_empty_parameter_list + | /* empty */ +; + + +non_empty_parameter_list: + parameter + | non_empty_parameter_list ',' parameter +; + +parameter: + optional_class_type is_reference is_variadic T_VARIABLE + { zend_do_receive_param(ZEND_RECV, &$4, NULL, &$1, $2.op_type, $3.op_type TSRMLS_CC); } + | optional_class_type is_reference is_variadic T_VARIABLE '=' static_scalar + { zend_do_receive_param(ZEND_RECV_INIT, &$4, &$6, &$1, $2.op_type, $3.op_type TSRMLS_CC); } +; + + +optional_class_type: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; } + | T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; } + | fully_qualified_class_name { $$ = $1; } +; + + +function_call_parameter_list: + '(' ')' { Z_LVAL($$.u.constant) = 0; } + | '(' non_empty_function_call_parameter_list ')' { $$ = $2; } + | '(' yield_expr ')' { zend_do_pass_param(&$2, ZEND_SEND_VAL TSRMLS_CC); } +; + + +non_empty_function_call_parameter_list: + function_call_parameter + | non_empty_function_call_parameter_list ',' function_call_parameter +; + +function_call_parameter: + expr_without_variable { zend_do_pass_param(&$1, ZEND_SEND_VAL TSRMLS_CC); } + | variable { zend_do_pass_param(&$1, ZEND_SEND_VAR TSRMLS_CC); } + | '&' w_variable { zend_do_pass_param(&$2, ZEND_SEND_REF TSRMLS_CC); } + | T_ELLIPSIS expr { zend_do_unpack_params(&$2 TSRMLS_CC); } +; + +global_var_list: + global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); } + | global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); } +; + + +global_var: + T_VARIABLE { $$ = $1; } + | '$' r_variable { $$ = $2; } + | '$' '{' expr '}' { $$ = $3; } +; + + +static_var_list: + static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } + | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); } + | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } + | T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); } + +; + + +class_statement_list: + class_statement_list class_statement + | /* empty */ +; + + +class_statement: + variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';' + | class_constant_declaration ';' + | trait_use_statement + | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } + '(' parameter_list ')' + method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); } +; + +trait_use_statement: + T_USE trait_list trait_adaptations +; + +trait_list: + fully_qualified_class_name { zend_do_use_trait(&$1 TSRMLS_CC); } + | trait_list ',' fully_qualified_class_name { zend_do_use_trait(&$3 TSRMLS_CC); } +; + +trait_adaptations: + ';' + | '{' trait_adaptation_list '}' +; + +trait_adaptation_list: + /* empty */ + | non_empty_trait_adaptation_list +; + +non_empty_trait_adaptation_list: + trait_adaptation_statement + | non_empty_trait_adaptation_list trait_adaptation_statement +; + +trait_adaptation_statement: + trait_precedence ';' + | trait_alias ';' +; + +trait_precedence: + trait_method_reference_fully_qualified T_INSTEADOF trait_reference_list { zend_add_trait_precedence(&$1, &$3 TSRMLS_CC); } +; + +trait_reference_list: + fully_qualified_class_name { zend_resolve_class_name(&$1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STRVAL($1.u.constant) TSRMLS_CC); } + | trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STRVAL($3.u.constant) TSRMLS_CC); $$ = $1; } +; + +trait_method_reference: + T_STRING { zend_prepare_reference(&$$, NULL, &$1 TSRMLS_CC); } + | trait_method_reference_fully_qualified { $$ = $1; } +; + +trait_method_reference_fully_qualified: + fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_prepare_reference(&$$, &$1, &$3 TSRMLS_CC); } +; + +trait_alias: + trait_method_reference T_AS trait_modifiers T_STRING { zend_add_trait_alias(&$1, &$3, &$4 TSRMLS_CC); } + | trait_method_reference T_AS member_modifier { zend_add_trait_alias(&$1, &$3, NULL TSRMLS_CC); } +; + +trait_modifiers: + /* empty */ { Z_LVAL($$.u.constant) = 0x0; } /* No change of methods visibility */ + | member_modifier { $$ = $1; } /* REM: Keep in mind, there are not only visibility modifiers */ +; + +method_body: + ';' /* abstract method */ { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; } + | '{' inner_statement_list '}' { Z_LVAL($$.u.constant) = 0; } +; + +variable_modifiers: + non_empty_member_modifiers { $$ = $1; } + | T_VAR { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } +; + +method_modifiers: + /* empty */ { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; } + | non_empty_member_modifiers { $$ = $1; if (!(Z_LVAL($$.u.constant) & ZEND_ACC_PPP_MASK)) { Z_LVAL($$.u.constant) |= ZEND_ACC_PUBLIC; } } +; + +non_empty_member_modifiers: + member_modifier { $$ = $1; } + | non_empty_member_modifiers member_modifier { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); } +; + +member_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_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; } + | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; } +; + +class_variable_declaration: + class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } + | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } + | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); } + | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); } +; + +class_constant_declaration: + class_constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); } + | T_CONST T_STRING '=' static_scalar { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); } +; + +echo_expr_list: + echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); } + | expr { zend_do_echo(&$1 TSRMLS_CC); } +; + + +for_expr: + /* empty */ { $$.op_type = IS_CONST; Z_TYPE($$.u.constant) = IS_BOOL; Z_LVAL($$.u.constant) = 1; } + | non_empty_for_expr { $$ = $1; } +; + +non_empty_for_expr: + non_empty_for_expr ',' { zend_do_free(&$1 TSRMLS_CC); } expr { $$ = $4; } + | expr { $$ = $1; } +; + +chaining_method_or_property: + chaining_method_or_property variable_property { $$.EA = $2.EA; } + | variable_property { $$.EA = $1.EA; } +; + +chaining_dereference: + chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); } +; + +chaining_instance_call: + chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; } + | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; } + | chaining_method_or_property { $$ = $1; } +; + +instance_call: + /* empty */ { $$ = $0; } + | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); } + chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); } +; + +new_expr: + T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} +; + +expr_without_variable: + T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); } + | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); } + | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } + | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } + | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); } + | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_POW_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_POW, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); } + | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); } + | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); } + | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); } + | T_DEC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); } + | expr T_BOOLEAN_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } + | expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } + | expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } + | expr T_LOGICAL_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } + | expr T_LOGICAL_XOR expr { zend_do_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 TSRMLS_CC); } + | expr '|' expr { zend_do_binary_op(ZEND_BW_OR, &$$, &$1, &$3 TSRMLS_CC); } + | expr '&' expr { zend_do_binary_op(ZEND_BW_AND, &$$, &$1, &$3 TSRMLS_CC); } + | expr '^' expr { zend_do_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); } + | expr '.' expr { zend_do_binary_op(ZEND_CONCAT, &$$, &$1, &$3 TSRMLS_CC); } + | expr '+' expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); } + | expr '-' expr { zend_do_binary_op(ZEND_SUB, &$$, &$1, &$3 TSRMLS_CC); } + | expr '*' expr { zend_do_binary_op(ZEND_MUL, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_POW expr { zend_do_binary_op(ZEND_POW, &$$, &$1, &$3 TSRMLS_CC); } + | expr '/' expr { zend_do_binary_op(ZEND_DIV, &$$, &$1, &$3 TSRMLS_CC); } + | expr '%' expr { zend_do_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_SL expr { zend_do_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_SR expr { zend_do_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); } + | '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } } + | '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } } + | '!' expr { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$2 TSRMLS_CC); } + | '~' expr { zend_do_unary_op(ZEND_BW_NOT, &$$, &$2 TSRMLS_CC); } + | expr T_IS_IDENTICAL expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); } + | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); } + | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); } + | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); } + | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); } + | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } + | parenthesis_expr { $$ = $1; } + | new_expr { $$ = $1; } + | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; } + | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } + expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } + expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); } + | expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); } + expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); } + | internal_functions_in_yacc { $$ = $1; } + | T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); } + | T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); } + | T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); } + | T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); } + | T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); } + | T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); } + | T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); } + | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); } + | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; } + | scalar { $$ = $1; } + | combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } + | combined_scalar { $$ = $1; } + | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); } + | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); } + | T_YIELD { zend_do_yield(&$$, NULL, NULL, 0 TSRMLS_CC); } + | function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); } + '(' parameter_list ')' lexical_vars + '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $3; } + | T_STATIC function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); } + '(' parameter_list ')' lexical_vars + '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $4; } +; + +yield_expr: + T_YIELD expr_without_variable { zend_do_yield(&$$, &$2, NULL, 0 TSRMLS_CC); } + | T_YIELD variable { zend_do_yield(&$$, &$2, NULL, 1 TSRMLS_CC); } + | T_YIELD expr T_DOUBLE_ARROW expr_without_variable { zend_do_yield(&$$, &$4, &$2, 0 TSRMLS_CC); } + | T_YIELD expr T_DOUBLE_ARROW variable { zend_do_yield(&$$, &$4, &$2, 1 TSRMLS_CC); } +; + +combined_scalar_offset: + combined_scalar '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | combined_scalar_offset '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $1.EA = 0; zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | general_constant '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } +; + +combined_scalar: + T_ARRAY '(' array_pair_list ')' { $$ = $3; } + | '[' array_pair_list ']' { $$ = $2; } +; + +function: + T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); } +; + +lexical_vars: + /* empty */ + | T_USE '(' lexical_var_list ')' +; + +lexical_var_list: + lexical_var_list ',' T_VARIABLE { zend_do_fetch_lexical_variable(&$3, 0 TSRMLS_CC); } + | lexical_var_list ',' '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$4, 1 TSRMLS_CC); } + | T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); } + | '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); } +; + +function_call: + namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $$.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | T_NS_SEPARATOR namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$2, &$$, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} +; + +class_name: + T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1, 1);} + | namespace_name { $$ = $1; } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; } +; + +fully_qualified_class_name: + namespace_name { $$ = $1; } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; } +; + + + +class_name_reference: + class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } +; + + +dynamic_class_name_reference: + base_variable T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); } + object_property { zend_do_push_object(&$4 TSRMLS_CC); } dynamic_class_name_variable_properties + { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; } + | base_variable { $$ = $1; } +; + + +dynamic_class_name_variable_properties: + dynamic_class_name_variable_properties dynamic_class_name_variable_property + | /* empty */ +; + + +dynamic_class_name_variable_property: + T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } +; + +exit_expr: + /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; } + | '(' ')' { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; } + | parenthesis_expr { $$ = $1; } +; + +backticks_expr: + /* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; } + | T_ENCAPSED_AND_WHITESPACE { $$ = $1; } + | encaps_list { $$ = $1; } +; + + +ctor_arguments: + /* empty */ { Z_LVAL($$.u.constant) = 0; } + | function_call_parameter_list { $$ = $1; } +; + + +common_scalar: + T_LNUMBER { $$ = $1; } + | T_DNUMBER { $$ = $1; } + | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } + | T_LINE { $$ = $1; } + | T_FILE { $$ = $1; } + | T_DIR { $$ = $1; } + | T_TRAIT_C { $$ = $1; } + | T_METHOD_C { $$ = $1; } + | T_FUNC_C { $$ = $1; } + | T_NS_C { $$ = $1; } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; } + | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; } +; + +static_class_constant: + class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); } +; + +static_scalar: /* compile-time evaluated scalars */ + static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); } +; + +static_scalar_value: + common_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } + | static_class_name_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } + | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } + | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } + | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; } + | '[' static_array_pair_list ']' { $$ = $2; } + | static_class_constant { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } + | T_CLASS_C { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } + | static_operation { $$ = $1; } +; + +static_operation: + static_scalar_value '[' static_scalar_value ']' { $$.u.ast = zend_ast_create_binary(ZEND_FETCH_DIM_R, $1.u.ast, $3.u.ast); } + | static_scalar_value '+' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_ADD, $1.u.ast, $3.u.ast); } + | static_scalar_value '-' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SUB, $1.u.ast, $3.u.ast); } + | static_scalar_value '*' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_MUL, $1.u.ast, $3.u.ast); } + | static_scalar_value T_POW static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_POW, $1.u.ast, $3.u.ast); } + | static_scalar_value '/' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_DIV, $1.u.ast, $3.u.ast); } + | static_scalar_value '%' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_MOD, $1.u.ast, $3.u.ast); } + | '!' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_BOOL_NOT, $2.u.ast); } + | '~' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_BW_NOT, $2.u.ast); } + | static_scalar_value '|' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BW_OR, $1.u.ast, $3.u.ast); } + | static_scalar_value '&' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BW_AND, $1.u.ast, $3.u.ast); } + | static_scalar_value '^' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BW_XOR, $1.u.ast, $3.u.ast); } + | static_scalar_value T_SL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SL, $1.u.ast, $3.u.ast); } + | static_scalar_value T_SR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_SR, $1.u.ast, $3.u.ast); } + | static_scalar_value '.' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_CONCAT, $1.u.ast, $3.u.ast); } + | static_scalar_value T_LOGICAL_XOR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_XOR, $1.u.ast, $3.u.ast); } + | static_scalar_value T_LOGICAL_AND static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); } + | static_scalar_value T_LOGICAL_OR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); } + | static_scalar_value T_BOOLEAN_AND static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_AND, $1.u.ast, $3.u.ast); } + | static_scalar_value T_BOOLEAN_OR static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_BOOL_OR, $1.u.ast, $3.u.ast); } + | static_scalar_value T_IS_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_IDENTICAL, $1.u.ast, $3.u.ast); } + | static_scalar_value T_IS_NOT_IDENTICAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_NOT_IDENTICAL, $1.u.ast, $3.u.ast); } + | static_scalar_value T_IS_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_EQUAL, $1.u.ast, $3.u.ast); } + | static_scalar_value T_IS_NOT_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_NOT_EQUAL, $1.u.ast, $3.u.ast); } + | static_scalar_value '<' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER, $1.u.ast, $3.u.ast); } + | static_scalar_value '>' static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER, $3.u.ast, $1.u.ast); } + | static_scalar_value T_IS_SMALLER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER_OR_EQUAL, $1.u.ast, $3.u.ast); } + | static_scalar_value T_IS_GREATER_OR_EQUAL static_scalar_value { $$.u.ast = zend_ast_create_binary(ZEND_IS_SMALLER_OR_EQUAL, $3.u.ast, $1.u.ast); } + | static_scalar_value '?' ':' static_scalar_value { $$.u.ast = zend_ast_create_ternary(ZEND_SELECT, $1.u.ast, NULL, $4.u.ast); } + | static_scalar_value '?' static_scalar_value ':' static_scalar_value { $$.u.ast = zend_ast_create_ternary(ZEND_SELECT, $1.u.ast, $3.u.ast, $5.u.ast); } + | '+' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_UNARY_PLUS, $2.u.ast); } + | '-' static_scalar_value { $$.u.ast = zend_ast_create_unary(ZEND_UNARY_MINUS, $2.u.ast); } + | '(' static_scalar_value ')' { $$ = $2; } +; + +general_constant: + class_constant { $$ = $1; } + | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 0 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); } +; + +scalar: + T_STRING_VARNAME { $$ = $1; } + | general_constant { $$ = $1; } + | class_name_scalar { $$ = $1; } + | common_scalar { $$ = $1; } + | '"' encaps_list '"' { $$ = $2; } + | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; } + | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} } +; + +static_array_pair_list: + /* empty */ { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } + | non_empty_static_array_pair_list possible_comma { zend_ast_dynamic_shrink(&$1.u.ast); $$ = $1; } +; + +possible_comma: + /* empty */ + | ',' +; + +non_empty_static_array_pair_list: + non_empty_static_array_pair_list ',' static_scalar_value T_DOUBLE_ARROW static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); zend_ast_dynamic_add(&$$.u.ast, $5.u.ast); } + | non_empty_static_array_pair_list ',' static_scalar_value { zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); } + | static_scalar_value T_DOUBLE_ARROW static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); zend_ast_dynamic_add(&$$.u.ast, $3.u.ast); } + | static_scalar_value { $$.u.ast = zend_ast_create_dynamic(ZEND_INIT_ARRAY); zend_ast_dynamic_add(&$$.u.ast, NULL); zend_ast_dynamic_add(&$$.u.ast, $1.u.ast); } +; + +expr: + r_variable { $$ = $1; } + | expr_without_variable { $$ = $1; } +; + +parenthesis_expr: + '(' expr ')' { $$ = $2; } + | '(' yield_expr ')' { $$ = $2; } +; + + +r_variable: + variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; } +; + + +w_variable: + variable { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1; + zend_check_writable_variable(&$1); } +; + +rw_variable: + variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1; + zend_check_writable_variable(&$1); } +; + +variable: + base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); } + object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties + { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); } + | base_variable_with_function_calls { $$ = $1; } +; + +variable_properties: + variable_properties variable_property { $$.EA = $2.EA; } + | /* empty */ { $$.EA = 0; } +; + + +variable_property: + T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.EA = $4.EA; } +; + +array_method_dereference: + array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } +; + +method: + { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_begin_method_call(&$$ TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } +; + +method_or_not: + method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); } + | array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); } + | /* empty */ { $$.EA = ZEND_PARSED_MEMBER; } +; + +variable_without_objects: + reference_variable { $$ = $1; } + | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); } +; + +static_member: + class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); } + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); } + +; + +variable_class_name: + reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; } +; + +array_function_dereference: + array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; } + '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); } +; + +base_variable_with_function_calls: + base_variable { $$ = $1; } + | array_function_dereference { $$ = $1; } + | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; } +; + + +base_variable: + reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; } + | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; } + | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; } +; + +reference_variable: + reference_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | reference_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); } + | compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); } +; + + +compound_variable: + T_VARIABLE { $$ = $1; } + | '$' '{' expr '}' { $$ = $3; } +; + +dim_offset: + /* empty */ { $$.op_type = IS_UNUSED; } + | expr { $$ = $1; } +; + + +object_property: + object_dim_list { $$ = $1; } + | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);} +; + +object_dim_list: + object_dim_list '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | object_dim_list '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); } + | variable_name { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);} +; + +variable_name: + T_STRING { $$ = $1; } + | '{' expr '}' { $$ = $2; } +; + +simple_indirect_reference: + '$' { Z_LVAL($$.u.constant) = 1; } + | simple_indirect_reference '$' { Z_LVAL($$.u.constant)++; } +; + +assignment_list: + assignment_list ',' assignment_list_element + | assignment_list_element +; + + +assignment_list_element: + variable { zend_do_add_list_element(&$1 TSRMLS_CC); } + | T_LIST '(' { zend_do_new_list_begin(TSRMLS_C); } assignment_list ')' { zend_do_new_list_end(TSRMLS_C); } + | /* empty */ { zend_do_add_list_element(NULL TSRMLS_CC); } +; + + +array_pair_list: + /* empty */ { zend_do_init_array(&$$, NULL, NULL, 0 TSRMLS_CC); } + | non_empty_array_pair_list possible_comma { $$ = $1; } +; + +non_empty_array_pair_list: + non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { zend_do_add_array_element(&$$, &$5, &$3, 0 TSRMLS_CC); } + | non_empty_array_pair_list ',' expr { zend_do_add_array_element(&$$, &$3, NULL, 0 TSRMLS_CC); } + | expr T_DOUBLE_ARROW expr { zend_do_init_array(&$$, &$3, &$1, 0 TSRMLS_CC); } + | expr { zend_do_init_array(&$$, &$1, NULL, 0 TSRMLS_CC); } + | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable { zend_do_add_array_element(&$$, &$6, &$3, 1 TSRMLS_CC); } + | non_empty_array_pair_list ',' '&' w_variable { zend_do_add_array_element(&$$, &$4, NULL, 1 TSRMLS_CC); } + | expr T_DOUBLE_ARROW '&' w_variable { zend_do_init_array(&$$, &$4, &$1, 1 TSRMLS_CC); } + | '&' w_variable { zend_do_init_array(&$$, &$2, NULL, 1 TSRMLS_CC); } +; + +encaps_list: + encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); } + | encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); } + | encaps_var { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, NULL, &$1 TSRMLS_CC); } + | T_ENCAPSED_AND_WHITESPACE encaps_var { zend_do_add_string(&$$, NULL, &$1 TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$$, &$2 TSRMLS_CC); } +; + + + +encaps_var: + T_VARIABLE { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); } + | T_VARIABLE '[' { zend_do_begin_variable_parse(TSRMLS_C); } encaps_var_offset ']' { fetch_array_begin(&$$, &$1, &$4 TSRMLS_CC); } + | T_VARIABLE T_OBJECT_OPERATOR T_STRING { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$2, &$1, 1 TSRMLS_CC); zend_do_fetch_property(&$$, &$2, &$3 TSRMLS_CC); } + | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$2, 1 TSRMLS_CC); } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_begin(&$$, &$2, &$4 TSRMLS_CC); } + | T_CURLY_OPEN variable '}' { $$ = $2; } +; + + +encaps_var_offset: + T_STRING { $$ = $1; } + | T_NUM_STRING { $$ = $1; } + | T_VARIABLE { fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); } +; + + +internal_functions_in_yacc: + T_ISSET '(' isset_variables ')' { $$ = $3; } + | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); } + | T_EMPTY '(' expr_without_variable ')' { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); } + | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); } + | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); } + | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); } + | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); } + | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); } +; + +isset_variables: + isset_variable { $$ = $1; } + | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } isset_variable { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } +; + +isset_variable: + variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); } + | expr_without_variable { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use isset() on the result of an expression (you can use \"null !== expression\" instead)"); } +; + +class_constant: + class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); } + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); } +; + +static_class_name_scalar: + class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 1 TSRMLS_CC); } +; + +class_name_scalar: + class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 0 TSRMLS_CC); } +; + +%% + +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr) +{ + if (!yyres) { + return yystrlen(yystr); + } + { + TSRMLS_FETCH(); + if (CG(parse_error) == 0) { + char buffer[120]; + const unsigned char *end, *str, *tok1 = NULL, *tok2 = NULL; + unsigned int len = 0, toklen = 0, yystr_len; + + CG(parse_error) = 1; + + if (LANG_SCNG(yy_text)[0] == 0 && + LANG_SCNG(yy_leng) == 1 && + memcmp(yystr, "\"end of file\"", sizeof("\"end of file\"") - 1) == 0) { + yystpcpy(yyres, "end of file"); + return sizeof("end of file")-1; + } + + str = LANG_SCNG(yy_text); + end = memchr(str, '\n', LANG_SCNG(yy_leng)); + yystr_len = yystrlen(yystr); + + if ((tok1 = memchr(yystr, '(', yystr_len)) != NULL + && (tok2 = zend_memrchr(yystr, ')', yystr_len)) != NULL) { + toklen = (tok2 - tok1) + 1; + } else { + tok1 = tok2 = NULL; + toklen = 0; + } + + if (end == NULL) { + len = LANG_SCNG(yy_leng) > 30 ? 30 : LANG_SCNG(yy_leng); + } else { + len = (end - str) > 30 ? 30 : (end - str); + } + if (toklen) { + snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1); + } else { + snprintf(buffer, sizeof(buffer), "'%.*s'", len, str); + } + yystpcpy(yyres, buffer); + return len + (toklen ? toklen + 1 : 0) + 2; + } + } + if (*yystr == '"') { + YYSIZE_T yyn = 0; + const char *yyp = yystr; + + for (; *++yyp != '"'; ++yyn) { + yyres[yyn] = *yyp; + } + yyres[yyn] = '\0'; + return yyn; + } + yystpcpy(yyres, yystr); + return strlen(yystr); +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/poc/zend/php5/lexer.l b/poc/zend/php5/lexer.l new file mode 100644 index 000000000..bb1faebdd --- /dev/null +++ b/poc/zend/php5/lexer.l @@ -0,0 +1,2378 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Marcus Boerger | + | Nuno Lopes | + | Scott MacVicar | + | Flex version authors: | + | Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#if 0 +# define YYDEBUG(s, c) printf("state: %d char: %c\n", s, c) +#else +# define YYDEBUG(s, c) +#endif + +#include "zend_language_scanner_defs.h" + +#include +#include "zend.h" +#ifdef PHP_WIN32 +# include +#endif +#include "zend_alloc.h" +#include +#include "zend_compile.h" +#include "zend_language_scanner.h" +#include "zend_highlight.h" +#include "zend_constants.h" +#include "zend_variables.h" +#include "zend_operators.h" +#include "zend_API.h" +#include "zend_strtod.h" +#include "zend_exceptions.h" +#include "zend_virtual_cwd.h" +#include "tsrm_config_common.h" + +#define YYCTYPE unsigned char +#define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } } +#define YYCURSOR SCNG(yy_cursor) +#define YYLIMIT SCNG(yy_limit) +#define YYMARKER SCNG(yy_marker) + +#define YYGETCONDITION() SCNG(yy_state) +#define YYSETCONDITION(s) SCNG(yy_state) = s + +#define STATE(name) yyc##name + +/* emulate flex constructs */ +#define BEGIN(state) YYSETCONDITION(STATE(state)) +#define YYSTATE YYGETCONDITION() +#define yytext ((char*)SCNG(yy_text)) +#define yyleng SCNG(yy_leng) +#define yyless(x) do { YYCURSOR = (unsigned char*)yytext + x; \ + yyleng = (unsigned int)x; } while(0) +#define yymore() goto yymore_restart + +/* perform sanity check. If this message is triggered you should + increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */ +/*!max:re2c */ +#if ZEND_MMAP_AHEAD < YYMAXFILL +# error ZEND_MMAP_AHEAD should be greater than or equal to YYMAXFILL +#endif + +#ifdef HAVE_STDARG_H +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +/* Globals Macros */ +#define SCNG LANG_SCNG +#ifdef ZTS +ZEND_API ts_rsrc_id language_scanner_globals_id; +#else +ZEND_API zend_php_scanner_globals language_scanner_globals; +#endif + +#define HANDLE_NEWLINES(s, l) \ +do { \ + char *p = (s), *boundary = p+(l); \ + \ + while (p= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x7F) + +#define ZEND_IS_OCT(c) ((c)>='0' && (c)<='7') +#define ZEND_IS_HEX(c) (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F')) + +BEGIN_EXTERN_C() + +static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) +{ + const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C); + assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding)); + return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC); +} + +static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) +{ + return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding) TSRMLS_CC); +} + +static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) +{ + return zend_multibyte_encoding_converter(to, to_length, from, from_length, +LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC); +} + +static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC) +{ + const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C); + assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding)); + return zend_multibyte_encoding_converter(to, to_length, from, from_length, +internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC); +} + + +static void _yy_push_state(int new_state TSRMLS_DC) +{ + zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int)); + YYSETCONDITION(new_state); +} + +#define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm) + +static void yy_pop_state(TSRMLS_D) +{ + int *stack_state; + zend_stack_top(&SCNG(state_stack), (void **) &stack_state); + YYSETCONDITION(*stack_state); + zend_stack_del_top(&SCNG(state_stack)); +} + +static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC) +{ + YYCURSOR = (YYCTYPE*)str; + YYLIMIT = YYCURSOR + len; + if (!SCNG(yy_start)) { + SCNG(yy_start) = YYCURSOR; + } +} + +void startup_scanner(TSRMLS_D) +{ + CG(parse_error) = 0; + CG(doc_comment) = NULL; + CG(doc_comment_len) = 0; + zend_stack_init(&SCNG(state_stack)); + zend_ptr_stack_init(&SCNG(heredoc_label_stack)); +} + +static void heredoc_label_dtor(zend_heredoc_label *heredoc_label) { + efree(heredoc_label->label); +} + +void shutdown_scanner(TSRMLS_D) +{ + CG(parse_error) = 0; + RESET_DOC_COMMENT(); + zend_stack_destroy(&SCNG(state_stack)); + zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); + zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); +} + +ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC) +{ + lex_state->yy_leng = SCNG(yy_leng); + lex_state->yy_start = SCNG(yy_start); + lex_state->yy_text = SCNG(yy_text); + lex_state->yy_cursor = SCNG(yy_cursor); + lex_state->yy_marker = SCNG(yy_marker); + lex_state->yy_limit = SCNG(yy_limit); + + lex_state->state_stack = SCNG(state_stack); + zend_stack_init(&SCNG(state_stack)); + + lex_state->heredoc_label_stack = SCNG(heredoc_label_stack); + zend_ptr_stack_init(&SCNG(heredoc_label_stack)); + + lex_state->in = SCNG(yy_in); + lex_state->yy_state = YYSTATE; + lex_state->filename = zend_get_compiled_filename(TSRMLS_C); + lex_state->lineno = CG(zend_lineno); + + lex_state->script_org = SCNG(script_org); + lex_state->script_org_size = SCNG(script_org_size); + lex_state->script_filtered = SCNG(script_filtered); + lex_state->script_filtered_size = SCNG(script_filtered_size); + lex_state->input_filter = SCNG(input_filter); + lex_state->output_filter = SCNG(output_filter); + lex_state->script_encoding = SCNG(script_encoding); +} + +ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC) +{ + SCNG(yy_leng) = lex_state->yy_leng; + SCNG(yy_start) = lex_state->yy_start; + SCNG(yy_text) = lex_state->yy_text; + SCNG(yy_cursor) = lex_state->yy_cursor; + SCNG(yy_marker) = lex_state->yy_marker; + SCNG(yy_limit) = lex_state->yy_limit; + + zend_stack_destroy(&SCNG(state_stack)); + SCNG(state_stack) = lex_state->state_stack; + + zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); + zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); + SCNG(heredoc_label_stack) = lex_state->heredoc_label_stack; + + SCNG(yy_in) = lex_state->in; + YYSETCONDITION(lex_state->yy_state); + CG(zend_lineno) = lex_state->lineno; + zend_restore_compiled_filename(lex_state->filename TSRMLS_CC); + + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + SCNG(script_org) = lex_state->script_org; + SCNG(script_org_size) = lex_state->script_org_size; + SCNG(script_filtered) = lex_state->script_filtered; + SCNG(script_filtered_size) = lex_state->script_filtered_size; + SCNG(input_filter) = lex_state->input_filter; + SCNG(output_filter) = lex_state->output_filter; + SCNG(script_encoding) = lex_state->script_encoding; + + RESET_DOC_COMMENT(); +} + +ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC) +{ + zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles); + /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */ + file_handle->opened_path = NULL; + if (file_handle->free_filename) { + file_handle->filename = NULL; + } +} + +#define BOM_UTF32_BE "\x00\x00\xfe\xff" +#define BOM_UTF32_LE "\xff\xfe\x00\x00" +#define BOM_UTF16_BE "\xfe\xff" +#define BOM_UTF16_LE "\xff\xfe" +#define BOM_UTF8 "\xef\xbb\xbf" + +static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC) +{ + const unsigned char *p; + int wchar_size = 2; + int le = 0; + + /* utf-16 or utf-32? */ + p = script; + while ((p-script) < script_size) { + p = memchr(p, 0, script_size-(p-script)-2); + if (!p) { + break; + } + if (*(p+1) == '\0' && *(p+2) == '\0') { + wchar_size = 4; + break; + } + + /* searching for UTF-32 specific byte orders, so this will do */ + p += 4; + } + + /* BE or LE? */ + p = script; + while ((p-script) < script_size) { + if (*p == '\0' && *(p+wchar_size-1) != '\0') { + /* BE */ + le = 0; + break; + } else if (*p != '\0' && *(p+wchar_size-1) == '\0') { + /* LE* */ + le = 1; + break; + } + p += wchar_size; + } + + if (wchar_size == 2) { + return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be; + } else { + return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be; + } + + return NULL; +} + +static const zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D) +{ + const zend_encoding *script_encoding = NULL; + int bom_size; + unsigned char *pos1, *pos2; + + if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) { + return NULL; + } + + /* check out BOM */ + if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) { + script_encoding = zend_multibyte_encoding_utf32be; + bom_size = sizeof(BOM_UTF32_BE)-1; + } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) { + script_encoding = zend_multibyte_encoding_utf32le; + bom_size = sizeof(BOM_UTF32_LE)-1; + } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) { + script_encoding = zend_multibyte_encoding_utf16be; + bom_size = sizeof(BOM_UTF16_BE)-1; + } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) { + script_encoding = zend_multibyte_encoding_utf16le; + bom_size = sizeof(BOM_UTF16_LE)-1; + } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) { + script_encoding = zend_multibyte_encoding_utf8; + bom_size = sizeof(BOM_UTF8)-1; + } + + if (script_encoding) { + /* remove BOM */ + LANG_SCNG(script_org) += bom_size; + LANG_SCNG(script_org_size) -= bom_size; + + return script_encoding; + } + + /* script contains NULL bytes -> auto-detection */ + if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) { + /* check if the NULL byte is after the __HALT_COMPILER(); */ + pos2 = LANG_SCNG(script_org); + + while (pos1 - pos2 >= sizeof("__HALT_COMPILER();")-1) { + pos2 = memchr(pos2, '_', pos1 - pos2); + if (!pos2) break; + pos2++; + if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) { + pos2 += sizeof("_HALT_COMPILER")-1; + while (*pos2 == ' ' || + *pos2 == '\t' || + *pos2 == '\r' || + *pos2 == '\n') { + pos2++; + } + if (*pos2 == '(') { + pos2++; + while (*pos2 == ' ' || + *pos2 == '\t' || + *pos2 == '\r' || + *pos2 == '\n') { + pos2++; + } + if (*pos2 == ')') { + pos2++; + while (*pos2 == ' ' || + *pos2 == '\t' || + *pos2 == '\r' || + *pos2 == '\n') { + pos2++; + } + if (*pos2 == ';') { + return NULL; + } + } + } + } + } + /* make best effort if BOM is missing */ + return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC); + } + + return NULL; +} + +static const zend_encoding* zend_multibyte_find_script_encoding(TSRMLS_D) +{ + const zend_encoding *script_encoding; + + if (CG(detect_unicode)) { + /* check out bom(byte order mark) and see if containing wchars */ + script_encoding = zend_multibyte_detect_unicode(TSRMLS_C); + if (script_encoding != NULL) { + /* bom or wchar detection is prior to 'script_encoding' option */ + return script_encoding; + } + } + + /* if no script_encoding specified, just leave alone */ + if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) { + return NULL; + } + + /* if multiple encodings specified, detect automagically */ + if (CG(script_encoding_list_size) > 1) { + return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size) TSRMLS_CC); + } + + return CG(script_encoding_list)[0]; +} + +ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC) +{ + const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C); + const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding(TSRMLS_C); + + if (!script_encoding) { + return FAILURE; + } + + /* judge input/output filter */ + LANG_SCNG(script_encoding) = script_encoding; + LANG_SCNG(input_filter) = NULL; + LANG_SCNG(output_filter) = NULL; + + if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) { + if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) { + /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */ + LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate; + LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script; + } else { + LANG_SCNG(input_filter) = NULL; + LANG_SCNG(output_filter) = NULL; + } + return SUCCESS; + } + + if (zend_multibyte_check_lexer_compatibility(internal_encoding)) { + LANG_SCNG(input_filter) = encoding_filter_script_to_internal; + LANG_SCNG(output_filter) = NULL; + } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) { + LANG_SCNG(input_filter) = NULL; + LANG_SCNG(output_filter) = encoding_filter_script_to_internal; + } else { + /* both script and internal encodings are incompatible w/ flex */ + LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate; + LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal; + } + + return 0; +} + +ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC) +{ + const char *file_path = NULL; + char *buf; + size_t size, offset = 0; + + /* The shebang line was read, get the current position to obtain the buffer start */ + if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) { + if ((offset = ftell(file_handle->handle.fp)) == -1) { + offset = 0; + } + } + + if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) { + return FAILURE; + } + + zend_llist_add_element(&CG(open_files), file_handle); + if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) { + zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files)); + size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle; + fh->handle.stream.handle = (void*)(((char*)fh) + diff); + file_handle->handle.stream.handle = fh->handle.stream.handle; + } + + /* Reset the scanner for scanning the new file */ + SCNG(yy_in) = file_handle; + SCNG(yy_start) = NULL; + + if (size != -1) { + if (CG(multibyte)) { + SCNG(script_org) = (unsigned char*)buf; + SCNG(script_org_size) = size; + SCNG(script_filtered) = NULL; + + zend_multibyte_set_filter(NULL TSRMLS_CC); + + if (SCNG(input_filter)) { + if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) { + zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected " + "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding))); + } + buf = (char*)SCNG(script_filtered); + size = SCNG(script_filtered_size); + } + } + SCNG(yy_start) = (unsigned char *)buf - offset; + yy_scan_buffer(buf, size TSRMLS_CC); + } else { + zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed"); + } + + BEGIN(INITIAL); + + if (file_handle->opened_path) { + file_path = file_handle->opened_path; + } else { + file_path = file_handle->filename; + } + + zend_set_compiled_filename(file_path TSRMLS_CC); + + if (CG(start_lineno)) { + CG(zend_lineno) = CG(start_lineno); + CG(start_lineno) = 0; + } else { + CG(zend_lineno) = 1; + } + + RESET_DOC_COMMENT(); + CG(increment_lineno) = 0; + return SUCCESS; +} +END_EXTERN_C() + + +ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) +{ + zend_lex_state original_lex_state; + zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); + zend_op_array *original_active_op_array = CG(active_op_array); + zend_op_array *retval=NULL; + int compiler_result; + zend_bool compilation_successful=0; + znode retval_znode; + zend_bool original_in_compilation = CG(in_compilation); + + retval_znode.op_type = IS_CONST; + INIT_PZVAL(&retval_znode.u.constant); + ZVAL_LONG(&retval_znode.u.constant, 1); + + zend_save_lexical_state(&original_lex_state TSRMLS_CC); + + retval = op_array; /* success oriented */ + + if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) { + if (type==ZEND_REQUIRE) { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); + zend_bailout(); + } else { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); + } + compilation_successful=0; + } else { + init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); + CG(in_compilation) = 1; + CG(active_op_array) = op_array; + zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); + zend_init_compiler_context(TSRMLS_C); + compiler_result = zendparse(TSRMLS_C); + zend_do_return(&retval_znode, 0 TSRMLS_CC); + CG(in_compilation) = original_in_compilation; + if (compiler_result != 0) { /* parser error */ + zend_bailout(); + } + compilation_successful=1; + } + + if (retval) { + CG(active_op_array) = original_active_op_array; + if (compilation_successful) { + pass_two(op_array TSRMLS_CC); + zend_release_labels(0 TSRMLS_CC); + } else { + efree(op_array); + retval = NULL; + } + } + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + return retval; +} + + +zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC) +{ + zend_file_handle file_handle; + zval tmp; + zend_op_array *retval; + char *opened_path = NULL; + + if (filename->type != IS_STRING) { + tmp = *filename; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + filename = &tmp; + } + file_handle.filename = Z_STRVAL_P(filename); + file_handle.free_filename = 0; + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.opened_path = NULL; + file_handle.handle.fp = NULL; + + retval = zend_compile_file(&file_handle, type TSRMLS_CC); + if (retval && file_handle.handle.stream.handle) { + int dummy = 1; + + if (!file_handle.opened_path) { + file_handle.opened_path = opened_path = estrndup(Z_STRVAL_P(filename), Z_STRLEN_P(filename)); + } + + zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL); + + if (opened_path) { + efree(opened_path); + } + } + zend_destroy_file_handle(&file_handle TSRMLS_CC); + + if (filename==&tmp) { + zval_dtor(&tmp); + } + return retval; +} + +ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC) +{ + char *buf; + size_t size; + + /* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */ + Z_STRVAL_P(str) = str_erealloc(Z_STRVAL_P(str), Z_STRLEN_P(str) + ZEND_MMAP_AHEAD); + memset(Z_STRVAL_P(str) + Z_STRLEN_P(str), 0, ZEND_MMAP_AHEAD); + + SCNG(yy_in) = NULL; + SCNG(yy_start) = NULL; + + buf = Z_STRVAL_P(str); + size = Z_STRLEN_P(str); + + if (CG(multibyte)) { + SCNG(script_org) = (unsigned char*)buf; + SCNG(script_org_size) = size; + SCNG(script_filtered) = NULL; + + zend_multibyte_set_filter(zend_multibyte_get_internal_encoding(TSRMLS_C) TSRMLS_CC); + + if (SCNG(input_filter)) { + if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) { + zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected " + "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding))); + } + buf = (char*)SCNG(script_filtered); + size = SCNG(script_filtered_size); + } + } + + yy_scan_buffer(buf, size TSRMLS_CC); + + zend_set_compiled_filename(filename TSRMLS_CC); + CG(zend_lineno) = 1; + CG(increment_lineno) = 0; + RESET_DOC_COMMENT(); + return SUCCESS; +} + + +ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D) +{ + size_t offset = SCNG(yy_cursor) - SCNG(yy_start); + if (SCNG(input_filter)) { + size_t original_offset = offset, length = 0; + do { + unsigned char *p = NULL; + if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC)) { + return (size_t)-1; + } + efree(p); + if (length > original_offset) { + offset--; + } else if (length < original_offset) { + offset++; + } + } while (original_offset != length); + } + return offset; +} + + +zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC) +{ + zend_lex_state original_lex_state; + zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); + zend_op_array *original_active_op_array = CG(active_op_array); + zend_op_array *retval; + zval tmp; + int compiler_result; + zend_bool original_in_compilation = CG(in_compilation); + + if (Z_STRLEN_P(source_string)==0) { + efree(op_array); + return NULL; + } + + CG(in_compilation) = 1; + + tmp = *source_string; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + source_string = &tmp; + + zend_save_lexical_state(&original_lex_state TSRMLS_CC); + if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) { + efree(op_array); + retval = NULL; + } else { + zend_bool orig_interactive = CG(interactive); + + CG(interactive) = 0; + init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); + CG(interactive) = orig_interactive; + CG(active_op_array) = op_array; + zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context))); + zend_init_compiler_context(TSRMLS_C); + BEGIN(ST_IN_SCRIPTING); + compiler_result = zendparse(TSRMLS_C); + + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + + if (compiler_result != 0) { + CG(active_op_array) = original_active_op_array; + CG(unclean_shutdown)=1; + destroy_op_array(op_array TSRMLS_CC); + efree(op_array); + retval = NULL; + } else { + zend_do_return(NULL, 0 TSRMLS_CC); + CG(active_op_array) = original_active_op_array; + pass_two(op_array TSRMLS_CC); + zend_release_labels(0 TSRMLS_CC); + retval = op_array; + } + } + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + zval_dtor(&tmp); + CG(in_compilation) = original_in_compilation; + return retval; +} + + +BEGIN_EXTERN_C() +int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC) +{ + zend_lex_state original_lex_state; + zend_file_handle file_handle; + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = filename; + file_handle.free_filename = 0; + file_handle.opened_path = NULL; + zend_save_lexical_state(&original_lex_state TSRMLS_CC); + if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) { + zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename TSRMLS_CC); + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + return FAILURE; + } + zend_highlight(syntax_highlighter_ini TSRMLS_CC); + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + zend_destroy_file_handle(&file_handle TSRMLS_CC); + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + return SUCCESS; +} + +int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC) +{ + zend_lex_state original_lex_state; + zval tmp = *str; + + str = &tmp; + zval_copy_ctor(str); + zend_save_lexical_state(&original_lex_state TSRMLS_CC); + if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) { + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + return FAILURE; + } + BEGIN(INITIAL); + zend_highlight(syntax_highlighter_ini TSRMLS_CC); + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + zend_restore_lexical_state(&original_lex_state TSRMLS_CC); + zval_dtor(str); + return SUCCESS; +} + +ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC) +{ + size_t length; + unsigned char *new_yy_start; + + /* convert and set */ + if (!SCNG(input_filter)) { + if (SCNG(script_filtered)) { + efree(SCNG(script_filtered)); + SCNG(script_filtered) = NULL; + } + SCNG(script_filtered_size) = 0; + length = SCNG(script_org_size); + new_yy_start = SCNG(script_org); + } else { + if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) { + zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected " + "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding))); + } + SCNG(script_filtered) = new_yy_start; + SCNG(script_filtered_size) = length; + } + + SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start)); + SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start)); + SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start)); + SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start)); + + SCNG(yy_start) = new_yy_start; +} + + +# define zend_copy_value(zendlval, yytext, yyleng) \ + if (SCNG(output_filter)) { \ + size_t sz = 0; \ + SCNG(output_filter)((unsigned char **)&Z_STRVAL_P(zendlval), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \ + Z_STRLEN_P(zendlval) = sz; \ + } else { \ + Z_STRVAL_P(zendlval) = (char *) estrndup(yytext, yyleng); \ + Z_STRLEN_P(zendlval) = yyleng; \ + } + +static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC) +{ + register char *s, *t; + char *end; + + ZVAL_STRINGL(zendlval, str, len, 1); + + /* convert escape sequences */ + s = t = Z_STRVAL_P(zendlval); + end = s+Z_STRLEN_P(zendlval); + while (s= end) { + *t++ = '\\'; + break; + } + + switch(*s) { + case 'n': + *t++ = '\n'; + Z_STRLEN_P(zendlval)--; + break; + case 'r': + *t++ = '\r'; + Z_STRLEN_P(zendlval)--; + break; + case 't': + *t++ = '\t'; + Z_STRLEN_P(zendlval)--; + break; + case 'f': + *t++ = '\f'; + Z_STRLEN_P(zendlval)--; + break; + case 'v': + *t++ = '\v'; + Z_STRLEN_P(zendlval)--; + break; + case 'e': +#ifdef PHP_WIN32 + *t++ = VK_ESCAPE; +#else + *t++ = '\e'; +#endif + Z_STRLEN_P(zendlval)--; + break; + case '"': + case '`': + if (*s != quote_type) { + *t++ = '\\'; + *t++ = *s; + break; + } + case '\\': + case '$': + *t++ = *s; + Z_STRLEN_P(zendlval)--; + break; + case 'x': + case 'X': + if (ZEND_IS_HEX(*(s+1))) { + char hex_buf[3] = { 0, 0, 0 }; + + Z_STRLEN_P(zendlval)--; /* for the 'x' */ + + hex_buf[0] = *(++s); + Z_STRLEN_P(zendlval)--; + if (ZEND_IS_HEX(*(s+1))) { + hex_buf[1] = *(++s); + Z_STRLEN_P(zendlval)--; + } + *t++ = (char) strtol(hex_buf, NULL, 16); + } else { + *t++ = '\\'; + *t++ = *s; + } + break; + default: + /* check for an octal */ + if (ZEND_IS_OCT(*s)) { + char octal_buf[4] = { 0, 0, 0, 0 }; + + octal_buf[0] = *s; + Z_STRLEN_P(zendlval)--; + if (ZEND_IS_OCT(*(s+1))) { + octal_buf[1] = *(++s); + Z_STRLEN_P(zendlval)--; + if (ZEND_IS_OCT(*(s+1))) { + octal_buf[2] = *(++s); + Z_STRLEN_P(zendlval)--; + } + } + *t++ = (char) strtol(octal_buf, NULL, 8); + } else { + *t++ = '\\'; + *t++ = *s; + } + break; + } + } else { + *t++ = *s; + } + + if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) { + CG(zend_lineno)++; + } + s++; + } + *t = 0; + if (SCNG(output_filter)) { + size_t sz = 0; + s = Z_STRVAL_P(zendlval); + SCNG(output_filter)((unsigned char **)&Z_STRVAL_P(zendlval), &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval) TSRMLS_CC); + Z_STRLEN_P(zendlval) = sz; + efree(s); + } +} + + +int lex_scan(zval *zendlval TSRMLS_DC) +{ +restart: + SCNG(yy_text) = YYCURSOR; + +yymore_restart: + +/*!re2c +re2c:yyfill:check = 0; +LNUM [0-9]+ +DNUM ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*) +EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM}) +HNUM "0x"[0-9a-fA-F]+ +BNUM "0b"[01]+ +LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* +WHITESPACE [ \n\r\t]+ +TABS_AND_SPACES [ \t]* +TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@] +ANY_CHAR [^] +NEWLINE ("\r"|"\n"|"\r\n") + +/* compute yyleng before each rule */ + := yyleng = YYCURSOR - SCNG(yy_text); + +"exit" { + return T_EXIT; +} + +"die" { + return T_EXIT; +} + +"function" { + return T_FUNCTION; +} + +"const" { + return T_CONST; +} + +"return" { + return T_RETURN; +} + +"yield" { + return T_YIELD; +} + +"try" { + return T_TRY; +} + +"catch" { + return T_CATCH; +} + +"finally" { + return T_FINALLY; +} + +"throw" { + return T_THROW; +} + +"if" { + return T_IF; +} + +"elseif" { + return T_ELSEIF; +} + +"endif" { + return T_ENDIF; +} + +"else" { + return T_ELSE; +} + +"while" { + return T_WHILE; +} + +"endwhile" { + return T_ENDWHILE; +} + +"do" { + return T_DO; +} + +"for" { + return T_FOR; +} + +"endfor" { + return T_ENDFOR; +} + +"foreach" { + return T_FOREACH; +} + +"endforeach" { + return T_ENDFOREACH; +} + +"declare" { + return T_DECLARE; +} + +"enddeclare" { + return T_ENDDECLARE; +} + +"instanceof" { + return T_INSTANCEOF; +} + +"as" { + return T_AS; +} + +"switch" { + return T_SWITCH; +} + +"endswitch" { + return T_ENDSWITCH; +} + +"case" { + return T_CASE; +} + +"default" { + return T_DEFAULT; +} + +"break" { + return T_BREAK; +} + +"continue" { + return T_CONTINUE; +} + +"goto" { + return T_GOTO; +} + +"echo" { + return T_ECHO; +} + +"print" { + return T_PRINT; +} + +"class" { + return T_CLASS; +} + +"interface" { + return T_INTERFACE; +} + +"trait" { + return T_TRAIT; +} + +"extends" { + return T_EXTENDS; +} + +"implements" { + return T_IMPLEMENTS; +} + +"->" { + yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); + return T_OBJECT_OPERATOR; +} + +{WHITESPACE}+ { + ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */ + HANDLE_NEWLINES(yytext, yyleng); + return T_WHITESPACE; +} + +"->" { + return T_OBJECT_OPERATOR; +} + +{LABEL} { + yy_pop_state(TSRMLS_C); + zend_copy_value(zendlval, yytext, yyleng); + zendlval->type = IS_STRING; + return T_STRING; +} + +{ANY_CHAR} { + yyless(0); + yy_pop_state(TSRMLS_C); + goto restart; +} + +"::" { + return T_PAAMAYIM_NEKUDOTAYIM; +} + +"\\" { + return T_NS_SEPARATOR; +} + +"..." { + return T_ELLIPSIS; +} + +"new" { + return T_NEW; +} + +"clone" { + return T_CLONE; +} + +"var" { + return T_VAR; +} + +"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" { + return T_INT_CAST; +} + +"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" { + return T_DOUBLE_CAST; +} + +"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" { + return T_STRING_CAST; +} + +"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" { + return T_ARRAY_CAST; +} + +"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" { + return T_OBJECT_CAST; +} + +"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" { + return T_BOOL_CAST; +} + +"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" { + return T_UNSET_CAST; +} + +"eval" { + return T_EVAL; +} + +"include" { + return T_INCLUDE; +} + +"include_once" { + return T_INCLUDE_ONCE; +} + +"require" { + return T_REQUIRE; +} + +"require_once" { + return T_REQUIRE_ONCE; +} + +"namespace" { + return T_NAMESPACE; +} + +"use" { + return T_USE; +} + +"insteadof" { + return T_INSTEADOF; +} + +"global" { + return T_GLOBAL; +} + +"isset" { + return T_ISSET; +} + +"empty" { + return T_EMPTY; +} + +"__halt_compiler" { + return T_HALT_COMPILER; +} + +"static" { + return T_STATIC; +} + +"abstract" { + return T_ABSTRACT; +} + +"final" { + return T_FINAL; +} + +"private" { + return T_PRIVATE; +} + +"protected" { + return T_PROTECTED; +} + +"public" { + return T_PUBLIC; +} + +"unset" { + return T_UNSET; +} + +"=>" { + return T_DOUBLE_ARROW; +} + +"list" { + return T_LIST; +} + +"array" { + return T_ARRAY; +} + +"callable" { + return T_CALLABLE; +} + +"++" { + return T_INC; +} + +"--" { + return T_DEC; +} + +"===" { + return T_IS_IDENTICAL; +} + +"!==" { + return T_IS_NOT_IDENTICAL; +} + +"==" { + return T_IS_EQUAL; +} + +"!="|"<>" { + return T_IS_NOT_EQUAL; +} + +"<=" { + return T_IS_SMALLER_OR_EQUAL; +} + +">=" { + return T_IS_GREATER_OR_EQUAL; +} + +"+=" { + return T_PLUS_EQUAL; +} + +"-=" { + return T_MINUS_EQUAL; +} + +"*=" { + return T_MUL_EQUAL; +} + +"*\*" { + return T_POW; +} + +"*\*=" { + return T_POW_EQUAL; +} + +"/=" { + return T_DIV_EQUAL; +} + +".=" { + return T_CONCAT_EQUAL; +} + +"%=" { + return T_MOD_EQUAL; +} + +"<<=" { + return T_SL_EQUAL; +} + +">>=" { + return T_SR_EQUAL; +} + +"&=" { + return T_AND_EQUAL; +} + +"|=" { + return T_OR_EQUAL; +} + +"^=" { + return T_XOR_EQUAL; +} + +"||" { + return T_BOOLEAN_OR; +} + +"&&" { + return T_BOOLEAN_AND; +} + +"OR" { + return T_LOGICAL_OR; +} + +"AND" { + return T_LOGICAL_AND; +} + +"XOR" { + return T_LOGICAL_XOR; +} + +"<<" { + return T_SL; +} + +">>" { + return T_SR; +} + +{TOKENS} { + return yytext[0]; +} + + +"{" { + yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); + return '{'; +} + + +"${" { + yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); + return T_DOLLAR_OPEN_CURLY_BRACES; +} + + +"}" { + RESET_DOC_COMMENT(); + if (!zend_stack_is_empty(&SCNG(state_stack))) { + yy_pop_state(TSRMLS_C); + } + return '}'; +} + + +{LABEL}[[}] { + yyless(yyleng - 1); + zend_copy_value(zendlval, yytext, yyleng); + zendlval->type = IS_STRING; + yy_pop_state(TSRMLS_C); + yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); + return T_STRING_VARNAME; +} + + +{ANY_CHAR} { + yyless(0); + yy_pop_state(TSRMLS_C); + yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); + goto restart; +} + +{BNUM} { + char *bin = yytext + 2; /* Skip "0b" */ + int len = yyleng - 2; + + /* Skip any leading 0s */ + while (*bin == '0') { + ++bin; + --len; + } + + if (len < SIZEOF_LONG * 8) { + if (len == 0) { + Z_LVAL_P(zendlval) = 0; + } else { + Z_LVAL_P(zendlval) = strtol(bin, NULL, 2); + } + zendlval->type = IS_LONG; + return T_LNUMBER; + } else { + ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, NULL)); + return T_DNUMBER; + } +} + +{LNUM} { + if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ + Z_LVAL_P(zendlval) = strtol(yytext, NULL, 0); + } else { + errno = 0; + Z_LVAL_P(zendlval) = strtol(yytext, NULL, 0); + if (errno == ERANGE) { /* Overflow */ + if (yytext[0] == '0') { /* octal overflow */ + Z_DVAL_P(zendlval) = zend_oct_strtod(yytext, NULL); + } else { + Z_DVAL_P(zendlval) = zend_strtod(yytext, NULL); + } + zendlval->type = IS_DOUBLE; + return T_DNUMBER; + } + } + + zendlval->type = IS_LONG; + return T_LNUMBER; +} + +{HNUM} { + char *hex = yytext + 2; /* Skip "0x" */ + int len = yyleng - 2; + + /* Skip any leading 0s */ + while (*hex == '0') { + hex++; + len--; + } + + if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) { + if (len == 0) { + Z_LVAL_P(zendlval) = 0; + } else { + Z_LVAL_P(zendlval) = strtol(hex, NULL, 16); + } + zendlval->type = IS_LONG; + return T_LNUMBER; + } else { + ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, NULL)); + return T_DNUMBER; + } +} + +[0]|([1-9][0-9]*) { /* Offset could be treated as a long */ + if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) { + ZVAL_LONG(zendlval, strtol(yytext, NULL, 10)); + } else { + ZVAL_STRINGL(zendlval, yytext, yyleng, 1); + } + return T_NUM_STRING; +} + +{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */ + ZVAL_STRINGL(zendlval, yytext, yyleng, 1); + return T_NUM_STRING; +} + +{DNUM}|{EXPONENT_DNUM} { + ZVAL_DOUBLE(zendlval, zend_strtod(yytext, NULL)); + return T_DNUMBER; +} + +"__CLASS__" { + zend_class_entry *ce = CG(active_class_entry); + if (ce && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) { + /* We create a special __CLASS__ constant that is going to be resolved + at run-time */ + Z_STRLEN_P(zendlval) = sizeof("__CLASS__")-1; + Z_STRVAL_P(zendlval) = estrndup("__CLASS__", Z_STRLEN_P(zendlval)); + zendlval->type = IS_CONSTANT; + } else { + if (ce && ce->name) { + ZVAL_STRINGL(zendlval, ce->name, ce->name_length, 1); + } else { + ZVAL_EMPTY_STRING(zendlval); + } + } + return T_CLASS_C; +} + +"__TRAIT__" { + zend_class_entry *ce = CG(active_class_entry); + if (ce && ce->name && ZEND_ACC_TRAIT == (ce->ce_flags & ZEND_ACC_TRAIT)) { + ZVAL_STRINGL(zendlval, ce->name, ce->name_length, 1); + } else { + ZVAL_EMPTY_STRING(zendlval); + } + return T_TRAIT_C; +} + +"__FUNCTION__" { + zend_op_array *op_array = CG(active_op_array); + if (op_array && op_array->function_name) { + ZVAL_STRING(zendlval, op_array->function_name, 1); + } else { + ZVAL_EMPTY_STRING(zendlval); + } + return T_FUNC_C; +} + +"__METHOD__" { + const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL; + const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL; + + Z_STRLEN_P(zendlval) = zend_spprintf(&Z_STRVAL_P(zendlval), 0, "%s%s%s", + class_name ? class_name : "", + class_name && func_name ? "::" : "", + func_name ? func_name : "" + ); + zendlval->type = IS_STRING; + return T_METHOD_C; +} + +"__LINE__" { + ZVAL_LONG(zendlval, CG(zend_lineno)); + return T_LINE; +} + +"__FILE__" { + char *filename = zend_get_compiled_filename(TSRMLS_C); + + if (!filename) { + filename = ""; + } + ZVAL_STRING(zendlval, filename, 1); + return T_FILE; +} + +"__DIR__" { + char *filename = zend_get_compiled_filename(TSRMLS_C); + const size_t filename_len = strlen(filename); + char *dirname; + + if (!filename) { + filename = ""; + } + + dirname = estrndup(filename, filename_len); + zend_dirname(dirname, filename_len); + + if (strcmp(dirname, ".") == 0) { + dirname = erealloc(dirname, MAXPATHLEN); +#if HAVE_GETCWD + VCWD_GETCWD(dirname, MAXPATHLEN); +#elif HAVE_GETWD + VCWD_GETWD(dirname); +#endif + } + + ZVAL_STRING(zendlval, dirname, 0); + return T_DIR; +} + +"__NAMESPACE__" { + if (CG(current_namespace)) { + *zendlval = *CG(current_namespace); + zval_copy_ctor(zendlval); + } else { + ZVAL_EMPTY_STRING(zendlval); + } + return T_NS_C; +} + +"" { + YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1)); + + if (bracket != SCNG(yy_text)) { + /* Handle previously scanned HTML, as possible