diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..e7ccfc0 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,25 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests for the configured nvm version of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: CI + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: ".nvmrc" + cache: "npm" + - run: npm ci + - run: npm run elm-format:validate + - run: npm test + - run: npm run elm-review diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..074a1ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +elm-stuff +node_modules \ No newline at end of file diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..bc7b6ca --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22.8.0 \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c338b29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright 2024 Décio Ferreira + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..23fdd60 --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# Elm GLSL Parser + +An Elm package that implements a GLSL (OpenGL Shading Language) parser, inspired by the [Haskell GLSL parser](https://hackage.haskell.org/package/language-glsl). This library allows you to parse GLSL shader code into Elm data structures, enabling further manipulation, analysis, or code generation. + +## Getting Started + +### Installation + +To install the package, run the following: + +```bash +elm install guida-lang/glsl +``` + +### Usage + +Here’s an example of how to use the GLSL parser in Elm: + +```elm +import Language.GLSL.Parser as Parser +import Language.GLSL.Syntax as Syntax + +shaderSource : String +shaderSource = + """ + void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + """ + +parseResult : Result String Syntax.TranslationUnit +parseResult = + Parser.parse shaderSource +``` + +### Parsing GLSL + +The `parse` function attempts to parse a GLSL shader string and returns a `Result`: + +- `Ok Syntax.TranslationUnit`: If the shader was parsed successfully, it returns an abstract syntax + tree (AST) representing the GLSL code. +- `Err String`: If parsing failed, it returns an error string describing the issue. + +### Example + +```elm +case parseResult of + Ok shader -> + -- Do something with the parsed shader + Debug.log "Parsed successfully!" shader + + Err error -> + Debug.log "Failed to parse shader:" error +``` + +## Documentation + +For full API documentation and more examples, please visit the +[Elm package documentation](https://package.elm-lang.org/packages/guida-lang/glsl/1.0.0). + +## Contributing + +Contributions are welcome! If you have ideas for improvements or find bugs, feel free to open an +issue or submit a pull request. + +### To contribute: + +1. Fork the repository. +2. Create a new feature branch. +3. Commit your changes. +4. Submit a pull request. diff --git a/elm.json b/elm.json new file mode 100644 index 0000000..d4e6605 --- /dev/null +++ b/elm.json @@ -0,0 +1,21 @@ +{ + "type": "package", + "name": "guida-lang/glsl", + "summary": "An Elm parser for GLSL, inspired by Haskell's GLSL parser", + "license": "BSD-3-Clause", + "version": "1.0.0", + "exposed-modules": [ + "Language.GLSL.Parser", + "Language.GLSL.Syntax" + ], + "elm-version": "0.19.0 <= v < 0.20.0", + "dependencies": { + "andre-dietrich/parser-combinators": "4.1.0 <= v < 5.0.0", + "elm/core": "1.0.0 <= v < 2.0.0", + "pilatch/flip": "1.0.0 <= v < 2.0.0", + "rtfeldman/elm-hex": "1.0.0 <= v < 2.0.0" + }, + "test-dependencies": { + "elm-explorations/test": "2.2.0 <= v < 3.0.0" + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..14f4d59 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2323 @@ +{ + "name": "glsl", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "elm": "^0.19.1-6", + "elm-format": "^0.8.7", + "elm-review": "^2.12.0", + "elm-test": "^0.19.1-revision12" + } + }, + "node_modules/@avh4/elm-format-darwin-arm64": { + "version": "0.8.7-2", + "resolved": "https://registry.npmjs.org/@avh4/elm-format-darwin-arm64/-/elm-format-darwin-arm64-0.8.7-2.tgz", + "integrity": "sha512-F5JD44mJ3KX960J5GkXMfh1/dtkXuPcQpX2EToHQKjLTZUfnhZ++ytQQt0gAvrJ0bzoOvhNzjNjUHDA1ruTVbg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@avh4/elm-format-darwin-x64": { + "version": "0.8.7-2", + "resolved": "https://registry.npmjs.org/@avh4/elm-format-darwin-x64/-/elm-format-darwin-x64-0.8.7-2.tgz", + "integrity": "sha512-4pfF1cl0KyTion+7Mg4XKM3yi4Yc7vP76Kt/DotLVGJOSag4ISGic1og2mt8RZZ7XArybBmHNyYkiUbe/cEiCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@avh4/elm-format-linux-arm64": { + "version": "0.8.7-2", + "resolved": "https://registry.npmjs.org/@avh4/elm-format-linux-arm64/-/elm-format-linux-arm64-0.8.7-2.tgz", + "integrity": "sha512-WkVmuce2zU6s9dupHhqPc886Vaqpea8dZlxv2fpZ4wSzPUbiiKHoHZzoVndMIMTUL0TZukP3Ps0n/lWO5R5+FA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@avh4/elm-format-linux-x64": { + "version": "0.8.7-2", + "resolved": "https://registry.npmjs.org/@avh4/elm-format-linux-x64/-/elm-format-linux-x64-0.8.7-2.tgz", + "integrity": "sha512-kmncfJrTBjVT94JtQvMf4M5Pn2Yl0sZt3wo7AzgFiDnB/CiZ+KjJyXuWM64NeGiv4MQqzPq65tsFXUH1CIJeiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@avh4/elm-format-win32-x64": { + "version": "0.8.7-2", + "resolved": "https://registry.npmjs.org/@avh4/elm-format-win32-x64/-/elm-format-win32-x64-0.8.7-2.tgz", + "integrity": "sha512-sBdMBGq/8mD8Y5C+fIr5vlb3N50yB7S1MfgeAq2QEbvkr/sKrCZI540i43lZDH9gWsfA1w2W8wCe0penFYzsGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@elm_binaries/darwin_arm64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/darwin_arm64/-/darwin_arm64-0.19.1-0.tgz", + "integrity": "sha512-mjbsH7BNHEAmoE2SCJFcfk5fIHwFIpxtSgnEAqMsVLpBUFoEtAeX+LQ+N0vSFJB3WAh73+QYx/xSluxxLcL6dA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@elm_binaries/darwin_x64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/darwin_x64/-/darwin_x64-0.19.1-0.tgz", + "integrity": "sha512-QGUtrZTPBzaxgi9al6nr+9313wrnUVHuijzUK39UsPS+pa+n6CmWyV/69sHZeX9qy6UfeugE0PzF3qcUiy2GDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@elm_binaries/linux_x64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/linux_x64/-/linux_x64-0.19.1-0.tgz", + "integrity": "sha512-T1ZrWVhg2kKAsi8caOd3vp/1A3e21VuCpSG63x8rDie50fHbCytTway9B8WHEdnBFv4mYWiA68dzGxYCiFmU2w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@elm_binaries/win32_x64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/win32_x64/-/win32_x64-0.19.1-0.tgz", + "integrity": "sha512-yDleiXqSE9EcqKtd9SkC/4RIW8I71YsXzMPL79ub2bBPHjWTcoyyeBbYjoOB9SxSlArJ74HaoBApzT6hY7Zobg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", + "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/elm": { + "version": "0.19.1-6", + "resolved": "https://registry.npmjs.org/elm/-/elm-0.19.1-6.tgz", + "integrity": "sha512-mKYyierHICPdMx/vhiIacdPmTPnh889gjHOZ75ZAoCxo3lZmSWbGP8HMw78wyctJH0HwvTmeKhlYSWboQNYPeQ==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "bin": { + "elm": "bin/elm" + }, + "engines": { + "node": ">=7.0.0" + }, + "optionalDependencies": { + "@elm_binaries/darwin_arm64": "0.19.1-0", + "@elm_binaries/darwin_x64": "0.19.1-0", + "@elm_binaries/linux_x64": "0.19.1-0", + "@elm_binaries/win32_x64": "0.19.1-0" + } + }, + "node_modules/elm-format": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/elm-format/-/elm-format-0.8.7.tgz", + "integrity": "sha512-sVzFXfWnb+6rzXK+q3e3Ccgr6/uS5mFbFk1VSmigC+x2XZ28QycAa7lS8owl009ALPhRQk+pZ95Eq5ANjpEZsQ==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "bin": { + "elm-format": "bin/elm-format" + }, + "optionalDependencies": { + "@avh4/elm-format-darwin-arm64": "0.8.7-2", + "@avh4/elm-format-darwin-x64": "0.8.7-2", + "@avh4/elm-format-linux-arm64": "0.8.7-2", + "@avh4/elm-format-linux-x64": "0.8.7-2", + "@avh4/elm-format-win32-x64": "0.8.7-2" + } + }, + "node_modules/elm-review": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/elm-review/-/elm-review-2.12.0.tgz", + "integrity": "sha512-so+G1hvCV85A63sQQzEhCNFNYyQVWDexXrz0TNEYg3/IIGHzN1bcRN+W4KJSvvFcmfEImzMSJ9AN20bvemU+4Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "chalk": "^4.0.0", + "chokidar": "^3.5.2", + "cross-spawn": "^7.0.3", + "elm-solve-deps-wasm": "^1.0.2", + "fastest-levenshtein": "^1.0.16", + "find-up": "^4.1.0", + "folder-hash": "^3.3.0", + "fs-extra": "^9.0.0", + "glob": "^10.2.6", + "globby": "^13.2.2", + "got": "^11.8.5", + "graceful-fs": "^4.2.11", + "minimist": "^1.2.6", + "ora": "^5.4.0", + "path-key": "^3.1.1", + "prompts": "^2.2.1", + "rimraf": "^5.0.0", + "strip-ansi": "^6.0.0", + "terminal-link": "^2.1.1", + "which": "^2.0.2", + "wrap-ansi": "^7.0.0" + }, + "bin": { + "elm-review": "bin/elm-review" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/jfmengels" + } + }, + "node_modules/elm-review/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/elm-review/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/elm-solve-deps-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/elm-solve-deps-wasm/-/elm-solve-deps-wasm-1.0.2.tgz", + "integrity": "sha512-qnwo7RO9IO7jd9SLHvIy0rSOEIlc/tNMTE9Cras0kl+b161PVidW4FvXo0MtXU8GAKi/2s/HYvhcnpR/NNQ1zw==", + "dev": true, + "license": "MPL-2.0" + }, + "node_modules/elm-test": { + "version": "0.19.1-revision12", + "resolved": "https://registry.npmjs.org/elm-test/-/elm-test-0.19.1-revision12.tgz", + "integrity": "sha512-5GV3WkJ8R/faOP1hwElQdNuCt8tKx2+1lsMrdeIYWSFz01Kp9gJl/R6zGtp4QUyrUtO8KnHsxjHrQNUf2CHkrg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "commander": "^9.4.1", + "cross-spawn": "^7.0.3", + "elm-solve-deps-wasm": "^1.0.2", + "glob": "^8.0.3", + "graceful-fs": "^4.2.10", + "split": "^1.0.1", + "which": "^2.0.2", + "xmlbuilder": "^15.1.1" + }, + "bin": { + "elm-test": "bin/elm-test" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/folder-hash": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/folder-hash/-/folder-hash-3.3.3.tgz", + "integrity": "sha512-SDgHBgV+RCjrYs8aUwCb9rTgbTVuSdzvFmLaChsLre1yf+D64khCW++VYciaByZ8Rm0uKF8R/XEpXuTRSGUM1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "graceful-fs": "~4.2.0", + "minimatch": "~3.0.4" + }, + "bin": { + "folder-hash": "bin/folder-hash" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/folder-hash/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/folder-hash/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..aae7603 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "scripts": { + "test": "elm-test", + "elm-review": "elm-review", + "elm-format": "elm-format . --yes", + "elm-format:validate": "elm-format . --validate" + }, + "devDependencies": { + "elm": "^0.19.1-6", + "elm-format": "^0.8.7", + "elm-review": "^2.12.0", + "elm-test": "^0.19.1-revision12" + } +} diff --git a/review/elm.json b/review/elm.json new file mode 100644 index 0000000..e282cd2 --- /dev/null +++ b/review/elm.json @@ -0,0 +1,41 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/core": "1.0.5", + "elm/json": "1.1.3", + "elm/project-metadata-utils": "1.0.2", + "jfmengels/elm-review": "2.14.0", + "jfmengels/elm-review-code-style": "1.2.0", + "jfmengels/elm-review-common": "1.3.3", + "jfmengels/elm-review-debug": "1.0.8", + "jfmengels/elm-review-documentation": "2.0.4", + "jfmengels/elm-review-simplify": "2.1.5", + "jfmengels/elm-review-unused": "1.2.3", + "stil4m/elm-syntax": "7.3.6" + }, + "indirect": { + "elm/bytes": "1.0.8", + "elm/html": "1.0.0", + "elm/parser": "1.1.0", + "elm/random": "1.0.0", + "elm/regex": "1.0.0", + "elm/time": "1.0.0", + "elm/virtual-dom": "1.0.3", + "elm-explorations/test": "2.2.0", + "pzp1997/assoc-list": "1.0.0", + "rtfeldman/elm-hex": "1.0.0", + "stil4m/structured-writer": "1.0.3" + } + }, + "test-dependencies": { + "direct": { + "elm-explorations/test": "2.2.0" + }, + "indirect": {} + } +} \ No newline at end of file diff --git a/review/src/ReviewConfig.elm b/review/src/ReviewConfig.elm new file mode 100644 index 0000000..ab63645 --- /dev/null +++ b/review/src/ReviewConfig.elm @@ -0,0 +1,67 @@ +module ReviewConfig exposing (config) + +{-| Do not rename the ReviewConfig module or the config function, because +`elm-review` will look for these. + +To add packages that contain rules, add them to this review project using + + `elm install author/packagename` + +when inside the directory containing this file. + +-} + +import Docs.NoMissing exposing (exposedModules, onlyExposed) +import Docs.ReviewAtDocs +import Docs.ReviewLinksAndSections +import Docs.UpToDateReadmeLinks +import NoConfusingPrefixOperator +import NoDebug.Log +import NoDebug.TodoOrToString +import NoExposingEverything +import NoImportingEverything +import NoMissingTypeAnnotation +import NoMissingTypeAnnotationInLetIn +import NoMissingTypeExpose +import NoPrematureLetComputation +import NoSimpleLetBody +import NoUnused.CustomTypeConstructorArgs +import NoUnused.CustomTypeConstructors +import NoUnused.Dependencies +import NoUnused.Exports +import NoUnused.Parameters +import NoUnused.Patterns +import NoUnused.Variables +import Review.Rule as Rule exposing (Rule) +import Simplify + + +config : List Rule +config = + [ Docs.NoMissing.rule + { document = onlyExposed + , from = exposedModules + } + , Docs.ReviewLinksAndSections.rule + , Docs.ReviewAtDocs.rule + , Docs.UpToDateReadmeLinks.rule + , NoConfusingPrefixOperator.rule + , NoDebug.Log.rule + , NoDebug.TodoOrToString.rule + |> Rule.ignoreErrorsForDirectories [ "tests/" ] + , NoExposingEverything.rule + , NoImportingEverything.rule [] + , NoMissingTypeAnnotation.rule + , NoMissingTypeAnnotationInLetIn.rule + , NoMissingTypeExpose.rule + , NoSimpleLetBody.rule + , NoPrematureLetComputation.rule + , NoUnused.CustomTypeConstructors.rule [] + , NoUnused.CustomTypeConstructorArgs.rule + , NoUnused.Dependencies.rule + , NoUnused.Exports.rule + , NoUnused.Parameters.rule + , NoUnused.Patterns.rule + , NoUnused.Variables.rule + , Simplify.rule Simplify.defaults + ] diff --git a/src/Language/GLSL/Parser.elm b/src/Language/GLSL/Parser.elm new file mode 100644 index 0000000..f64ac11 --- /dev/null +++ b/src/Language/GLSL/Parser.elm @@ -0,0 +1,1915 @@ +module Language.GLSL.Parser exposing (parse) + +{-| This module is part of an Elm implementation of a GLSL parser, inspired by the +Haskell GLSL parser. + +Reference: + +This implementation attempts to adapt the concepts and structure from the +Haskell parser into the Elm ecosystem. + +@docs parse + +-} + +import Combine +import Combine.Char +import Flip exposing (flip) +import Hex +import Language.GLSL.Syntax + exposing + ( CaseLabel(..) + , Compound(..) + , Condition(..) + , Declaration(..) + , Expr(..) + , ExternalDeclaration(..) + , Field(..) + , FullType(..) + , FunctionIdentifier(..) + , FunctionPrototype(..) + , InitDeclarator(..) + , IntConstantKind(..) + , InterpolationQualifier(..) + , InvariantOrType(..) + , InvariantQualifier(..) + , LayoutQualifier(..) + , LayoutQualifierId(..) + , ParameterDeclaration(..) + , ParameterQualifier(..) + , ParameterTypeQualifier(..) + , Parameters(..) + , PrecisionQualifier(..) + , Statement(..) + , StorageQualifier(..) + , StructDeclarator(..) + , TranslationUnit(..) + , TypeQualifier(..) + , TypeSpecifier(..) + , TypeSpecifierNoPrecision(..) + , TypeSpecifierNonArray(..) + ) + + +try : P a -> P a +try = + identity + + +letter : P Char +letter = + Combine.lazy (\() -> Combine.Char.satisfy Char.isAlpha) + + +alphaNum : P Char +alphaNum = + Combine.lazy (\() -> Combine.Char.satisfy Char.isAlphaNum) + + +notFollowedBy : P a -> P () +notFollowedBy p = + Combine.maybe p + |> Combine.andThen + (\result -> + case result of + Just _ -> + Combine.fail "Unexpected match" + + Nothing -> + Combine.succeed () + ) + + +type Assoc + = AssocLeft + | AssocRight + + +type Operator tok st a + = Infix (P (a -> a -> a)) Assoc + + +buildExpressionParser : List (List (Operator Char S Expr)) -> P Expr -> P Expr +buildExpressionParser operators simpleExpr = + let + makeParser : List (Operator Char S Expr) -> P Expr -> P Expr + makeParser ops term = + let + -- { rassoc : List (P (Expr -> Expr -> Expr)), lassoc : List (P (Expr -> Expr -> Expr)), nassoc : List (P (Expr -> Expr -> Expr)), prefix : List (P (Expr -> Expr)), postfix : List (P (Expr -> Expr)) } + { rassoc, lassoc, nassoc, prefix, postfix } = + List.foldr splitOp { rassoc = [], lassoc = [], nassoc = [], prefix = [], postfix = [] } ops + + rassocOp : P (Expr -> Expr -> Expr) + rassocOp = + Combine.choice rassoc + + lassocOp : P (Expr -> Expr -> Expr) + lassocOp = + Combine.choice lassoc + + nassocOp : P (Expr -> Expr -> Expr) + nassocOp = + Combine.choice nassoc + + prefixOp : P (Expr -> Expr) + prefixOp = + Combine.choice prefix |> Combine.mapError (\_ -> [ "" ]) + + postfixOp : P (Expr -> Expr) + postfixOp = + Combine.choice postfix |> Combine.mapError (\_ -> [ "" ]) + + ambiguous : String -> P a -> P b + ambiguous assoc op = + try + (op + |> Combine.andThen + (\_ -> + Combine.fail + ("ambiguous use of a " + ++ assoc + ++ " associative operator" + ) + ) + ) + + ambiguousRight : P Expr + ambiguousRight = + ambiguous "right" rassocOp + + ambiguousLeft : P Expr + ambiguousLeft = + ambiguous "left" lassocOp + + ambiguousNon : P Expr + ambiguousNon = + ambiguous "non" nassocOp + + termP : P Expr + termP = + prefixP + |> Combine.andThen + (\pre -> + term + |> Combine.andThen + (\x -> + postfixP + |> Combine.map (\post -> post (pre x)) + ) + ) + + postfixP : P (Expr -> Expr) + postfixP = + Combine.or postfixOp (Combine.succeed identity) + + prefixP : P (Expr -> Expr) + prefixP = + Combine.or prefixOp (Combine.succeed identity) + + rassocP : Expr -> P Expr + rassocP x = + Combine.choice + [ rassocOp + |> Combine.andThen + (\f -> + termP + |> Combine.andThen rassocP1 + |> Combine.map (f x) + ) + , ambiguousLeft + , ambiguousNon + ] + + rassocP1 : Expr -> P Expr + rassocP1 x = + Combine.or (rassocP x) (Combine.succeed x) + + lassocP : Expr -> P Expr + lassocP x = + Combine.choice + [ lassocOp + |> Combine.andThen + (\f -> + termP + |> Combine.andThen lassocP1 + |> Combine.map (f x) + ) + , ambiguousRight + , ambiguousNon + ] + + lassocP1 : Expr -> P Expr + lassocP1 x = + Combine.or (lassocP x) (Combine.succeed x) + + nassocP : Expr -> P Expr + nassocP x = + nassocOp + |> Combine.andThen + (\f -> + termP + |> Combine.andThen + (\y -> + Combine.choice + [ ambiguousRight + , ambiguousLeft + , ambiguousNon + , Combine.succeed (f x y) + ] + ) + ) + in + termP + |> Combine.andThen + (\x -> + Combine.choice + [ rassocP x + , lassocP x + , nassocP x + , Combine.succeed x + ] + |> Combine.mapError (\_ -> [ "operator" ]) + ) + + splitOp : + Operator Char S Expr + -> { rassoc : List (P (Expr -> Expr -> Expr)), lassoc : List (P (Expr -> Expr -> Expr)), nassoc : List (P (Expr -> Expr -> Expr)), prefix : List (P (Expr -> Expr)), postfix : List (P (Expr -> Expr)) } + -> { rassoc : List (P (Expr -> Expr -> Expr)), lassoc : List (P (Expr -> Expr -> Expr)), nassoc : List (P (Expr -> Expr -> Expr)), prefix : List (P (Expr -> Expr)), postfix : List (P (Expr -> Expr)) } + splitOp singleOperator acc = + case singleOperator of + Infix op assoc -> + case assoc of + AssocLeft -> + { acc | lassoc = op :: acc.lassoc } + + AssocRight -> + { acc | rassoc = op :: acc.rassoc } + in + List.foldl makeParser simpleExpr operators + + + +---------------------------------------------------------------------- +-- Parser state, hold a symbol table. +---------------------------------------------------------------------- + + +type alias S = + () + + +type alias P a = + Combine.Parser S a + + + +---------------------------------------------------------------------- +-- Reserved words +---------------------------------------------------------------------- +-- List of keywords. + + +keywords : List String +keywords = + List.concatMap String.words + [ "attribute const uniform varying" + , "layout" + , "centroid flat smooth noperspective" + , "break continue do for while switch case default" + , "if else" + , "in out inout" + , "float int void bool true false" + , "invariant" + , "discard return" + , "mat2 mat3 mat4" + , "mat2x2 mat2x3 mat2x4" + , "mat3x2 mat3x3 mat3x4" + , "mat4x2 mat4x3 mat4x4" + , "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4" + , "uint uvec2 uvec3 uvec4" + , "lowp mediump highp precision" + , "sampler1D sampler2D sampler3D samplerCube" + , "sampler1DShadow sampler2DShadow samplerCubeShadow" + , "sampler1DArray sampler2DArray" + , "sampler1DArrayShadow sampler2DArrayShadow" + , "isampler1D isampler2D isampler3D isamplerCube" + , "isampler1DArray isampler2DArray" + , "usampler1D usampler2D usampler3D usamplerCube" + , "usampler1DArray usampler2DArray" + , "sampler2DRect sampler2DRectShadow isampler2DRect usampler2DRect" + , "samplerBuffer isamplerBuffer usamplerBuffer" + , "sampler2DMS isampler2DMS usampler2DMS" + , "sampler2DMSArray isampler2DMSArray usampler2DMSArray" + , "struct" + ] + + + +-- List of keywords reserved for future use. + + +reservedWords : List String +reservedWords = + List.concatMap String.words + [ "common partition active" + , "asm" + , "class union enum typedef template this packed" + , "goto" + , "inline noinline volatile public static extern external interface" + , "long short double half fixed unsigned superp" + , "input output" + , "hvec2 hvec3 hvec4 dvec2 dvec3 dvec4 fvec2 fvec3 fvec4" + , "sampler3DRect" + , "filter" + , "image1D image2D image3D imageCube" + , "iimage1D iimage2D iimage3D iimageCube" + , "uimage1D uimage2D uimage3D uimageCube" + , "image1DArray image2DArray" + , "iimage1DArray iimage2DArray uimage1DArray uimage2DArray" + , "image1DShadow image2DShadow" + , "image1DArrayShadow image2DArrayShadow" + , "imageBuffer iimageBuffer uimageBuffer" + , "sizeof cast" + , "namespace using" + , "row_major" + ] + + + +---------------------------------------------------------------------- +-- Convenience parsers +---------------------------------------------------------------------- + + +comment : P () +comment = + Combine.lazy + (\() -> + Combine.Char.char '/' + |> Combine.keep + (Combine.choice + [ Combine.Char.char '*' + |> Combine.ignore (Combine.manyTill Combine.Char.anyChar (try <| Combine.string "*/")) + |> Combine.onsuccess () + , Combine.Char.char '/' + |> Combine.ignore + (Combine.manyTill Combine.Char.anyChar + (Combine.choice + [ Combine.Char.newline |> Combine.onsuccess () + , Combine.end + ] + ) + ) + |> Combine.onsuccess () + ] + ) + ) + + +blank : P () +blank = + Combine.lazy + (\() -> + Combine.or + comment + (Combine.whitespace |> Combine.onsuccess ()) + ) + + +lexeme : P a -> P a +lexeme p = + p + |> Combine.ignore (Combine.skipMany blank) + + +{-| Parses a GLSL shader string into an abstract syntax tree (AST). + +This function attempts to parse a given GLSL shader and returns either the parsed result +as a `TranslationUnit` type or an error message if parsing fails. + +-} +parse : String -> Result String TranslationUnit +parse = + Combine.parse + (Combine.skipMany blank + |> Combine.keep translationUnit + |> Combine.ignore Combine.end + ) + + + +---------------------------------------------------------------------- +-- Lexical elements (tokens) +---------------------------------------------------------------------- + + +semicolon : P () +semicolon = + Combine.lazy (\() -> lexeme (Combine.Char.char ';' |> Combine.onsuccess ())) + + +comma : P () +comma = + Combine.lazy (\() -> lexeme (Combine.Char.char ',' |> Combine.onsuccess ())) + + +colon : P () +colon = + Combine.lazy (\() -> lexeme (Combine.Char.char ':' |> Combine.onsuccess ())) + + +lbrace : P () +lbrace = + Combine.lazy (\() -> lexeme (Combine.Char.char '{' |> Combine.onsuccess ())) + + +rbrace : P () +rbrace = + Combine.lazy (\() -> lexeme (Combine.Char.char '}' |> Combine.onsuccess ())) + + +lbracket : P () +lbracket = + Combine.lazy (\() -> lexeme (Combine.Char.char '[' |> Combine.onsuccess ())) + + +rbracket : P () +rbracket = + Combine.lazy (\() -> lexeme (Combine.Char.char ']' |> Combine.onsuccess ())) + + +lparen : P () +lparen = + Combine.lazy (\() -> lexeme (Combine.Char.char '(' |> Combine.onsuccess ())) + + +rparen : P () +rparen = + Combine.lazy (\() -> lexeme (Combine.Char.char ')' |> Combine.onsuccess ())) + + + +-- Try to parse a given string, making sure it is not a +-- prefix of an identifier. + + +keyword : String -> P () +keyword w = + Combine.lazy + (\() -> + lexeme <| + try + (Combine.string w + |> Combine.keep (notFollowedBy identifierTail) + ) + ) + + + +-- Parses and returns an identifier. +-- TODO an identifier can't start with "gl_" unless +-- it is to redeclare a predeclared "gl_" identifier. + + +identifier : P String +identifier = + Combine.lazy + (\() -> + let + check : String -> P String + check i = + if List.member i reservedWords then + Combine.fail (i ++ " is reserved") + + else if List.member i keywords then + Combine.fail (i ++ " is a keyword") + + else + checkUnderscore i (String.toList i) + + checkUnderscore : String -> List Char -> P String + checkUnderscore i i2 = + case i2 of + '_' :: '_' :: _ -> + Combine.fail (i ++ " is reserved (two consecutive underscores)") + + _ :: cs -> + checkUnderscore i cs + + [] -> + Combine.succeed i + in + lexeme + (identifierHead + |> Combine.andThen + (\h -> + Combine.many identifierTail + |> Combine.andThen + (\t -> + check (String.fromList (h :: t)) + ) + ) + ) + ) + + + +-- TODO the size of the int should fit its type. + + +intConstant : P Expr +intConstant = + Combine.lazy + (\() -> + Combine.choice + [ hexadecimal + , octal + , badOctal + |> Combine.andThen (\_ -> Combine.fail "Invalid octal number") + , decimal + ] + ) + + +floatingConstant : P Expr +floatingConstant = + Combine.lazy + (\() -> + Combine.choice + [ floatExponent + , floatPoint + , pointFloat + ] + ) + + + +-- Try to parse a given string, and allow identifier characters +-- (or anything else) to directly follow. + + +operator : String -> P String +operator = + lexeme << try << Combine.string + + + +---------------------------------------------------------------------- +-- Lexical elements helpers +---------------------------------------------------------------------- + + +identifierHead : P Char +identifierHead = + Combine.lazy (\() -> Combine.or letter (Combine.Char.char '_')) + + +identifierTail : P Char +identifierTail = + Combine.lazy (\() -> Combine.or alphaNum (Combine.Char.char '_')) + + +hexadecimal : P Expr +hexadecimal = + Combine.lazy + (\() -> + lexeme + (try + (Combine.Char.char '0' + |> Combine.ignore (Combine.Char.oneOf [ 'X', 'x' ]) + |> Combine.keep (Combine.many1 Combine.Char.hexDigit) + |> Combine.andThen + (\d -> + -- TODO + Combine.maybe (Combine.Char.oneOf [ 'U', 'u' ]) + |> Combine.andThen + (\_ -> + case Hex.fromString (String.fromList d) of + Ok val -> + Combine.succeed (IntConstant Hexadecimal val) + + Err err -> + Combine.fail err + ) + ) + ) + ) + ) + + +octal : P Expr +octal = + Combine.lazy + (\() -> + lexeme + (try + (Combine.Char.char '0' + |> Combine.keep (Combine.many1 Combine.Char.octDigit) + |> Combine.andThen + (\d -> + -- TODO + Combine.maybe (Combine.Char.oneOf [ 'U', 'u' ]) + |> Combine.andThen + (\_ -> + case octFromString (String.fromList d) of + Ok val -> + Combine.succeed (IntConstant Octal val) + + Err err -> + Combine.fail err + ) + ) + ) + ) + ) + + +octFromString : String -> Result String Int +octFromString _ = + Debug.todo "octFromString" + + +badOctal : P () +badOctal = + Combine.lazy + (\() -> + lexeme + (try + (Combine.Char.char '0' + |> Combine.keep (Combine.many1 Combine.Char.hexDigit) + |> Combine.onsuccess () + ) + ) + ) + + +decimal : P Expr +decimal = + Combine.lazy + (\() -> + lexeme + (try + (Combine.many1 Combine.Char.digit + |> Combine.ignore (notFollowedBy (Combine.or (Combine.Char.char '.') (exponent |> Combine.onsuccess ' '))) + |> Combine.ignore + -- TODO + (Combine.maybe (Combine.Char.oneOf [ 'U', 'u' ])) + |> Combine.andThen + (\d -> + case String.toInt (String.fromList d) of + Just val -> + Combine.succeed (IntConstant Decimal val) + + Nothing -> + Combine.fail "Invalid decimal number" + ) + ) + ) + ) + + +floatExponent : P Expr +floatExponent = + Combine.lazy + (\() -> + lexeme + (try + (Combine.many1 Combine.Char.digit + |> Combine.andThen + (\d -> + exponent + |> Combine.andThen + (\e -> + Combine.maybe (Combine.Char.oneOf [ 'F', 'f' ]) + -- TODO + |> Combine.andThen + (\_ -> + case String.toFloat (String.fromList d ++ e) of + Just val -> + Combine.succeed (FloatConstant val) + + Nothing -> + Combine.fail "Invalid float exponent number" + ) + ) + ) + ) + ) + ) + + +floatPoint : P Expr +floatPoint = + Combine.lazy + (\() -> + lexeme + (try + (Combine.many1 Combine.Char.digit + |> Combine.andThen + (\d -> + Combine.Char.char '.' + |> Combine.andThen + (\_ -> + Combine.many Combine.Char.digit + |> Combine.andThen + (\d_ -> + let + d__ : String + d__ = + if List.isEmpty d_ then + "0" + + else + String.fromList d_ + in + Combine.maybe exponent + |> Combine.andThen + (\e -> + Combine.maybe (Combine.Char.oneOf [ 'F', 'f' ]) + -- TODO + |> Combine.andThen + (\_ -> + case String.toFloat (String.fromList d ++ "." ++ d__ ++ Maybe.withDefault "" e) of + Just val -> + Combine.succeed (FloatConstant val) + + Nothing -> + Combine.fail "Invalid float point number" + ) + ) + ) + ) + ) + ) + ) + ) + + +pointFloat : P Expr +pointFloat = + Combine.lazy + (\() -> + lexeme + (try + (Combine.Char.char '.' + |> Combine.andThen + (\_ -> + Combine.many1 Combine.Char.digit + |> Combine.andThen + (\d -> + Combine.maybe exponent + |> Combine.andThen + (\e -> + Combine.maybe (Combine.Char.oneOf [ 'F', 'f' ]) + |> Combine.andThen + (\_ -> + case String.toFloat ("0." ++ String.fromList d ++ Maybe.withDefault "" e) of + Just val -> + Combine.succeed (FloatConstant val) + + Nothing -> + Combine.fail "Invalid point float number" + ) + ) + ) + ) + ) + ) + ) + + +exponent : P String +exponent = + Combine.lazy + (\() -> + lexeme + (try + (Combine.Char.oneOf [ 'E', 'e' ] + |> Combine.andThen + (\_ -> + Combine.maybe (Combine.Char.oneOf [ '+', '-' ]) + |> Combine.andThen + (\s -> + Combine.many1 Combine.Char.digit + |> Combine.map + (\d -> + "e" + ++ Maybe.withDefault "" (Maybe.map String.fromChar s) + ++ String.fromList d + ) + ) + ) + ) + ) + ) + + + +---------------------------------------------------------------------- +-- Tables for buildExpressionParser +---------------------------------------------------------------------- + + +infixLeft : String -> (a -> a -> a) -> Operator Char S a +infixLeft s r = + Infix (lexeme (try <| Combine.string s) |> Combine.onsuccess r) AssocLeft + + +infixLeft_ : String -> (a -> a -> a) -> Operator Char S a +infixLeft_ s r = + Infix + (lexeme + (try (Combine.string s) + |> Combine.ignore (notFollowedBy (Combine.Char.char '=')) + ) + |> Combine.onsuccess r + ) + AssocLeft + + +infixLeft__ : Char -> (a -> a -> a) -> Operator Char S a +infixLeft__ c r = + Infix + (lexeme + (try (Combine.Char.char c) + |> Combine.ignore (notFollowedBy (Combine.Char.oneOf [ c, '=' ])) + ) + |> Combine.onsuccess r + ) + AssocLeft + + +infixRight : String -> (a -> a -> a) -> Operator Char S a +infixRight s r = + Infix (lexeme (try <| Combine.string s) |> Combine.onsuccess r) AssocRight + + +conditionalTable : List (List (Operator Char S Expr)) +conditionalTable = + [ [ infixLeft_ "*" Mul, infixLeft_ "/" Div, infixLeft_ "%" Mod ] + , [ infixLeft_ "+" Add, infixLeft_ "-" Sub ] + , [ infixLeft_ "<<" LeftShift, infixLeft_ ">>" RightShift ] + , [ infixLeft_ "<" Lt + , infixLeft_ ">" Gt + , infixLeft "<=" Lte + , infixLeft ">=" Gte + ] + , [ infixLeft "==" Equ, infixLeft "!=" Neq ] + , [ infixLeft__ '&' BitAnd ] + , [ infixLeft_ "^" BitXor ] + , [ infixLeft__ '|' BitOr ] + , [ infixLeft "&&" And ] + , [ infixLeft "||" Or ] + ] + + +assignmentTable : List (List (Operator Char S Expr)) +assignmentTable = + [ [ infixRight "=" Equal ] + , [ infixRight "+=" AddAssign ] + , [ infixRight "-=" SubAssign ] + , [ infixRight "*=" MulAssign ] + , [ infixRight "/=" DivAssign ] + , [ infixRight "%=" ModAssign ] + , [ infixRight "<<=" LeftAssign ] + , [ infixRight ">>=" RightAssign ] + , [ infixRight "&=" AndAssign ] + , [ infixRight "^=" XorAssign ] + , [ infixRight "|=" OrAssign ] + ] + + +expressionTable : List (List (Operator Char S Expr)) +expressionTable = + [ [ infixLeft "," Sequence ] + ] + + + +---------------------------------------------------------------------- +-- Grammar +---------------------------------------------------------------------- + + +primaryExpression : P Expr +primaryExpression = + Combine.lazy + (\() -> + Combine.choice + [ Combine.map Variable (try identifier) + + -- int constant + , intConstant + + -- uint constant + -- float constant + , floatingConstant + + -- bool constant + , keyword "true" |> Combine.onsuccess (BoolConstant True) + , keyword "false" |> Combine.onsuccess (BoolConstant False) + + -- expression within parentheses + , Combine.between lparen rparen expression + ] + ) + + +postfixExpression : P Expr +postfixExpression = + Combine.lazy + (\() -> + Combine.or + (try + (functionCallGeneric + |> Combine.map (\( i, p ) -> FunctionCall i p) + ) + ) + primaryExpression + |> Combine.andThen + (\e -> + Combine.many + (Combine.choice + [ Combine.between lbracket rbracket integerExpression + |> Combine.map (flip Bracket) + , dotFunctionCallGeneric + , dotFieldSelection + , operator "++" |> Combine.onsuccess PostInc + , operator "--" |> Combine.onsuccess PostDec + ] + ) + |> Combine.map (\p -> List.foldl (<|) e p) + ) + ) + + +dotFunctionCallGeneric : P (Expr -> Expr) +dotFunctionCallGeneric = + Combine.lazy + (\() -> + lexeme (try (Combine.string ".") |> Combine.keep functionCallGeneric) + |> Combine.map (\( i, p ) e -> MethodCall e i p) + ) + + +dotFieldSelection : P (Expr -> Expr) +dotFieldSelection = + Combine.lazy + (\() -> + lexeme (try (Combine.string ".") |> Combine.keep identifier) + |> Combine.map (flip FieldSelection) + ) + + +integerExpression : P Expr +integerExpression = + Combine.lazy (\() -> expression) + + + +-- Those productions are pushed inside postfixExpression. +-- functionCall = functionCallOrMethod +-- functionCallOrMethod = functionCallGeneric <|> postfixExpression DOT functionCallGeneric + + +functionCallGeneric : P ( FunctionIdentifier, Parameters ) +functionCallGeneric = + Combine.lazy + (\() -> + functionCallHeader + |> Combine.andThen + (\i -> + Combine.choice + [ keyword "void" |> Combine.onsuccess ParamVoid + , Combine.sepBy comma assignmentExpression + |> Combine.map Params + ] + |> Combine.andThen + (\p -> + rparen + |> Combine.onsuccess ( i, p ) + ) + ) + ) + + + +-- Those productions are pushed inside functionCallGeneric. +-- functionCallHeaderNoParameters = undefined +-- functionCallHeaderWithParameters = undefined + + +functionCallHeader : P FunctionIdentifier +functionCallHeader = + Combine.lazy + (\() -> + functionIdentifier + |> Combine.andThen + (\i -> + lparen + |> Combine.onsuccess i + ) + ) + + +functionIdentifier : P FunctionIdentifier +functionIdentifier = + Combine.lazy + (\() -> + Combine.choice + [ try identifier |> Combine.map FuncId + + -- TODO if the 'identifier' is declared as a type, should be this case + , typeSpecifier |> Combine.map FuncIdTypeSpec + + -- no need for fieldSelection + ] + ) + + +unaryExpression : P Expr +unaryExpression = + Combine.lazy + (\() -> + Combine.many + (Combine.choice + [ operator "++" |> Combine.onsuccess PreInc + , operator "--" |> Combine.onsuccess PreDec + , operator "+" |> Combine.onsuccess UnaryPlus + , operator "-" |> Combine.onsuccess UnaryNegate + , operator "!" |> Combine.onsuccess UnaryNot + , operator "~" |> Combine.onsuccess UnaryOneComplement + ] + ) + |> Combine.andThen + (\p -> + postfixExpression + |> Combine.map + (\e -> + List.foldr (<|) e p + ) + ) + ) + + + +-- inside unaryExpression +-- unaryOperator = choice +-- implemented throught buildExpressionParser +-- multiplicativeExpression = undefined +-- additiveExpression = undefined +-- shiftExpression = undefined +-- relationalExpression = undefined +-- equalityExpression = undefined +-- andExpression = undefined +-- exclusiveOrExpression = undefined +-- inclusiveOrExpression = undefined +-- logicalAndExpression = undefined +-- logicalXorExpression = undefined +-- logicalOrExpression = undefined + + +conditionalExpression : P Expr +conditionalExpression = + Combine.lazy + (\() -> + buildExpressionParser conditionalTable unaryExpression + |> Combine.andThen + (\loe -> + Combine.maybe + (lexeme (Combine.string "?") + |> Combine.keep expression + |> Combine.ignore (lexeme (Combine.string ":")) + |> Combine.andThen + (\e -> + assignmentExpression + |> Combine.map (\a -> ( e, a )) + ) + ) + |> Combine.map + (\ter -> + case ter of + Nothing -> + loe + + Just ( e, a ) -> + Selection loe e a + ) + ) + ) + + +assignmentExpression : P Expr +assignmentExpression = + Combine.lazy (\() -> buildExpressionParser assignmentTable conditionalExpression) + + +expression : P Expr +expression = + Combine.lazy (\() -> buildExpressionParser expressionTable assignmentExpression) + + +constantExpression : P Expr +constantExpression = + Combine.lazy (\() -> conditionalExpression) + + + +-- The GLSL grammar include here function definition but we don't +-- do this here because they should occur only at top level (page 28). +-- Function definitions are handled in externalDefinition instead. + + +declaration : P Declaration +declaration = + Combine.lazy + (\() -> + let + idecl : P InitDeclarator + idecl = + identifier + |> Combine.andThen + (\i -> + Combine.maybe (Combine.between lbracket rbracket (Combine.maybe constantExpression)) + |> Combine.andThen + (\m -> + Combine.maybe (lexeme (Combine.string "=") |> Combine.keep initializer) + |> Combine.map (InitDecl i m) + ) + ) + in + Combine.choice + [ try + (fullySpecifiedType + |> Combine.andThen + (\t -> + Combine.sepBy comma idecl + |> Combine.ignore semicolon + |> Combine.map (InitDeclaration (TypeDeclarator t)) + ) + ) + , keyword "invariant" + |> Combine.keep (Combine.sepBy comma idecl) + |> Combine.ignore semicolon + |> Combine.map (InitDeclaration InvariantDeclarator) + , keyword "precision" + |> Combine.keep precisionQualifier + |> Combine.andThen + (\q -> + typeSpecifierNoPrecision + |> Combine.ignore semicolon + |> Combine.map (Precision q) + ) + , typeQualifier + |> Combine.andThen + (\q -> + Combine.choice + [ semicolon |> Combine.onsuccess (TQ q) + , identifier + |> Combine.ignore lbrace + |> Combine.andThen + (\i -> + structDeclarationList + |> Combine.ignore rbrace + |> Combine.andThen + (\s -> + Combine.maybe + (identifier + |> Combine.andThen + (\j -> + Combine.maybe (Combine.between lbracket rbracket (Combine.maybe constantExpression)) + |> Combine.map (\n -> ( j, n )) + ) + ) + |> Combine.ignore semicolon + |> Combine.map (\m -> Block q i s m) + ) + ) + ] + ) + ] + ) + + +functionPrototype : P FunctionPrototype +functionPrototype = + Combine.lazy + (\() -> + functionDeclarator + |> Combine.andThen + (\( t, i, p ) -> + rparen + |> Combine.onsuccess (FuncProt t i p) + ) + ) + + +functionDeclarator : P ( FullType, String, List ParameterDeclaration ) +functionDeclarator = + Combine.lazy + (\() -> + functionHeader + |> Combine.andThen + (\( t, i ) -> + Combine.sepBy comma parameterDeclaration + |> Combine.map (\p -> ( t, i, p )) + ) + ) + + + +-- inside functionDeclarator +-- functionHeaderWithParameters = undefined + + +functionHeader : P ( FullType, String ) +functionHeader = + Combine.lazy + (\() -> + fullySpecifiedType + |> Combine.andThen + (\t -> + identifier + |> Combine.andThen + (\i -> + lparen + |> Combine.onsuccess ( t, i ) + ) + ) + ) + + + +-- inside parameterDeclaration +-- parameterDeclarator = undefined +-- expanding parameterDeclarator and parameterTypeSpecifier, the rule is: +-- parameterDeclaration: +-- parameterTypeQualifier [parameterQualifier] typeSpecifier identifier[[e]] +-- [parameterQualifier] typeSpecifier identifier[[e]] +-- parameterTypeQualifier [parameterQualifier] typeSpecifier +-- [parameterQualifier] typeSpecifier +-- which is simply +-- [parameterTypeQualifier] [parameterQualifier] typeSpecifier [identifier[[e]]] + + +parameterDeclaration : P ParameterDeclaration +parameterDeclaration = + Combine.lazy + (\() -> + Combine.maybe parameterTypeQualifier + |> Combine.andThen + (\tq -> + Combine.maybe parameterQualifier + |> Combine.andThen + (\q -> + typeSpecifier + |> Combine.andThen + (\s -> + Combine.maybe + (identifier + |> Combine.andThen + (\i -> + -- FIXME can't the bracket be empty, i.e. a[] ? + Combine.maybe (Combine.between lbracket rbracket constantExpression) + |> Combine.map (\b -> ( i, b )) + ) + ) + |> Combine.map (\m -> ParameterDeclaration tq q s m) + ) + ) + ) + ) + + +parameterQualifier : P ParameterQualifier +parameterQualifier = + Combine.lazy + (\() -> + Combine.choice + -- "empty" case handled in the caller + [ (try << lexeme << Combine.string) "inout" |> Combine.onsuccess InOutParameter + , (try << lexeme << Combine.string) "in" |> Combine.onsuccess InParameter + , (try << lexeme << Combine.string) "out" |> Combine.onsuccess OutParameter + ] + ) + + + +-- inside parameterDeclaration +-- parameterTypeSpecifier = typeSpecifier +-- FIXME not correct w.r.t. the specs. +-- The specs allow +-- int +-- int, foo +-- invariant foo, bar[] +-- and disallow +-- invariant bar[] +-- It is not used, it is inside declaration. +-- initDeclaratorList = undefined +-- inside initDeclaratorList +-- singleDeclaration = undefined + + +fullySpecifiedType : P FullType +fullySpecifiedType = + Combine.lazy + (\() -> + Combine.choice + [ try typeSpecifier |> Combine.map (FullType Nothing) + , typeQualifier + |> Combine.andThen + (\q -> + typeSpecifier + |> Combine.map (FullType (Just q)) + ) + ] + ) + + +invariantQualifier : P InvariantQualifier +invariantQualifier = + Combine.lazy (\() -> keyword "invariant" |> Combine.onsuccess Invariant) + + +interpolationQualifier : P InterpolationQualifier +interpolationQualifier = + Combine.lazy + (\() -> + Combine.choice + [ keyword "smooth" |> Combine.onsuccess Smooth + , keyword "flat" |> Combine.onsuccess Flat + , keyword "noperspective" |> Combine.onsuccess NoPerspective + ] + ) + + +layoutQualifier : P LayoutQualifier +layoutQualifier = + Combine.lazy + (\() -> + Combine.sequence [ keyword "layout", lparen ] + |> Combine.keep (Combine.sepBy comma layoutQualifierId) + |> Combine.ignore rparen + |> Combine.map Layout + ) + + + +-- implemented directly in layoutQualifier +-- layoutQualifierIdList = undefined + + +layoutQualifierId : P LayoutQualifierId +layoutQualifierId = + Combine.lazy + (\() -> + identifier + |> Combine.andThen + (\i -> + Combine.maybe (lexeme (Combine.string "=") |> Combine.keep intConstant) + |> Combine.map (LayoutQualId i) + ) + ) + + +parameterTypeQualifier : P ParameterTypeQualifier +parameterTypeQualifier = + Combine.lazy (\() -> keyword "const" |> Combine.onsuccess ConstParameter) + + + +-- sto +-- lay [sto] +-- int [sto] +-- inv [sto] +-- inv int sto + + +typeQualifier : P TypeQualifier +typeQualifier = + Combine.lazy + (\() -> + Combine.choice + [ storageQualifier + |> Combine.map TypeQualSto + , layoutQualifier + |> Combine.andThen + (\l -> + Combine.maybe storageQualifier + |> Combine.map (TypeQualLay l) + ) + , interpolationQualifier + |> Combine.andThen + (\i -> + Combine.maybe storageQualifier + |> Combine.map (TypeQualInt i) + ) + , invariantQualifier + |> Combine.andThen + (\i -> + Combine.choice + [ interpolationQualifier + |> Combine.andThen + (\j -> + storageQualifier + |> Combine.map (TypeQualInv3 i j) + ) + , Combine.maybe storageQualifier + |> Combine.map (TypeQualInv i) + ] + ) + ] + ) + + + +-- TODO see 4.3 for restrictions + + +storageQualifier : P StorageQualifier +storageQualifier = + Combine.lazy + (\() -> + Combine.choice + [ keyword "const" |> Combine.onsuccess Const + , keyword "attribute" |> Combine.onsuccess Attribute -- TODO vertex only, is deprecated + , keyword "varying" |> Combine.onsuccess Varying -- deprecated + , keyword "in" |> Combine.onsuccess In + , keyword "out" |> Combine.onsuccess Out + , keyword "centroid" + |> Combine.keep + (Combine.choice + [ keyword "varying" |> Combine.onsuccess CentroidVarying -- deprecated + , keyword "in" |> Combine.onsuccess CentroidIn + , keyword "out" |> Combine.onsuccess CentroidOut + ] + ) + , keyword "uniform" |> Combine.onsuccess Uniform + ] + ) + + +typeSpecifier : P TypeSpecifier +typeSpecifier = + Combine.lazy + (\() -> + Combine.choice + [ try precisionQualifier + |> Combine.andThen + (\q -> + typeSpecifierNoPrecision + |> Combine.map (\s -> TypeSpec (Just q) s) + ) + , typeSpecifierNoPrecision |> Combine.map (TypeSpec Nothing) + ] + ) + + +typeSpecifierNoPrecision : P TypeSpecifierNoPrecision +typeSpecifierNoPrecision = + Combine.lazy + (\() -> + typeSpecifierNonArray + |> Combine.andThen + (\s -> + Combine.choice + [ try (Combine.sequence [ lbracket, rbracket ]) + |> Combine.onsuccess (TypeSpecNoPrecision s (Just Nothing)) + , lbracket + |> Combine.keep constantExpression + |> Combine.andThen + (\c -> + rbracket + |> Combine.onsuccess (TypeSpecNoPrecision s (Just (Just c))) + ) + , Combine.succeed (TypeSpecNoPrecision s Nothing) + ] + ) + ) + + + +-- Basic types, structs, and user-defined types. + + +typeSpecifierNonArray : P TypeSpecifierNonArray +typeSpecifierNonArray = + Combine.lazy + (\() -> + Combine.choice + [ keyword "void" |> Combine.onsuccess Void + , keyword "float" |> Combine.onsuccess Float + , keyword "int" |> Combine.onsuccess Int + , keyword "uint" |> Combine.onsuccess UInt + , keyword "bool" |> Combine.onsuccess Bool + , keyword "vec2" |> Combine.onsuccess Vec2 + , keyword "vec3" |> Combine.onsuccess Vec3 + , keyword "vec4" |> Combine.onsuccess Vec4 + , keyword "bvec2" |> Combine.onsuccess BVec2 + , keyword "bvec3" |> Combine.onsuccess BVec3 + , keyword "bvec4" |> Combine.onsuccess BVec4 + , keyword "ivec2" |> Combine.onsuccess IVec2 + , keyword "ivec3" |> Combine.onsuccess IVec3 + , keyword "ivec4" |> Combine.onsuccess IVec4 + , keyword "uvec2" |> Combine.onsuccess UVec2 + , keyword "uvec3" |> Combine.onsuccess UVec3 + , keyword "uvec4" |> Combine.onsuccess UVec4 + , keyword "mat2" |> Combine.onsuccess Mat2 + , keyword "mat3" |> Combine.onsuccess Mat3 + , keyword "mat4" |> Combine.onsuccess Mat4 + , keyword "mat2x2" |> Combine.onsuccess Mat2x2 + , keyword "mat2x3" |> Combine.onsuccess Mat2x3 + , keyword "mat2x4" |> Combine.onsuccess Mat2x4 + , keyword "mat3x2" |> Combine.onsuccess Mat3x2 + , keyword "mat3x3" |> Combine.onsuccess Mat3x3 + , keyword "mat3x4" |> Combine.onsuccess Mat3x4 + , keyword "mat4x2" |> Combine.onsuccess Mat4x2 + , keyword "mat4x3" |> Combine.onsuccess Mat4x3 + , keyword "mat4x4" |> Combine.onsuccess Mat4x4 + , keyword "sampler1D" |> Combine.onsuccess Sampler1D + , keyword "sampler2D" |> Combine.onsuccess Sampler2D + , keyword "sampler3D" |> Combine.onsuccess Sampler3D + , keyword "samplerCube" |> Combine.onsuccess SamplerCube + , keyword "sampler1DShadow" |> Combine.onsuccess Sampler1DShadow + , keyword "sampler2DShadow" |> Combine.onsuccess Sampler2DShadow + , keyword "samplerCubeShadow" |> Combine.onsuccess SamplerCubeShadow + , keyword "sampler1DArray" |> Combine.onsuccess Sampler1DArray + , keyword "sampler2DArray" |> Combine.onsuccess Sampler2DArray + , keyword "sampler1DArrayShadow" |> Combine.onsuccess Sampler1DArrayShadow + , keyword "sampler2DArrayShadow" |> Combine.onsuccess Sampler2DArrayShadow + , keyword "isampler1D" |> Combine.onsuccess ISampler1D + , keyword "isampler2D" |> Combine.onsuccess ISampler2D + , keyword "isampler3D" |> Combine.onsuccess ISampler3D + , keyword "isamplerCube" |> Combine.onsuccess ISamplerCube + , keyword "isampler1DArray" |> Combine.onsuccess ISampler1DArray + , keyword "isampler2DArray" |> Combine.onsuccess ISampler2DArray + , keyword "usampler1D" |> Combine.onsuccess USampler1D + , keyword "usampler2D" |> Combine.onsuccess USampler2D + , keyword "usampler3D" |> Combine.onsuccess USampler3D + , keyword "usamplerCube" |> Combine.onsuccess USamplerCube + , keyword "usampler1DArray" |> Combine.onsuccess USampler1DArray + , keyword "usampler2DArray" |> Combine.onsuccess USampler2DArray + , keyword "sampler2DRect" |> Combine.onsuccess Sampler2DRect + , keyword "sampler2DRectShadow" |> Combine.onsuccess Sampler2DRectShadow + , keyword "isampler2DRect" |> Combine.onsuccess ISampler2DRect + , keyword "usampler2DRect" |> Combine.onsuccess USampler2DRect + , keyword "samplerBuffer" |> Combine.onsuccess SamplerBuffer + , keyword "isamplerBuffer" |> Combine.onsuccess ISamplerBuffer + , keyword "usamplerBuffer" |> Combine.onsuccess USamplerBuffer + , keyword "sampler2DMS" |> Combine.onsuccess Sampler2DMS + , keyword "isampler2DMS" |> Combine.onsuccess ISampler2DMS + , keyword "usampler2DMS" |> Combine.onsuccess USampler2DMS + , keyword "sampler2DMSArray" |> Combine.onsuccess Sampler2DMSArray + , keyword "isampler2DMSArray" |> Combine.onsuccess ISampler2DMSArray + , keyword "usampler2DMSArray" |> Combine.onsuccess USampler2DMSArray + , structSpecifier + , identifier |> Combine.map TypeName -- verify if it is declared + ] + ) + + +precisionQualifier : P PrecisionQualifier +precisionQualifier = + Combine.lazy + (\() -> + Combine.choice + [ keyword "highp" |> Combine.onsuccess HighP + , keyword "mediump" |> Combine.onsuccess MediumP + , keyword "lowp" |> Combine.onsuccess LowP + ] + ) + + +structSpecifier : P TypeSpecifierNonArray +structSpecifier = + Combine.lazy + (\() -> + keyword "struct" + |> Combine.keep (Combine.maybe identifier) + |> Combine.andThen + (\i -> + lbrace + |> Combine.keep structDeclarationList + |> Combine.andThen + (\d -> + rbrace + |> Combine.map (\_ -> StructSpecifier i d) + ) + ) + ) + + +structDeclarationList : P (List Field) +structDeclarationList = + Combine.lazy (\() -> Combine.many1 structDeclaration) + + +structDeclaration : P Field +structDeclaration = + Combine.lazy + (\() -> + Combine.maybe typeQualifier + |> Combine.andThen + (\q -> + typeSpecifier + |> Combine.andThen + (\s -> + structDeclaratorList + |> Combine.andThen + (\l -> + semicolon + |> Combine.map (\_ -> Field q s l) + ) + ) + ) + ) + + +structDeclaratorList : P (List StructDeclarator) +structDeclaratorList = + Combine.lazy (\() -> Combine.sepBy comma structDeclarator) + + +structDeclarator : P StructDeclarator +structDeclarator = + Combine.lazy + (\() -> + identifier + |> Combine.andThen + (\i -> + Combine.choice + [ lbracket + |> Combine.keep (Combine.maybe constantExpression) + |> Combine.ignore rbracket + |> Combine.map (\e -> StructDeclarator i (Just e)) + , Combine.succeed (StructDeclarator i Nothing) + ] + ) + ) + + +initializer : P Expr +initializer = + Combine.lazy (\() -> assignmentExpression) + + +declarationStatement : P Declaration +declarationStatement = + Combine.lazy (\() -> declaration) + + +statement : P Statement +statement = + Combine.lazy + (\() -> + Combine.or (Combine.map CompoundStatement (Combine.lazy (\() -> compoundStatement))) + (Combine.lazy (\() -> simpleStatement)) + ) + + +simpleStatement : P Statement +simpleStatement = + Combine.lazy + (\() -> + Combine.choice + [ declarationStatement |> Combine.map DeclarationStatement + , expressionStatement |> Combine.map ExpressionStatement + , selectionStatement + , switchStatement + , caseLabel |> Combine.map CaseLabel + , iterationStatement + , jumpStatement + ] + ) + + +compoundStatement : P Compound +compoundStatement = + Combine.lazy + (\() -> + Combine.choice + [ try (Combine.sequence [ lbrace, rbrace ]) + |> Combine.onsuccess (Compound []) + , Combine.between lbrace rbrace (Combine.lazy (\() -> statementList)) + |> Combine.map Compound + ] + ) + + +statementNoNewScope : P Statement +statementNoNewScope = + Combine.lazy + (\() -> + Combine.or + (Combine.map CompoundStatement compoundStatementNoNewScope) + simpleStatement + ) + + +compoundStatementNoNewScope : P Compound +compoundStatementNoNewScope = + Combine.lazy (\() -> compoundStatement) + + +statementList : P (List Statement) +statementList = + Combine.lazy (\() -> Combine.many1 (Combine.lazy (\() -> statement))) + + +expressionStatement : P (Maybe Expr) +expressionStatement = + Combine.lazy + (\() -> + Combine.choice + [ semicolon |> Combine.onsuccess Nothing + , expression |> Combine.andThen (\e -> semicolon |> Combine.onsuccess (Just e)) + ] + ) + + +selectionStatement : P Statement +selectionStatement = + Combine.lazy + (\() -> + keyword "if" + |> Combine.ignore lparen + |> Combine.keep expression + |> Combine.ignore rparen + |> Combine.andThen + (\c -> + statement + |> Combine.andThen + (\t -> + Combine.maybe (keyword "else" |> Combine.keep statement) + |> Combine.map (SelectionStatement c t) + ) + ) + ) + + + +-- inside selectionStatement +-- selectionRestStatement = undefined + + +condition : P Condition +condition = + Combine.lazy + (\() -> + Combine.choice + [ expression + |> Combine.map Condition + , fullySpecifiedType + |> Combine.andThen + (\t -> + identifier + |> Combine.ignore (lexeme (Combine.string "=")) + |> Combine.andThen + (\i -> + initializer + |> Combine.map (InitializedCondition t i) + ) + ) + ] + ) + + +switchStatement : P Statement +switchStatement = + Combine.lazy + (\() -> + keyword "switch" + |> Combine.ignore lparen + |> Combine.keep expression + |> Combine.ignore rparen + |> Combine.ignore lbrace + |> Combine.andThen + (\e -> + switchStatementList + |> Combine.ignore rbrace + |> Combine.map (SwitchStatement e) + ) + ) + + +switchStatementList : P (List Statement) +switchStatementList = + Combine.lazy (\() -> Combine.many statement) + + +caseLabel : P CaseLabel +caseLabel = + Combine.lazy + (\() -> + Combine.choice + [ keyword "case" + |> Combine.keep expression + |> Combine.andThen + (\e -> + colon + |> Combine.onsuccess (Case e) + ) + , keyword "default" + |> Combine.keep (Combine.succeed Default) + ] + ) + + +iterationStatement : P Statement +iterationStatement = + Combine.lazy + (\() -> + Combine.choice + [ keyword "while" + |> Combine.ignore lparen + |> Combine.keep condition + |> Combine.ignore rparen + |> Combine.andThen + (\c -> + statementNoNewScope + |> Combine.map (While c) + ) + , keyword "do" + |> Combine.keep statement + |> Combine.ignore (keyword "while") + |> Combine.ignore lparen + |> Combine.andThen + (\s -> + expression + |> Combine.ignore rparen + |> Combine.ignore semicolon + |> Combine.map (DoWhile s) + ) + , keyword "for" + |> Combine.ignore lparen + |> Combine.keep forInitStatement + |> Combine.andThen + (\i -> + Combine.maybe condition + |> Combine.ignore semicolon + |> Combine.andThen + (\c -> + Combine.maybe expression + |> Combine.ignore rparen + |> Combine.andThen + (\e -> + statementNoNewScope + |> Combine.map (For i c e) + ) + ) + ) + ] + ) + + +forInitStatement : P (Result (Maybe Expr) Declaration) +forInitStatement = + Combine.or (expressionStatement |> Combine.map Err) + (declarationStatement |> Combine.map Ok) + + + +-- inside iterationStatement +-- conditionOp = undefined +-- inside iterationStatement +-- forRestStatement = undefined + + +jumpStatement : P Statement +jumpStatement = + Combine.choice + [ Combine.sequence [ keyword "continue", semicolon ] |> Combine.onsuccess Continue + , Combine.sequence [ keyword "break", semicolon ] |> Combine.onsuccess Break + , try (Combine.sequence [ keyword "return", semicolon ]) |> Combine.onsuccess (Return Nothing) + , keyword "return" + |> Combine.keep expression + |> Combine.andThen + (\e -> + semicolon + |> Combine.onsuccess (Return (Just e)) + ) + , Combine.sequence [ keyword "discard", semicolon ] |> Combine.onsuccess Discard + ] + + +translationUnit : P TranslationUnit +translationUnit = + Combine.lazy (\() -> Combine.map TranslationUnit (Combine.many1 externalDeclaration)) + + +externalDeclaration : P ExternalDeclaration +externalDeclaration = + Combine.lazy + (\() -> + Combine.choice + [ functionPrototype + |> Combine.andThen + (\p -> + Combine.choice + [ semicolon |> Combine.onsuccess (FunctionDeclaration p) + , compoundStatementNoNewScope |> Combine.map (FunctionDefinition p) + ] + ) + , Combine.map Declaration declaration + ] + ) diff --git a/src/Language/GLSL/Syntax.elm b/src/Language/GLSL/Syntax.elm new file mode 100644 index 0000000..0cf3205 --- /dev/null +++ b/src/Language/GLSL/Syntax.elm @@ -0,0 +1,466 @@ +module Language.GLSL.Syntax exposing + ( TranslationUnit(..) + , ExternalDeclaration(..), Declaration(..) + , InitDeclarator(..) + , InvariantOrType(..) + , FunctionPrototype(..) + , ParameterDeclaration(..) + , FullType(..) + , TypeQualifier(..) + , TypeSpecifier(..) + , InvariantQualifier(..) + , InterpolationQualifier(..) + , LayoutQualifier(..) + , LayoutQualifierId(..) + , Statement(..) + , Compound(..) + , Condition(..) + , CaseLabel(..) + , StorageQualifier(..) + , TypeSpecifierNoPrecision(..) + , TypeSpecifierNonArray(..) + , PrecisionQualifier(..) + , Field(..) + , StructDeclarator(..) + , Expr(..) + , IntConstantKind(..) + , Parameters(..) + , ParameterQualifier(..) + , ParameterTypeQualifier(..) + , FunctionIdentifier(..) + ) + +{-| This module is part of an Elm implementation of a GLSL parser, inspired by the +Haskell GLSL parser. + +Reference: + +This implementation attempts to adapt the concepts and structure from the +Haskell parser into the Elm ecosystem. + + +# Abstract syntax tree + +@docs TranslationUnit + +@docs ExternalDeclaration, Declaration +@docs InitDeclarator +@docs InvariantOrType +@docs FunctionPrototype +@docs ParameterDeclaration +@docs FullType +@docs TypeQualifier +@docs TypeSpecifier +@docs InvariantQualifier +@docs InterpolationQualifier +@docs LayoutQualifier +@docs LayoutQualifierId +@docs Statement +@docs Compound +@docs Condition +@docs CaseLabel +@docs StorageQualifier +@docs TypeSpecifierNoPrecision +@docs TypeSpecifierNonArray +@docs PrecisionQualifier +@docs Field +@docs StructDeclarator +@docs Expr +@docs IntConstantKind +@docs Parameters +@docs ParameterQualifier +@docs ParameterTypeQualifier +@docs FunctionIdentifier + +-} + +-- TODO: +-- - add support for 'array of strings' ? +-- - add support for macro preprocessing +-- - add support for optional macro #include +-- - applicative style (see http://github.com/markusle/husky)? +-- - type checking +-- - check for constant expression where expected +-- - error reporting +-- - pretty-printing +-- - basic queries (inputs and outputs of the shader) +-- - support GLSL 1.40? +-- - proper testing (HUnit and QuickCheck) +-- - use hpc with the tests +-- - scoping +-- - clean module import/export +-- - order of Syntax data types and Pretty instances should be the same +-- - build with no warning +-- - use hlint +-- - push to github +-- - push to hackage +-- - use parsec 3 +-- - handle all possible newlines (\n, \r, \r\n, \n\r) +-- - 80-columns clean +-- - lot of restriction of Samplers use (section 4.1.7), +-- well in fact, for plenty of things. +---------------------------------------------------------------------- +-- Abstract syntax tree +---------------------------------------------------------------------- + + +{-| Represents the top-level structure of a parsed GLSL shader. + +A `TranslationUnit` is the root of the Abstract Syntax Tree (AST) for a GLSL shader. + +-} +type TranslationUnit + = TranslationUnit (List ExternalDeclaration) + + + +-- at least one + + +{-| -} +type ExternalDeclaration + = -- function declarations should be at top level (page 28) + FunctionDeclaration FunctionPrototype + | FunctionDefinition FunctionPrototype Compound + | Declaration Declaration + + + +-- TODO clean + + +{-| -} +type Declaration + = -- e.g. layout (origin_upper_left) in vec4 gl_FragCoord; + -- struct name { ... }; + -- struct name { ... } name; + InitDeclaration InvariantOrType (List InitDeclarator) + | Precision PrecisionQualifier TypeSpecifierNoPrecision + | Block TypeQualifier String (List Field) (Maybe ( String, Maybe (Maybe Expr) )) -- constant expression + -- e.g. layout (origin_upper_left) in; TODO check if it is only used for default layout. + | TQ TypeQualifier + + + +-- TODO regroup String (Maybe (Maybe Expr)) as Declarator and use it for +-- StructDeclarator. + + +{-| -} +type InitDeclarator + = InitDecl String (Maybe (Maybe Expr)) (Maybe Expr) -- constant expression; assignment expression + + +{-| -} +type InvariantOrType + = InvariantDeclarator + | TypeDeclarator FullType + + +{-| -} +type FunctionPrototype + = FuncProt FullType String (List ParameterDeclaration) + + +{-| -} +type ParameterDeclaration + = ParameterDeclaration (Maybe ParameterTypeQualifier) (Maybe ParameterQualifier) TypeSpecifier (Maybe ( String, Maybe Expr )) + + + +-- constant expression + + +{-| -} +type FullType + = FullType (Maybe TypeQualifier) TypeSpecifier + + + +-- sto +-- lay [sto] +-- int [sto] +-- inv [sto] +-- inv int sto + + +{-| -} +type TypeQualifier + = TypeQualSto StorageQualifier + | TypeQualLay LayoutQualifier (Maybe StorageQualifier) + | TypeQualInt InterpolationQualifier (Maybe StorageQualifier) + | TypeQualInv InvariantQualifier (Maybe StorageQualifier) + | TypeQualInv3 InvariantQualifier InterpolationQualifier StorageQualifier + + +{-| -} +type TypeSpecifier + = TypeSpec (Maybe PrecisionQualifier) TypeSpecifierNoPrecision + + +{-| -} +type InvariantQualifier + = Invariant + + +{-| -} +type InterpolationQualifier + = Smooth + | Flat + | NoPerspective + + +{-| -} +type LayoutQualifier + = Layout (List LayoutQualifierId) + + +{-| -} +type LayoutQualifierId + = LayoutQualId String (Maybe Expr) -- TODO Expr should be IntConstant + + +{-| -} +type Statement + = -- declaration statement + DeclarationStatement Declaration + -- jump statement + | Continue + | Break + | Return (Maybe Expr) + | Discard -- fragment shader only + -- compound statement + | CompoundStatement Compound + -- expression statement + | ExpressionStatement (Maybe Expr) + -- selection statement + | SelectionStatement Expr Statement (Maybe Statement) + -- switch statement + | SwitchStatement Expr (List Statement) + | CaseLabel CaseLabel + -- iteration statement + | While Condition Statement -- no new scope + | DoWhile Statement Expr + | For (Result (Maybe Expr) Declaration) (Maybe Condition) (Maybe Expr) Statement + + + +-- 1st stmt: expression or declaration, 2nd: no new scope + + +{-| -} +type Compound + = Compound (List Statement) + + +{-| -} +type Condition + = Condition Expr + | InitializedCondition FullType String Expr -- assignment expression + + +{-| -} +type CaseLabel + = Case Expr + | Default + + +{-| -} +type StorageQualifier + = Const + | Attribute -- vertex only + | Varying + | CentroidVarying + | In + | Out + | CentroidIn + | CentroidOut + | Uniform + + +{-| -} +type TypeSpecifierNoPrecision + = TypeSpecNoPrecision TypeSpecifierNonArray (Maybe (Maybe Expr)) -- constant expression + + +{-| -} +type TypeSpecifierNonArray + = Void + | Float + | Int + | UInt + | Bool + | Vec2 + | Vec3 + | Vec4 + | BVec2 + | BVec3 + | BVec4 + | IVec2 + | IVec3 + | IVec4 + | UVec2 + | UVec3 + | UVec4 + | Mat2 + | Mat3 + | Mat4 + | Mat2x2 + | Mat2x3 + | Mat2x4 + | Mat3x2 + | Mat3x3 + | Mat3x4 + | Mat4x2 + | Mat4x3 + | Mat4x4 + | Sampler1D + | Sampler2D + | Sampler3D + | SamplerCube + | Sampler1DShadow + | Sampler2DShadow + | SamplerCubeShadow + | Sampler1DArray + | Sampler2DArray + | Sampler1DArrayShadow + | Sampler2DArrayShadow + | ISampler1D + | ISampler2D + | ISampler3D + | ISamplerCube + | ISampler1DArray + | ISampler2DArray + | USampler1D + | USampler2D + | USampler3D + | USamplerCube + | USampler1DArray + | USampler2DArray + | Sampler2DRect + | Sampler2DRectShadow + | ISampler2DRect + | USampler2DRect + | SamplerBuffer + | ISamplerBuffer + | USamplerBuffer + | Sampler2DMS + | ISampler2DMS + | USampler2DMS + | Sampler2DMSArray + | ISampler2DMSArray + | USampler2DMSArray + | StructSpecifier (Maybe String) (List Field) + | TypeName String -- TODO user-defined type, should verify if it is declared + + +{-| -} +type PrecisionQualifier + = HighP + | MediumP + | LowP + + + +-- TODO The type qualifier can be present only when there is one or more declarators. +-- There other restrictions, see 4.1.8. + + +{-| -} +type Field + = Field (Maybe TypeQualifier) TypeSpecifier (List StructDeclarator) + + +{-| -} +type StructDeclarator + = StructDeclarator String (Maybe (Maybe Expr)) -- constant expression + + +{-| -} +type Expr + = -- primaryExpression + Variable String + | IntConstant IntConstantKind Int + | FloatConstant Float + | BoolConstant Bool + -- postfixExpression + | Bracket Expr Expr + | FieldSelection Expr String + | MethodCall Expr FunctionIdentifier Parameters + | FunctionCall FunctionIdentifier Parameters + | PostInc Expr + | PostDec Expr + | PreInc Expr + | PreDec Expr + -- unary expression + | UnaryPlus Expr + | UnaryNegate Expr + | UnaryNot Expr + | UnaryOneComplement Expr + -- binary expression + | Mul Expr Expr + | Div Expr Expr + | Mod Expr Expr + | Add Expr Expr + | Sub Expr Expr + | LeftShift Expr Expr + | RightShift Expr Expr + | Lt Expr Expr + | Gt Expr Expr + | Lte Expr Expr + | Gte Expr Expr + | Equ Expr Expr + | Neq Expr Expr + | BitAnd Expr Expr + | BitXor Expr Expr + | BitOr Expr Expr + | And Expr Expr + | Or Expr Expr + | Selection Expr Expr Expr -- ternary _ ? _ : _ operator + -- assignment, the left Expr should be unary expression + | Equal Expr Expr + | MulAssign Expr Expr + | DivAssign Expr Expr + | ModAssign Expr Expr + | AddAssign Expr Expr + | SubAssign Expr Expr + | LeftAssign Expr Expr + | RightAssign Expr Expr + | AndAssign Expr Expr + | XorAssign Expr Expr + | OrAssign Expr Expr + -- sequence + | Sequence Expr Expr + + +{-| -} +type IntConstantKind + = Hexadecimal + | Octal + | Decimal + + +{-| -} +type Parameters + = ParamVoid + | Params (List Expr) + + +{-| -} +type ParameterQualifier + = InParameter + | OutParameter + | InOutParameter + + +{-| -} +type ParameterTypeQualifier + = ConstParameter + + +{-| -} +type FunctionIdentifier + = -- TODO could be refine (I think a precision qualifier is not permitted, + -- nor a complete struct definition) + FuncIdTypeSpec TypeSpecifier + | FuncId String diff --git a/tests/Language/GLSL/ParserTests.elm b/tests/Language/GLSL/ParserTests.elm new file mode 100644 index 0000000..f0e58e7 --- /dev/null +++ b/tests/Language/GLSL/ParserTests.elm @@ -0,0 +1,118 @@ +module Language.GLSL.ParserTests exposing (suite) + +import Expect +import Language.GLSL.Parser as P +import Language.GLSL.Syntax + exposing + ( Compound(..) + , Declaration(..) + , Expr(..) + , ExternalDeclaration(..) + , FullType(..) + , FunctionIdentifier(..) + , FunctionPrototype(..) + , InitDeclarator(..) + , InvariantOrType(..) + , Parameters(..) + , PrecisionQualifier(..) + , Statement(..) + , StorageQualifier(..) + , TranslationUnit(..) + , TypeQualifier(..) + , TypeSpecifier(..) + , TypeSpecifierNoPrecision(..) + , TypeSpecifierNonArray(..) + ) +import Test exposing (Test) + + +suite : Test +suite = + Test.describe "Language.GLSL.Parser" + [ Test.describe "Triangle" + [ Test.test "vertexShader" <| + \_ -> + P.parse """ + attribute vec3 position; + attribute vec3 color; + uniform mat4 perspective; + varying vec3 vcolor; + + void main () { + gl_Position = perspective * vec4(position, 1.0); + vcolor = color; + } + """ + |> Expect.equal + (Ok + (TranslationUnit + [ Declaration (InitDeclaration (TypeDeclarator (FullType (Just (TypeQualSto Attribute)) (TypeSpec Nothing (TypeSpecNoPrecision Vec3 Nothing)))) [ InitDecl "position" Nothing Nothing ]) + , Declaration (InitDeclaration (TypeDeclarator (FullType (Just (TypeQualSto Attribute)) (TypeSpec Nothing (TypeSpecNoPrecision Vec3 Nothing)))) [ InitDecl "color" Nothing Nothing ]) + , Declaration (InitDeclaration (TypeDeclarator (FullType (Just (TypeQualSto Uniform)) (TypeSpec Nothing (TypeSpecNoPrecision Mat4 Nothing)))) [ InitDecl "perspective" Nothing Nothing ]) + , Declaration (InitDeclaration (TypeDeclarator (FullType (Just (TypeQualSto Varying)) (TypeSpec Nothing (TypeSpecNoPrecision Vec3 Nothing)))) [ InitDecl "vcolor" Nothing Nothing ]) + , FunctionDefinition + (FuncProt + (FullType Nothing + (TypeSpec Nothing (TypeSpecNoPrecision Void Nothing)) + ) + "main" + [] + ) + (Compound + [ ExpressionStatement + (Just + (Equal (Variable "gl_Position") + (Mul (Variable "perspective") + (FunctionCall (FuncIdTypeSpec (TypeSpec Nothing (TypeSpecNoPrecision Vec4 Nothing))) + (Params [ Variable "position", FloatConstant 1.0 ]) + ) + ) + ) + ) + , ExpressionStatement (Just (Equal (Variable "vcolor") (Variable "color"))) + ] + ) + ] + ) + ) + , Test.test "fragmentShader" <| + \_ -> + P.parse """ + precision mediump float; + varying vec3 vcolor; + + void main () { + gl_FragColor = vec4(vcolor, 1.0); + } + """ + |> Expect.equal + (Ok + (TranslationUnit + [ Declaration (Precision MediumP (TypeSpecNoPrecision Float Nothing)) + , Declaration + (InitDeclaration + (TypeDeclarator + (FullType (Just (TypeQualSto Varying)) + (TypeSpec Nothing (TypeSpecNoPrecision Vec3 Nothing)) + ) + ) + [ InitDecl "vcolor" Nothing Nothing ] + ) + , FunctionDefinition + (FuncProt (FullType Nothing (TypeSpec Nothing (TypeSpecNoPrecision Void Nothing))) "main" []) + (Compound + [ ExpressionStatement + (Just + (Equal (Variable "gl_FragColor") + (FunctionCall (FuncIdTypeSpec (TypeSpec Nothing (TypeSpecNoPrecision Vec4 Nothing))) + (Params [ Variable "vcolor", FloatConstant 1.0 ]) + ) + ) + ) + ] + ) + ] + ) + ) + ] + ]