diff --git a/.github/workflows/haskell-ci.diff b/.github/workflows/haskell-ci.diff index dc7006b92..985e22b7e 100644 --- a/.github/workflows/haskell-ci.diff +++ b/.github/workflows/haskell-ci.diff @@ -1,9 +1,9 @@ --- haskell-ci.yml 2022-12-16 13:49:54.000000000 +0100 +++ patched-haskell-ci.yml 2022-12-16 13:49:36.000000000 +0100 -@@ -176,10 +176,6 @@ - active-repositories: hackage.haskell.org, head.hackage.ghc.haskell.org:override +@@ -170,10 +170,6 @@ + repository hackage.haskell.org + url: http://hackage.haskell.org/ EOF - fi - cat >> $CABAL_CONFIG < "$HOME/.ghcup/bin/ghcup" - chmod a+x "$HOME/.ghcup/bin/ghcup" - "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false) - "$HOME/.ghcup/bin/ghcup" install cabal 3.10.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false) - else - apt-add-repository -y 'ppa:hvr/ghc' - apt-get update - apt-get install -y "$HCNAME" - mkdir -p "$HOME/.ghcup/bin" - curl -sL https://downloads.haskell.org/ghcup/0.1.19.2/x86_64-linux-ghcup-0.1.19.2 > "$HOME/.ghcup/bin/ghcup" - chmod a+x "$HOME/.ghcup/bin/ghcup" - "$HOME/.ghcup/bin/ghcup" install cabal 3.10.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false) - fi + apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5 libnuma-dev + mkdir -p "$HOME/.ghcup/bin" + curl -sL https://downloads.haskell.org/ghcup/0.1.30.0/x86_64-linux-ghcup-0.1.30.0 > "$HOME/.ghcup/bin/ghcup" + chmod a+x "$HOME/.ghcup/bin/ghcup" + "$HOME/.ghcup/bin/ghcup" config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.8.yaml; + "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false) + "$HOME/.ghcup/bin/ghcup" install cabal 3.12.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false) env: HCKIND: ${{ matrix.compilerKind }} HCNAME: ${{ matrix.compiler }} @@ -121,25 +120,18 @@ jobs: echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV" echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV" HCDIR=/opt/$HCKIND/$HCVER - if [ "${{ matrix.setup-method }}" = ghcup ]; then - HC=$HOME/.ghcup/bin/$HCKIND-$HCVER - echo "HC=$HC" >> "$GITHUB_ENV" - echo "HCPKG=$HOME/.ghcup/bin/$HCKIND-pkg-$HCVER" >> "$GITHUB_ENV" - echo "HADDOCK=$HOME/.ghcup/bin/haddock-$HCVER" >> "$GITHUB_ENV" - echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.1.0 -vnormal+nowrap" >> "$GITHUB_ENV" - else - HC=$HCDIR/bin/$HCKIND - echo "HC=$HC" >> "$GITHUB_ENV" - echo "HCPKG=$HCDIR/bin/$HCKIND-pkg" >> "$GITHUB_ENV" - echo "HADDOCK=$HCDIR/bin/haddock" >> "$GITHUB_ENV" - echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.1.0 -vnormal+nowrap" >> "$GITHUB_ENV" - fi - + HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER") + HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#') + HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#') + echo "HC=$HC" >> "$GITHUB_ENV" + echo "HCPKG=$HCPKG" >> "$GITHUB_ENV" + echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV" + echo "CABAL=$HOME/.ghcup/bin/cabal-3.12.1.0 -vnormal+nowrap" >> "$GITHUB_ENV" HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))') echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV" echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV" echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV" - echo "HEADHACKAGE=false" >> "$GITHUB_ENV" + if [ $((HCNUMVER >= 91200)) -ne 0 ] ; then echo "HEADHACKAGE=true" >> "$GITHUB_ENV" ; else echo "HEADHACKAGE=false" >> "$GITHUB_ENV" ; fi echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV" echo "GHCJSARITH=0" >> "$GITHUB_ENV" env: @@ -168,6 +160,18 @@ jobs: repository hackage.haskell.org url: http://hackage.haskell.org/ EOF + if $HEADHACKAGE; then + cat >> $CABAL_CONFIG <> $CABAL_CONFIG <= 80200)) -ne 0 ] ; then echo " ghc-options: -Werror=missing-methods" >> cabal.project ; fi cat >> cabal.project <> cabal.project.local + if $HEADHACKAGE; then + echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1,/g')" >> cabal.project + fi + $HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: any.$_ installed\n" unless /^(BNFC|bnfc-system-tests)$/; }' >> cabal.project.local cat cabal.project cat cabal.project.local - name: dump install plan @@ -233,7 +240,7 @@ jobs: $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all cabal-plan - name: restore cache - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} path: ~/.cabal/store @@ -248,6 +255,14 @@ jobs: - name: build run: | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always + - name: install doctest + if: env.HEADHACKAGE != 'true' + run: | + $CABAL v2-install --ignore-project $ARG_COMPILER doctest --ghc-options=-rtsopts --overwrite-policy=always + - name: doctests + if: env.HEADHACKAGE != 'true' + run: | + $CABAL v2-repl BNFC --with-ghc-pkg=$HCPKG -w doctest --repl-options=-w - name: tests run: | $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct @@ -265,7 +280,7 @@ jobs: rm -f cabal.project.local $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all - name: save cache - uses: actions/cache/save@v3 + uses: actions/cache/save@v4 if: always() with: key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml new file mode 100644 index 000000000..d02f27954 --- /dev/null +++ b/.github/workflows/nix.yml @@ -0,0 +1,43 @@ +name: "Test Nix Integration" +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + nix: + strategy: + fail-fast: true + matrix: + os: + - ubuntu-latest + - macos-latest + name: Nix on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: cachix/install-nix-action@V27 + with: + extra_nix_config: | + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= cache.ngi0.nixos.org-1:KqH5CBLNSyX184S9BKZJo1LxrxJ9ltnY2uAs5c/f1MA= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= + substituters = https://cache.nixos.org https://cache.ngi0.nixos.org/ https://cache.iog.io/ + nix_path: nixpkgs=channel:nixos-unstable + + - name: "Test Nix flakes build" + run: nix build + + # Development shells will require building of hls and take a lot of time + # Let's not do that in the actions for now + # - name: "Test Nix flakes development shell" + # run: nix develop --check + + - name: "Test Nix flake-compact build" + run: nix-build + + # - name: "Test Nix flake-compact development shell" + # run: nix-shell --run echo + + - continue-on-error: false + run: nix flake check --allow-import-from-derivation --impure \ No newline at end of file diff --git a/.github/workflows/stack.yml b/.github/workflows/stack.yml index a9568aea7..095f98bf5 100644 --- a/.github/workflows/stack.yml +++ b/.github/workflows/stack.yml @@ -7,7 +7,7 @@ on: branches: [ master, 'ci-*' ] tags: [ 'v*' ] pull_request: - types: [ opened, synchronize] + types: [ opened, synchronize ] workflow_dispatch: # For making a release, we need write permissions. @@ -23,13 +23,14 @@ jobs: fail-fast: false matrix: # Note: check release logic below when changing the matrix! - ghc: [9.6.2, 9.4.5, 9.2.8, 9.0.2, 8.10.7, 8.8.4, 8.6.5, 8.4.4, 8.2.2] + # Stack 3.1.1 only supports GHC 8.4 and up. + ghc: ['9.10', '9.8', '9.6', '9.4', '9.2', '9.0', '8.10', '8.8', '8.6', '8.4'] os: [ubuntu-latest] include: - os: macOS-latest - ghc: 9.6.2 + ghc: '9.8' - os: windows-latest - ghc: 9.6.2 + ghc: '9.8' # Needed for Windows to make piping (... >> ...) and evaluation ( $(...) ) work. @@ -38,15 +39,15 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Haskell - uses: haskell/actions/setup@v2 + uses: haskell-actions/setup@v2 id: haskell-setup # <-- self-chosen identifier with: - ghc-version: ${{ matrix.ghc }} - enable-stack: true - # stack-version: latest + ghc-version: ${{ matrix.ghc }} + enable-stack: true + cabal-update: false - name: Environment settings based on the Haskell setup shell: bash @@ -63,7 +64,7 @@ jobs: GHC_VER=$(ghc --numeric-version) CABAL_VER=$(cabal --numeric-version) STACK_VER=$(stack --numeric-version) - STACK_FLAGS="--stack-yaml stack-${GHC_VER}.yaml --system-ghc --no-terminal --color always" + STACK_FLAGS="--stack-yaml stack-${{ matrix.ghc }}.yaml --system-ghc --no-terminal --color always" TARGET=$(if [ "${{ runner.os }}" == "Windows" ]; then echo ":bnfc"; fi) echo "GHC_VER = ${GHC_VER}" echo "CABAL_VER = ${CABAL_VER}" @@ -79,7 +80,7 @@ jobs: # From now on, use env.{GHC|CABAL}_VER rather than matrix.{ghc|cabal}-ver! - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 env: key: ${{ runner.os }}-stack-${{ env.STACK_VER }}-ghc-${{ env.GHC_VER }} ## Just stack.yaml is actually not correct, better would be stack.yaml.lock, @@ -88,7 +89,7 @@ jobs: # key: ${{ runner.os }}-${{ env.STACK_VER }}-${{ hashFiles('source/BNFC.cabal', format('stack-{0}.yaml', env.GHC_VER)) }} with: path: ${{ steps.haskell-setup.outputs.stack-root }} - key: ${{ env.key }}-resolver-${{ hashFiles(format('stack-{0}.yaml', env.GHC_VER)) }} + key: ${{ env.key }}-resolver-${{ hashFiles(format('stack-{0}.yaml', matrix.ghc)) }} restore-keys: ${{ env.key }}- - name: Build dependencies. @@ -120,7 +121,7 @@ jobs: # Conditional to ensure this deployment is only run once per action. if: >- startsWith(github.ref, 'refs/tags/v') - && matrix.ghc == '9.6.2' + && matrix.ghc == '9.8' run: | DIST_TGZ=$(cabal sdist source | tail -1) echo "DIST_TGZ=${DIST_TGZ}" >> "${GITHUB_ENV}" @@ -128,7 +129,7 @@ jobs: - name: Source tarball release. if: >- startsWith(github.ref, 'refs/tags/v') - && matrix.ghc == '9.6.2' + && matrix.ghc == '9.8' uses: softprops/action-gh-release@v1 with: draft: true @@ -140,7 +141,7 @@ jobs: if: >- startsWith(github.ref, 'refs/tags/v') && runner.os == 'Linux' - && matrix.ghc == '9.6.2' + && matrix.ghc == '9.8' run: | BNFC_BIN=bnfc-${BNFC_VERSION}-linux.binary cp -p "${BNFC_EXE}" "${BNFC_BIN}" @@ -151,7 +152,7 @@ jobs: if: >- startsWith(github.ref, 'refs/tags/v') && runner.os == 'Linux' - && matrix.ghc == '9.6.2' + && matrix.ghc == '9.8' uses: softprops/action-gh-release@v1 with: draft: true diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..f3b4ba6e1 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,31 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# This file originally taken from: https://github.com/readthedocs/readthedocs.org/issues/10290#issuecomment-1535838000 + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # You can also specify other tool versions: + # nodejs: "19" + # rust: "1.64" + # golang: "1.19" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# If using Sphinx, optionally build your docs in additional formats such as PDF +formats: + - pdf + +# # Optionally declare the Python requirements required to build your docs +# python: +# install: +# - requirements: docs/requirements.txt diff --git a/README.md b/README.md index 0eeb21024..ab469e1cb 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,16 @@ enter at the command line: bnfc --help ``` +BNFC versions in major Stackage LTS snapshots: + +| GHC | LTS | BNFC | +|--------|-------|---------| +| 8.8.4 | 16.31 | 2.8.4 | +| 8.10.7 | 18.28 | 2.9.4 | +| 9.0.2 | 19.33 | 2.9.4 | +| 9.2.8 | 20.26 | 2.9.4.1 | +| 9.4.8 | 21.25 | 2.9.5 | + ### Installation via cabal You need a running installation of a recent version of @@ -71,9 +81,9 @@ and then either ``` or ``` - stack install --stack-yaml stack-8.10.7.yaml + stack install --stack-yaml stack-9.4.yaml ``` -(replace `8.10.7` with your GHC version, and if you want to build with +(replace `9.4` with your GHC major version, and if you want to build with your installed GHC then add flag `--system-ghc`). Mini tutorial diff --git a/cabal.haskell-ci b/cabal.haskell-ci index 7b88abe74..bad5b022d 100644 --- a/cabal.haskell-ci +++ b/cabal.haskell-ci @@ -1,7 +1,7 @@ -- -- The name of GitHub Action -- github-action-name: -branches: master ci* +branches: master -- 2021-01-22 if cabal-version is greater than shipped Cabal, allow newer Cabal version -- https://github.com/haskell-CI/haskell-ci/issues/468#issuecomment-761865807 diff --git a/default.nix b/default.nix new file mode 100644 index 000000000..71330e434 --- /dev/null +++ b/default.nix @@ -0,0 +1,10 @@ +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).defaultNix \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 9a549e536..d89c1032c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -41,16 +41,16 @@ # General information about the project. project = u'BNFC' -copyright = u'2022, BNFC Developers' +copyright = u'2023, BNFC Developers' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '2.9.5' +version = '2.9.6' # The full version, including alpha/beta/rc tags. -release = '2.9.5' +release = '2.9.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 041c508aa..305639240 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -57,6 +57,31 @@ since 2.8.2 CUP version v11b. entry point for the grammar. If you need multiple entrypoints, use ANTLRv4. +Prerequisites +^^^^^^^^^^^^^ + +For the Java/CUP backend you need: + +- Parser generator: `CUP `_ libraries version 0.11b. +- Lexer generator `JFLex `_ or the `JLex `_ libraries. + +To set up CUP and JLex, follow these instructions: + +1. Download the JAVA archives for + `CUP v11b `_, + `CUP v11b runtime `_, + and + `JLex `_. + +2. Make sure they are placed in your ``CLASSPATH``. + + For example, in Linux or macOS, store these jars in ``${HOME}/java-lib/`` and add the following line to your shell initialization file:: + + export CLASSPATH=${CLASSPATH}\ + :${HOME}/java-lib/java-cup-11b.jar\ + :${HOME}/java-lib/java-cup-11b-runtime.jar\ + :${HOME}/java-lib/JLex-1.2.6.jar + ANTLRv4 ....... diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..a40c83a2b --- /dev/null +++ b/flake.lock @@ -0,0 +1,722 @@ +{ + "nodes": { + "HTTP": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "cabal-32": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-X0TFfdD4KZpwl0Zr6x+PLxUt/VyKQfX7ylXHdmZIL+w=", + "owner": "haskell", + "repo": "cabal", + "rev": "48bf10787e27364730dd37a42b603cee8d6af7ee", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34": { + "flake": false, + "locked": { + "lastModified": 1645834128, + "narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=", + "owner": "haskell", + "repo": "cabal", + "rev": "5ff598c67f53f7c4f48e31d722ba37172230c462", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cabal-36": { + "flake": false, + "locked": { + "lastModified": 1669081697, + "narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=", + "owner": "haskell", + "repo": "cabal", + "rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.6", + "repo": "cabal", + "type": "github" + } + }, + "cardano-shell": { + "flake": false, + "locked": { + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-shell", + "type": "github" + } + }, + "flake-compat": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1672831974, + "narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=", + "owner": "input-output-hk", + "repo": "flake-compat", + "rev": "45f2638735f8cdc40fe302742b79f248d23eb368", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "hkm/gitlab-fix", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "ghc-8.6.5-iohk": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "hackage": { + "flake": false, + "locked": { + "lastModified": 1721263615, + "narHash": "sha256-J/VaA4xWMpp43HptVP2tpfLwIYCg+OrBova4Uh5R8C8=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "beaee455c56dee413b33f89f6ebd0520ff435295", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "haskellNix": { + "inputs": { + "HTTP": "HTTP", + "cabal-32": "cabal-32", + "cabal-34": "cabal-34", + "cabal-36": "cabal-36", + "cardano-shell": "cardano-shell", + "flake-compat": "flake-compat_2", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", + "hackage": "hackage", + "hls-1.10": "hls-1.10", + "hls-2.0": "hls-2.0", + "hls-2.2": "hls-2.2", + "hls-2.3": "hls-2.3", + "hls-2.4": "hls-2.4", + "hls-2.5": "hls-2.5", + "hls-2.6": "hls-2.6", + "hls-2.7": "hls-2.7", + "hls-2.8": "hls-2.8", + "hls-2.9": "hls-2.9", + "hpc-coveralls": "hpc-coveralls", + "hydra": "hydra", + "iserv-proxy": "iserv-proxy", + "nixpkgs": [ + "haskellNix", + "nixpkgs-unstable" + ], + "nixpkgs-2003": "nixpkgs-2003", + "nixpkgs-2105": "nixpkgs-2105", + "nixpkgs-2111": "nixpkgs-2111", + "nixpkgs-2205": "nixpkgs-2205", + "nixpkgs-2211": "nixpkgs-2211", + "nixpkgs-2305": "nixpkgs-2305", + "nixpkgs-2311": "nixpkgs-2311", + "nixpkgs-2405": "nixpkgs-2405", + "nixpkgs-unstable": "nixpkgs-unstable", + "old-ghc-nix": "old-ghc-nix", + "stackage": "stackage" + }, + "locked": { + "lastModified": 1721263838, + "narHash": "sha256-ZFcyUXcxU9k5tkv/t5deuQ8PRY0Q0/uk8MLHUb2eXEs=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "7bcd019c70e1929d733ed0bf5349c747ce0ee66a", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "hls-1.10": { + "flake": false, + "locked": { + "lastModified": 1680000865, + "narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "1.10.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.0": { + "flake": false, + "locked": { + "lastModified": 1687698105, + "narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "783905f211ac63edf982dd1889c671653327e441", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.0.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.2": { + "flake": false, + "locked": { + "lastModified": 1693064058, + "narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.2.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.3": { + "flake": false, + "locked": { + "lastModified": 1695910642, + "narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.3.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.4": { + "flake": false, + "locked": { + "lastModified": 1699862708, + "narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.4.0.1", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.5": { + "flake": false, + "locked": { + "lastModified": 1701080174, + "narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "27f8c3d3892e38edaef5bea3870161815c4d014c", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.5.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.6": { + "flake": false, + "locked": { + "lastModified": 1705325287, + "narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.6.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.7": { + "flake": false, + "locked": { + "lastModified": 1708965829, + "narHash": "sha256-LfJ+TBcBFq/XKoiNI7pc4VoHg4WmuzsFxYJ3Fu+Jf+M=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "50322b0a4aefb27adc5ec42f5055aaa8f8e38001", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.7.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.8": { + "flake": false, + "locked": { + "lastModified": 1715153580, + "narHash": "sha256-Vi/iUt2pWyUJlo9VrYgTcbRviWE0cFO6rmGi9rmALw0=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "dd1be1beb16700de59e0d6801957290bcf956a0a", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.8.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hls-2.9": { + "flake": false, + "locked": { + "lastModified": 1718469202, + "narHash": "sha256-THXSz+iwB1yQQsr/PY151+2GvtoJnTIB2pIQ4OzfjD4=", + "owner": "haskell", + "repo": "haskell-language-server", + "rev": "40891bccb235ebacce020b598b083eab9dda80f1", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "2.9.0.0", + "repo": "haskell-language-server", + "type": "github" + } + }, + "hpc-coveralls": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "hydra": { + "inputs": { + "nix": "nix", + "nixpkgs": [ + "haskellNix", + "hydra", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671755331, + "narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=", + "owner": "NixOS", + "repo": "hydra", + "rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8", + "type": "github" + }, + "original": { + "id": "hydra", + "type": "indirect" + } + }, + "iserv-proxy": { + "flake": false, + "locked": { + "lastModified": 1717479972, + "narHash": "sha256-7vE3RQycHI1YT9LHJ1/fUaeln2vIpYm6Mmn8FTpYeVo=", + "owner": "stable-haskell", + "repo": "iserv-proxy", + "rev": "2ed34002247213fc435d0062350b91bab920626e", + "type": "github" + }, + "original": { + "owner": "stable-haskell", + "ref": "iserv-syms", + "repo": "iserv-proxy", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1661606874, + "narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.11.0", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1657693803, + "narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "365e1b3a859281cf11b94f87231adeabbdd878a2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.05-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2003": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105": { + "locked": { + "lastModified": 1659914493, + "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2111": { + "locked": { + "lastModified": 1659446231, + "narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "eabc38219184cc3e04a974fe31857d8e0eac098d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2205": { + "locked": { + "lastModified": 1685573264, + "narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "380be19fbd2d9079f677978361792cb25e8a3635", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2211": { + "locked": { + "lastModified": 1688392541, + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-22.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2305": { + "locked": { + "lastModified": 1705033721, + "narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-23.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2311": { + "locked": { + "lastModified": 1719957072, + "narHash": "sha256-gvFhEf5nszouwLAkT9nWsDzocUTqLWHuL++dvNjMp9I=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7144d6241f02d171d25fba3edeaf15e0f2592105", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-23.11-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2405": { + "locked": { + "lastModified": 1720122915, + "narHash": "sha256-Nby8WWxj0elBu1xuRaUcRjPi/rU3xVbkAt2kj4QwX2U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "835cf2d3f37989c5db6585a28de967a667a75fb1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-24.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1720181791, + "narHash": "sha256-i4vJL12/AdyuQuviMMd1Hk2tsGt02hDNhA0Zj1m16N8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4284c2b73c8bce4b46a6adf23e16d9e2ec8da4bb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "old-ghc-nix": { + "flake": false, + "locked": { + "lastModified": 1631092763, + "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master", + "repo": "old-ghc-nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "haskellNix": "haskellNix", + "nixpkgs": [ + "haskellNix", + "nixpkgs-unstable" + ] + } + }, + "stackage": { + "flake": false, + "locked": { + "lastModified": 1721262189, + "narHash": "sha256-FhQK+UGKGBJCyLo8NBhU65QKm5loHS/APUKno/9jO/U=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "a55d366b4ab71687ce60d428a775a4ecc824a658", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..1533df7a1 --- /dev/null +++ b/flake.nix @@ -0,0 +1,122 @@ +{ + inputs.haskellNix.url = "github:input-output-hk/haskell.nix"; + inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + inputs.flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; + outputs = { self, nixpkgs, flake-utils, haskellNix, ... }: + let + supportedSystems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-linux" + "aarch64-darwin" + ]; + in + flake-utils.lib.eachSystem supportedSystems (system: + let + lib = nixpkgs.lib; + supportedGHCStackFile = { + # Haskell.nix does not support GHC versions older than 8.10 + # Note: only GHC 9.8.2 is tested to work for now + ghc8107 = "stack-8.10.yaml"; + ghc902 = "stack-9.0.yaml"; + ghc928 = "stack-9.2.yaml"; + ghc948 = "stack-9.4.yaml"; + ghc965 = "stack-9.6.yaml"; + ghc982 = "stack-9.8.yaml"; + }; + defaultVersion = "ghc982"; + + overlays = [ haskellNix.overlay + (final: _prev: lib.attrsets.mapAttrs' ( + ghcVersion: value: { + name = "bnfc-project-${ghcVersion}"; + value = final.haskell-nix.stackProject' { + src = ./.; + name = "bnfc-project-${ghcVersion}"; + compiler-nix-name = ghcVersion; # Version of GHC to use + # Use the corresponding stack configuration as well + stackYaml = value; + # Tools to include in the development shell + shell.tools = { + cabal = "latest"; + hlint = { + ghc8107 = "3.4"; + ghc902 = "3.5"; + ghc928 = "3.6.1"; + ghc948 = "3.8"; + ghc965 = "3.8"; + ghc982 = "3.8"; + }.${ghcVersion}; + haskell-language-server = if ghcVersion == "ghc8107" then "2.2.0.0" + else if ghcVersion == "ghc902" then "2.4.0.0" + else "latest"; + }; + modules = [{ + # Disable check for doctests + packages.BNFC.components.tests.doctests.doCheck = false; + }]; + # For `nix flake show --impure` and `nix flake check --impure` to work + } // ( if (builtins ? currentSystem) then {evalSystem = builtins.currentSystem;} else {}); + }) supportedGHCStackFile + ) + ]; + pkgs = import nixpkgs { inherit system overlays; inherit (haskellNix) config; }; + allVersions = builtins.mapAttrs ( + name: _value: pkgs."bnfc-project-${name}".flake {} + ) supportedGHCStackFile; + + allFlake = allVersions.${defaultVersion}; + # `nix flake check` currently does not support custom check logics, and will check hydrajobs + # defined for all platforms, which can cause check failures (see issue NixOS/nix#6453) + # For `nix flake check` to work, filter out all hydrajobs that are not for the current platform + # Note that on non x86_64-linux platforms --impure is required to pick up the correct platform names + flake = if system == (builtins.currentSystem or "x86_64-linux") + then allFlake + else builtins.removeAttrs allFlake ["hydraJobs"]; + in flake // { + legacyPackages = pkgs; + apps = { + default = flake.apps."BNFC:exe:bnfc"; + } // (lib.attrsets.mapAttrs' ( + name: _value: { + name = "bnfc-${name}"; + value = allVersions.${name}.apps."BNFC:exe:bnfc"; + } + ) supportedGHCStackFile); + packages = rec { + bnfc = flake.packages."BNFC:exe:bnfc"; + default = bnfc; + libBNFC = flake.packages."BNFC:lib:BNFC"; + } // (lib.attrsets.mapAttrs' ( + name: _value: { + name = "bnfc-${name}"; + value = allVersions.${name}.packages."BNFC:exe:bnfc"; + } + ) supportedGHCStackFile) + // (lib.attrsets.mapAttrs' ( + name: _value: { + name = "libBNFC-${name}"; + value = allVersions.${name}.packages."BNFC:lib:BNFC"; + } + ) supportedGHCStackFile); + devShells = { + default = flake.devShells.default; + } // (lib.attrsets.mapAttrs' ( + name: _value: { + name = "bnfc-${name}"; + value = allVersions.${name}.devShells.default; + } + ) supportedGHCStackFile); + }); + + # --- Flake Local Nix Configuration ---------------------------- + nixConfig = { + # This sets the flake to use the IOG nix cache. + # Nix should ask for permission before using it, + # but remove it here if you do not want it to. + extra-substituters = ["https://cache.iog.io"]; + extra-trusted-public-keys = ["hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="]; + allow-import-from-derivation = "true"; + }; +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..64fbdb42d --- /dev/null +++ b/shell.nix @@ -0,0 +1,10 @@ +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).shellNix \ No newline at end of file diff --git a/source/BNFC.cabal b/source/BNFC.cabal index cca33f2d5..a354ee5a6 100644 --- a/source/BNFC.cabal +++ b/source/BNFC.cabal @@ -1,5 +1,5 @@ Name: BNFC -Version: 2.9.5 +Version: 2.9.6 cabal-version: 2.0 -- >=2.0 for build-tool-depends: hspec-discover -- Andreas, 2022-12-16, issue #429: @@ -32,8 +32,11 @@ Description: -- Support range when build with cabal tested-with: - GHC == 9.6.2 - GHC == 9.4.5 + GHC == 9.12.0 + GHC == 9.10.1 + GHC == 9.8.2 + GHC == 9.6.6 + GHC == 9.4.8 GHC == 9.2.8 GHC == 9.0.2 GHC == 8.10.7 @@ -42,7 +45,6 @@ tested-with: GHC == 8.4.4 GHC == 8.2.2 GHC == 8.0.2 - GHC == 7.10.3 extra-doc-files: README.md @@ -54,15 +56,15 @@ extra-source-files: src/BNFC.cf src/Makefile -- Support range when build with stack - stack-9.6.2.yaml - stack-9.4.5.yaml - stack-9.2.8.yaml - stack-9.0.2.yaml - stack-8.10.7.yaml - stack-8.8.4.yaml - stack-8.6.5.yaml - stack-8.4.4.yaml - stack-8.2.2.yaml + stack-9.8.yaml + stack-9.6.yaml + stack-9.4.yaml + stack-9.2.yaml + stack-9.0.yaml + stack-8.10.yaml + stack-8.8.yaml + stack-8.6.yaml + stack-8.4.yaml source-repository head type: git @@ -79,6 +81,9 @@ executable bnfc other-modules: -- Generated by cabal Paths_BNFC + autogen-modules: + -- Generated by cabal + Paths_BNFC default-extensions: -- Keep in alphabetical order. LambdaCase @@ -152,6 +157,14 @@ library -- BNFC.Lex -- -- Generated by happy -- BNFC.Par + -- 2023-11-03 We cannot add BNFC.{Lex,Par} as then the Lex.x and Par.y files + -- are not bundled by cabal dist. + -- Just make sure that there is no src/BNFC/{Lex,Par}.hs before running cabal sdist, + -- otherwise we will end up with both Lex.hs and Lex.x (resp. Par.{hs,y}) + -- which will cause alex/happy to not be run, leading to build failures. + autogen-modules: + -- Generated by cabal + Paths_BNFC other-modules: -- Generated by cabal Paths_BNFC @@ -262,6 +275,11 @@ library -- Agda backend BNFC.Backend.Agda + -- Tree-sitter backend + BNFC.Backend.TreeSitter + BNFC.Backend.TreeSitter.CFtoTreeSitter + BNFC.Backend.TreeSitter.RegToJSReg + ----- Testing -------------------------------------------------------------- test-suite unit-tests @@ -326,6 +344,7 @@ test-suite unit-tests BNFC.Backend.JavaSpec BNFC.Backend.LatexSpec BNFC.Backend.OCamlSpec + BNFC.Backend.TreeSitterSpec -- Generated by cabal Paths_BNFC autogen-modules: diff --git a/source/BNFC.spec b/source/BNFC.spec index e17408582..7a8f58337 100644 --- a/source/BNFC.spec +++ b/source/BNFC.spec @@ -1,7 +1,7 @@ # https://fedoraproject.org/wiki/Packaging:Haskell Name: BNFC -Version: 2.9.5 +Version: 2.9.6 Release: 1%{?dist} Summary: A compiler front-end generator diff --git a/source/CHANGELOG.md b/source/CHANGELOG.md index ecc719dfc..7fa13f6d4 100644 --- a/source/CHANGELOG.md +++ b/source/CHANGELOG.md @@ -1,3 +1,8 @@ +# Unreleased + +* C: preserve case in constructors (union): e.g. label `EInt` now is union member `eInt_` rather than `eint_` + [[#479](https://github.com/BNFC/bnfc/issues/479)] + # 2.9.5 Andreas Abel , July 2023 diff --git a/source/Makefile b/source/Makefile index 6849b7b15..229f2a2c9 100644 --- a/source/Makefile +++ b/source/Makefile @@ -8,7 +8,7 @@ CABAL_BUILDDIR_SUFFIX= CABAL_BUILD_OPTS = --enable-tests # --builddir=dist-ghc-$(GHC_VERSION)$(CABAL_BUILDDIR_SUFFIX) CABAL_CONFIGURE_OPTS = --enable-tests -CABAL_INSTALL_OPTS = $(CABAL_CONFIGURE_OPTS) $(CABAL_BUILD_OPTS) --overwrite-policy=always +CABAL_INSTALL_OPTS = --overwrite-policy=always CABAL_TEST_OPTS = $(CABAL_BUILD_OPTS) CABAL = cabal $(CABAL_OPTS) @@ -38,7 +38,7 @@ cabal-test: doctest: build doctest-install doctest-quick doctest-install: - cabal install doctest --program-suffix=-${GHC_VERSION} + cabal install doctest --ignore-project --program-suffix=-${GHC_VERSION} doctest-quick: cabal repl -w doctest-${GHC_VERSION} --repl-options=-Wno-type-defaults @@ -62,6 +62,15 @@ TAGS : # Binary package (tgz, for linux) bdist: dist/${BDIST_TAG}.tar.gz +# Source package +# Andreas, 2023-11-03, PR #466: need to remove BNFC/{Lex,Par}.hs, +# otherwise they will be shipped in the sdist package +# and cause compilation to fail. +sdist: + make -C src clean + cabal sdist + +# OLD goal dist/%.tar.gz: cabal v1-clean cabal v1-install ${CABAL_OPTS} --only-dependencies diff --git a/source/main/Main.hs b/source/main/Main.hs index 5486d60b3..754bf2684 100644 --- a/source/main/Main.hs +++ b/source/main/Main.hs @@ -25,6 +25,7 @@ import BNFC.Backend.Java import BNFC.Backend.Latex import BNFC.Backend.OCaml import BNFC.Backend.Pygments +import BNFC.Backend.TreeSitter import BNFC.CF (CF) import BNFC.GetCF import BNFC.Options hiding (make, Backend) @@ -81,3 +82,4 @@ maketarget = \case TargetOCaml -> makeOCaml TargetPygments -> makePygments TargetCheck -> error "impossible" + TargetTreeSitter -> makeTreeSitter diff --git a/source/src/BNFC/Backend/C/CFtoCAbs.hs b/source/src/BNFC/Backend/C/CFtoCAbs.hs index b906ca859..3d69d3bc6 100644 --- a/source/src/BNFC/Backend/C/CFtoCAbs.hs +++ b/source/src/BNFC/Backend/C/CFtoCAbs.hs @@ -35,7 +35,7 @@ import BNFC.PrettyPrint import BNFC.Options ( RecordPositions(..) ) import BNFC.Utils ( (+++), unless ) import BNFC.Backend.Common.NamedVariables -import BNFC.Backend.C.Common ( posixC ) +import BNFC.Backend.C.Common ( posixC, memName ) -- | The result is two files (.H file, .C file) @@ -304,12 +304,12 @@ mkCFile datas _cf = concat -- switch(p->kind) -- { -- case is_EInt: --- return make_EInt (p->u.eint_.integer_); +-- return make_EInt (p->u.eInt_.integer_); -- -- case is_EAdd: -- return make_EAdd --- ( clone_Exp(p->u.eadd_.exp_1) --- , clone_Exp(p->u.eadd_.exp_2) +-- ( clone_Exp(p->u.eAdd_.exp_1) +-- , clone_Exp(p->u.eAdd_.exp_2) -- ); -- -- default: @@ -375,7 +375,7 @@ prCloneC (cat, rules) prCloneCat :: String -> (Cat, Doc) -> String prCloneCat fnm (cat, nt) = cloner cat member where - member = concat [ "p->u.", map toLower fnm, "_.", render nt ] + member = concat [ "p->u.", memName fnm, ".", render nt ] -- | Clone or not depending on the category. -- Only pointers need to be cloned. @@ -401,8 +401,8 @@ cloner cat x = -- break; -- -- case is_EAdd: --- free_Exp(p->u.eadd_.exp_1); --- free_Exp(p->u.eadd_.exp_2); +-- free_Exp(p->u.eAdd_.exp_1); +-- free_Exp(p->u.eAdd_.exp_2); -- break; -- -- default: @@ -482,8 +482,8 @@ prDestructorC (cat, rules) prFreeCat fnm (cat, nt) = Just $ concat [ maybe ("free_" ++ identCat (normCat cat)) (const "free") $ maybeTokenCat cat , "(p->u." - , map toLower fnm - , "_.", render nt, ");" + , memName fnm + , ".", render nt, ");" ] @@ -614,21 +614,15 @@ prParams = zipWith prParam [1::Int ..] prParam n c = (text (identCat c), text ("p" ++ show n)) -- | Prints the assignments of parameters to instance variables. --- >>> prAssigns "A" [("A",1),("B",2)] [text "abc", text "def"] +-- >>> prAssigns "A" [("A",1),("BA",2)] [text "abc", text "def"] -- tmp->u.a_.a_ = abc; --- tmp->u.a_.b_2 = def; +-- tmp->u.a_.ba_2 = def; prAssigns :: String -> [IVar] -> [Doc] -> Doc prAssigns c vars params = vcat $ zipWith prAssign vars params where prAssign (t,n) p = - text ("tmp->u." ++ c' ++ "_." ++ vname t n) <+> char '=' <+> p <> semi + text ("tmp->u." ++ memName c ++ "." ++ vname t n) <+> char '=' <+> p <> semi vname t n | n == 1, [_] <- filter ((t ==) . fst) vars = varName t | otherwise = varName t ++ showNum n - c' = map toLower c - -{- **** Helper Functions **** -} - -memName :: String -> String -memName s = map toLower s ++ "_" diff --git a/source/src/BNFC/Backend/C/CFtoCPrinter.hs b/source/src/BNFC/Backend/C/CFtoCPrinter.hs index 857011212..f4ab6f99a 100644 --- a/source/src/BNFC/Backend/C/CFtoCPrinter.hs +++ b/source/src/BNFC/Backend/C/CFtoCPrinter.hs @@ -33,7 +33,8 @@ import BNFC.Utils ( (+++), uniqOn, unless, unlessNull ) import BNFC.Backend.Common import BNFC.Backend.Common.NamedVariables -import BNFC.Backend.Common.StrUtils (renderCharOrString) +import BNFC.Backend.Common.StrUtils ( renderCharOrString ) +import BNFC.Backend.C.Common ( memName ) -- | Produces (.h file, .c file). @@ -446,7 +447,7 @@ prPrintRule r@(Rule fun _ _ _) = unless (isCoercion fun) $ concat where p = precRule r fnm = funName fun - pre = concat [ "p->u.", map toLower fnm, "_." ] + pre = concat [ "p->u.", memName fnm, "." ] -- | Only render the rhs (items) of a rule. @@ -567,8 +568,8 @@ prShowCat fnm (cat, nt) = concat [ " sh" , maybe (identCat $ normCat cat) basicFunName $ maybeTokenCat cat , "(p->u." - , map toLower fnm - , "_." + , memName fnm + , "." , render nt , ");\n" ] diff --git a/source/src/BNFC/Backend/C/CFtoCSkel.hs b/source/src/BNFC/Backend/C/CFtoCSkel.hs index ea21f0721..4fc8af5e4 100644 --- a/source/src/BNFC/Backend/C/CFtoCSkel.hs +++ b/source/src/BNFC/Backend/C/CFtoCSkel.hs @@ -19,6 +19,7 @@ import Prelude hiding ((<>)) import BNFC.CF import BNFC.Utils ( (+++), capitalize ) import BNFC.Backend.Common.NamedVariables +import BNFC.Backend.C.Common ( memName ) import Data.Char ( toLower ) import Data.Either ( lefts ) @@ -166,11 +167,11 @@ prData (cat, rules) -- | Visits all the instance variables of a category. -- >>> let ab = Cat "Ab" --- >>> prPrintRule (Rule "Abc" undefined [Left ab, Left ab] Parsable) --- case is_Abc: --- /* Code for Abc Goes Here */ --- visitAb(p->u.abc_.ab_1); --- visitAb(p->u.abc_.ab_2); +-- >>> prPrintRule (Rule "ABC" undefined [Left ab, Left ab] Parsable) +-- case is_ABC: +-- /* Code for ABC Goes Here */ +-- visitAb(p->u.aBC_.ab_1); +-- visitAb(p->u.aBC_.ab_2); -- break; -- -- >>> let ab = TokenCat "Ab" @@ -209,8 +210,7 @@ prCat fnm (cat, vname) = let visitf = "visit" <> if isTokenCat cat then basicFunName cat else text (identCat (normCat cat)) - in visitf <> parens ("p->u." <> text v <> "_." <> vname ) <> ";" - where v = map toLower fnm + in visitf <> parens ("p->u." <> text (memName fnm) <> "." <> vname ) <> ";" -- | The visit-function name of a basic type diff --git a/source/src/BNFC/Backend/C/Common.hs b/source/src/BNFC/Backend/C/Common.hs index ae4ccded3..1ccc27963 100644 --- a/source/src/BNFC/Backend/C/Common.hs +++ b/source/src/BNFC/Backend/C/Common.hs @@ -1,10 +1,12 @@ -- | Common definitions for the modules of the C backend. module BNFC.Backend.C.Common - ( posixC + ( memName + , posixC ) where import Prelude +import BNFC.Backend.Common.NamedVariables -- | Switch C to language variant that has @strdup@. @@ -16,3 +18,8 @@ posixC = , " */" , "#define _POSIX_C_SOURCE 200809L" ] + +-- | Variant names in unions. + +memName :: String -> String +memName s = firstLowerCase s ++ "_" diff --git a/source/src/BNFC/Backend/TreeSitter.hs b/source/src/BNFC/Backend/TreeSitter.hs new file mode 100644 index 000000000..885124c38 --- /dev/null +++ b/source/src/BNFC/Backend/TreeSitter.hs @@ -0,0 +1,32 @@ +{- + BNF Converter: TreeSitter Grammar Generator + Copyright (C) 2004 Author: Markus Forsberg, Michael Pellauer, + Bjorn Bringert + + Description : This module generates the grammar.js input file for + tree-sitter. + + Author : Kangjing Huang (huangkangjing@gmail.com) + Created : 23 Nov, 2023 + +-} + +module BNFC.Backend.TreeSitter where + +import BNFC.Backend.Base +import BNFC.Backend.TreeSitter.CFtoTreeSitter (cfToTreeSitter) +import BNFC.CF +import BNFC.Options hiding (Backend) +import BNFC.PrettyPrint + +-- | Entry point: create grammar.js file +makeTreeSitter :: SharedOptions -> CF -> Backend +makeTreeSitter opts cf = do + mkfile "grammar.js" comment (render $ cfToTreeSitter name cf) + where + name = lang opts + +comment :: String -> String +comment = ("// " ++) + +-- | TODO: Add Makefile generation for tree-sitter diff --git a/source/src/BNFC/Backend/TreeSitter/CFtoTreeSitter.hs b/source/src/BNFC/Backend/TreeSitter/CFtoTreeSitter.hs new file mode 100644 index 000000000..eae9b17bb --- /dev/null +++ b/source/src/BNFC/Backend/TreeSitter/CFtoTreeSitter.hs @@ -0,0 +1,244 @@ +{- + BNF Converter: TreeSitter Grammar Generator + Copyright (C) 2004 Author: Markus Forsberg, Michael Pellauer, + Bjorn Bringert + + Description : This module converts BNFC grammar to the contents of a + tree-sitter grammar.js file + + Author : Kangjing Huang (huangkangjing@gmail.com) + Created : 08 Nov, 2023 + +-} + +module BNFC.Backend.TreeSitter.CFtoTreeSitter where + +import BNFC.Abs (Reg (RSeq, RSeqs, RStar, RAny)) +import BNFC.Backend.TreeSitter.RegToJSReg +import BNFC.CF +import BNFC.Lexing (mkRegMultilineComment) +import BNFC.PrettyPrint +import Prelude hiding ((<>)) + +-- | Indent one level of 2 spaces +indent :: Doc -> Doc +indent = nest 2 + +-- | Create content of grammar.js file +cfToTreeSitter :: String -> CF -> Doc +cfToTreeSitter name cf = + -- Overall structure of grammar.js + text "module.exports = grammar({" + $+$ indent + ( text "name: '" <> text name <> text "'," + $+$ extrasSection + $+$ wordSection + $+$ rulesSection + ) + $+$ text "});" + where + extrasSection = prExtras cf + wordSection = prWord cf + rulesSection = + text "rules: {" + $+$ indent + ( prRules cf + $+$ prUsrTokenRules cf + $+$ prBuiltinTokenRules cf + ) + $+$ text "}," + +-- | Print rules for comments +prExtras :: CF -> Doc +prExtras cf = + if extraNeeded + then + defineSymbol "extras" <> "[" + $+$ indent + ( -- default rule for white spaces + text "/\\s/," + $+$ mRules + $+$ sRules + ) + $+$ text "]," + else empty + where + extraNeeded = length commentMRules + length commentSRules > 0 + (commentMRules, commentSRules) = comments cf + mRules = vcat' $ map mkOneMRule commentMRules + sRules = vcat' $ map mkOneSRule commentSRules + mkOneSRule s = text (printRegJSReg $ RSeq (RSeqs s) (RStar RAny)) <> text "," + mkOneMRule (s, e) = text (printRegJSReg $ mkRegMultilineComment s e) <> text "," + +-- | Print word section, this section is needed for tree-sitter +-- to do keyword extraction before any parsing/lexing, see +-- https://tree-sitter.github.io/tree-sitter/creating-parsers#keyword-extraction +-- TODO: currently, we just add every user defined token as well +-- as the predefined Ident token to this list to be safe. Ideally, +-- we should enumerate all defined tokens against all occurrences of +-- keywords. Any tokens patterns that could accept a keyword will go +-- into this list. This will require integration of a regex engine. +prWord :: CF -> Doc +prWord cf = + if wordNeeded + then + defineSymbol "word" + $+$ indent + ( wrapChoice + ( usrTokensFormatted + ++ [text "$.token_Ident" | identUsed] + ) + ) + <> "," + else empty + where + wordNeeded = identUsed || usrTokens /= [] + identUsed = isUsedCat cf (TokenCat catIdent) + usrTokens = tokenPragmas cf + usrTokensFormatted = + map (text . refName . formatCatName False . TokenCat . fst) $ usrTokens + +-- | Print builtin token rules according to their usage +prBuiltinTokenRules :: CF -> Doc +prBuiltinTokenRules cf = + ifC catInteger integerRule + $+$ ifC catDouble doubleRule + $+$ ifC catChar charRule + $+$ ifC catString stringRule + $+$ ifC catIdent identRule + where + ifC cat d = if isUsedCat cf (TokenCat cat) then d else empty + +-- | Predefined builtin token rules +integerRule, doubleRule, charRule, stringRule, identRule :: Doc +integerRule = defineSymbol "token_Integer" <+> text "/\\d+/" <> "," +doubleRule = defineSymbol "token_Double" <+> text "/\\d+\\.\\d+(e-?\\d+)?/" <> "," +charRule = + defineSymbol "token_Char" <+> text "/'([^'\\\\]|(\\\\[\"'\\\\tnrf]))'/" <> "," +stringRule = + defineSymbol "token_String" <+> text "/\"([^'\\\\]|(\\\\[\"'\\\\tnrf]))*\"/" <> "," +identRule = + defineSymbol "token_Ident" <+> text "/[a-zA-Z][a-zA-Z\\d_']*/" <> "," + +-- | First print the entrypoint rule, tree-sitter always use the +-- first rule as entrypoint and does not support multi-entrypoint. +-- Then print rest of the rules +prRules :: CF -> Doc +prRules cf = + if onlyOneEntry + then + prOneCat entryRules entryCat + $+$ prOtherRules entryCat cf + else error "Tree-sitter only supports one entrypoint" + where + --If entrypoint is defined, there must be only one entrypoint + --If it is not defined, defaults to use the first rule as entrypoint + onlyOneEntry = not (hasEntryPoint cf) || onlyOneEntryDefined + onlyOneEntryDefined = length (allEntryPoints cf) == 1 + entryCat = firstEntry cf + entryRules = rulesForCat' cf entryCat + +-- | Print all other rules except the entrypoint +prOtherRules :: Cat -> CF -> Doc +prOtherRules entryCat cf = vcat' $ map mkOne rules + where + rules = [(c, r) | (c, r) <- ruleGroupsInternals cf, c /= entryCat] + mkOne (cat, rules) = prOneCat rules cat + +prUsrTokenRules :: CF -> Doc +prUsrTokenRules cf = vcat' $ map prOneToken tokens + where + tokens = tokenPragmas cf + +-- | Check if a set of rules contains internal rules +hasInternal :: [Rule] -> Bool +hasInternal = not . all isParsable + +-- | Generates one or two tree-sitter rule(s) for one non-terminal from CF. +-- Uses choice function from tree-sitter to combine rules for the non-terminal +-- If the non-terminal has internal rules, an internal version of the non-terminal +-- will be created (prefixed with "_" in tree-sitter), and all internal rules will +-- be sectioned as such. +prOneCat :: [Rule] -> NonTerminal -> Doc +prOneCat rules nt = + defineSymbol (formatCatName False nt) + $+$ indent (appendComma parRhs) + $+$ internalRules + where + int = hasInternal rules + internalRules = + if int + then defineSymbol (formatCatName True nt) $+$ indent (appendComma intRhs) + else empty + parRhs = wrapChoice $ transChoice ++ genChoice (filter isParsable rules) + transChoice = [text $ refName $ formatCatName True nt | int] + intRhs = wrapChoice $ genChoice (filter (not . isParsable) rules) + genChoice = map (wrapSeq . formatRhs . rhsRule) + +-- | Generate one tree-sitter rule for one defined token +prOneToken :: (TokenCat, Reg) -> Doc +prOneToken (cat, exp) = + defineSymbol (formatCatName False $ TokenCat cat) + $+$ indent (text $ printRegJSReg exp) <> "," + +-- | Start a defined symbol block in tree-sitter grammar +defineSymbol :: String -> Doc +defineSymbol name = hsep [text name <> ":", text "$", text "=>"] + +appendComma :: Doc -> Doc +appendComma = (<> text ",") + +commaJoin :: Bool -> [Doc] -> Doc +commaJoin newline = + foldl comma empty + where + comma a b + | isEmpty a = b + | isEmpty b = a + | otherwise = (if newline then ($+$) else (<>)) (a <> ",") b + +wrapSeq :: [Doc] -> Doc +wrapSeq = wrapOptListFun "seq" False + +wrapChoice :: [Doc] -> Doc +wrapChoice = wrapOptListFun "choice" True + +-- | Wrap list using tree-sitter fun if the list contains multiple items +-- Returns the only item without wrapping otherwise +wrapOptListFun :: String -> Bool -> [Doc] -> Doc +wrapOptListFun fun newline list = + if length list == 1 + then head list + else wrapFun fun newline (commaJoin newline list) + +wrapFun :: String -> Bool -> Doc -> Doc +wrapFun fun newline arg = joinOp [text fun <> text "(", indent arg, text ")"] + where + joinOp = if newline then vcat' else hcat + +-- | Helper for referring to non-terminal names in tree-sitter +refName :: String -> String +refName = ("$." ++) + +-- | Format right hand side into list of strings +formatRhs :: SentForm -> [Doc] +formatRhs = + map (\case + Left c -> text $ refName $ formatCatName False c + Right term -> quoted term) + +quoted :: String -> Doc +quoted s = text "\"" <> text s <> text "\"" + +-- | Format string for cat name, prefix "_" if the name is for internal rules +formatCatName :: Bool -> Cat -> String +formatCatName internal c = + if internal + then "_" ++ formatted + else formatted + where + formatted = formatName c + formatName (Cat name) = name + formatName (TokenCat name) = "token_" ++ name + formatName (ListCat c) = "list_" ++ formatName c + formatName (CoercCat name i) = name ++ show i \ No newline at end of file diff --git a/source/src/BNFC/Backend/TreeSitter/RegToJSReg.hs b/source/src/BNFC/Backend/TreeSitter/RegToJSReg.hs new file mode 100644 index 000000000..92ca550db --- /dev/null +++ b/source/src/BNFC/Backend/TreeSitter/RegToJSReg.hs @@ -0,0 +1,94 @@ +{- + BNF Converter: TreeSitter Grammar Generator + Copyright (C) 2004 Author: Markus Forsberg, Michael Pellauer, + Bjorn Bringert + + Description : This module converts BNFC Reg to Javascript regular + expressions that is used in + + Author : Kangjing Huang (huangkangjing@gmail.com) + Created : 23 Nov, 2023 + +-} +{-# LANGUAGE LambdaCase #-} + +module BNFC.Backend.TreeSitter.RegToJSReg (printRegJSReg) where + +import BNFC.Abs + +printRegJSReg :: Reg -> String +printRegJSReg r = "/" ++ render (prt 0 r) ++ "/" + +-- There is no space-based formatting for javascript regex +-- We just concat everything together +render :: [String] -> String +render = concat + +parenth :: [String] -> [String] +parenth s = ["("] ++ s ++ [")"] + +-- Printer class +class Print a where + prt :: Int -> a -> [String] + +prPrec :: Int -> Int -> [String] -> [String] +prPrec i j = if i > j then parenth else id + +-- | reserved characters for Javascript regex format, sourced from +-- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping +reserved :: String +reserved = ".*+?^${}()|[]\\/" + +-- | reserved characters for alt expressions in Javascript regex format +reservedAlt :: String +reservedAlt = "^[]-\\/" + +-- | Pattern for matching empty string in Javascript regex format +emptyPat :: String +emptyPat = " [^\\u0000-\\uFFFF]?" + +-- | escape character according to Javascript regex format +escapeCharFrom :: String -> Char -> String +escapeCharFrom reservedChars x + | x `elem` reservedChars = '\\' : [x] + | otherwise = [x] + +escapeChar :: Char -> String +escapeChar = escapeCharFrom reserved + +escapeStr :: String -> String +escapeStr = concatMap escapeChar + +escapeCharAlt :: Char -> String +escapeCharAlt = escapeCharFrom reservedAlt + +escapeStrAlt :: String -> String +escapeStrAlt = concatMap escapeChar + +instance Print Identifier where + prt _ (Identifier (_, i)) = [i] + +instance Print Reg where + prt i = \case + RSeq reg0 reg -> prPrec i 2 $ prt 2 reg0 ++ prt 3 reg + RAlt reg0 reg -> prPrec i 1 $ prt 1 reg0 ++ ["|"] ++ prt 2 reg + -- Javascript regex does not support general set difference + RMinus reg0 REps -> prt i reg0 -- REps is identity for difference + RMinus RAny (RChar c) -> ["[^" ++ escapeCharAlt c ++ "]"] + RMinus RAny (RAlts s) -> ["[^" ++ escapeStrAlt s ++ "]"] + -- TODO: It is possible to use external scanners in tree-sitter: + -- https://tree-sitter.github.io/tree-sitter/creating-parsers#external-scanners + -- to support general set differences in the future + RMinus _ _ -> error "Javascript regex does not support general set differences" + RStar reg -> prt 3 reg ++ ["*"] + RPlus reg -> prt 3 reg ++ ["+"] + ROpt reg -> prt 3 reg ++ ["?"] + REps -> [emptyPat] + RChar c -> [escapeChar c] + RAlts str -> ["[" ++ escapeStrAlt str ++ "]"] + RSeqs str -> [escapeStr str] + RDigit -> ["\\d"] + RLetter -> ["[a-zA-Z]"] + RUpper -> ["[A-Z]"] + RLower -> ["[a-z]"] + RAny -> ["."] diff --git a/source/src/BNFC/CF.hs b/source/src/BNFC/CF.hs index 27d577969..f1c50e0d8 100644 --- a/source/src/BNFC/CF.hs +++ b/source/src/BNFC/CF.hs @@ -783,6 +783,9 @@ hasPositionTokens cf = or [ b | TokenReg _ b _ <- cfgPragmas cf ] isPositionCat :: CFG f -> TokenCat -> Bool isPositionCat cf cat = or [ b | TokenReg name b _ <- cfgPragmas cf, wpThing name == cat] +-- | Is there a explicitly defined @entrypoint@ pragma? +hasEntryPoint :: CFG f -> Bool +hasEntryPoint cf = or [ True | EntryPoints{} <- cfgPragmas cf] -- | Categories that are entry points to the parser. -- diff --git a/source/src/BNFC/GetCF.hs b/source/src/BNFC/GetCF.hs index fe9d6eaa1..3a8c681a6 100644 --- a/source/src/BNFC/GetCF.hs +++ b/source/src/BNFC/GetCF.hs @@ -18,12 +18,12 @@ -- | Check LBNF input file and turn it into the 'CF' internal representation. module BNFC.GetCF - ( parseCF + ( parseCF, parseRawCF , checkRule, transItem ) where import Control.Arrow (left) -import Control.Monad.Reader (ReaderT, runReaderT, MonadReader(..), asks) +import Control.Monad.Reader (ReaderT, runReaderT, MonadReader(..), ask) import Control.Monad.State (State, evalState, get, modify) import Control.Monad.Except (MonadError(..)) @@ -63,18 +63,23 @@ type Err = Either String -- $setup -- >>> import BNFC.Print --- | Entrypoint. +-- | Parse raw CF from LBNF file without checking backend requirements -parseCF :: SharedOptions -> Target -> String -> IO CF -parseCF opts target content = do - cf <- runErr $ pGrammar (myLexer content) +parseRawCF :: FilePath -> String -> Err CF +parseRawCF fileName content = pGrammar (myLexer content) -- <&> expandRules -- <&> from ghc 8.4 >>= return . expandRules - >>= getCF opts + >>= getCF fileName >>= return . markTokenCategories + -- Construct the typing information in 'define' expressions. + >>= runTypeChecker . checkDefinitions + +-- | Entrypoint. Parses full CF from LBNF file and checks against +-- all backend requirements - -- Construct the typing information in 'define' expressions. - cf <- either die return $ runTypeChecker $ checkDefinitions cf +parseCF :: SharedOptions -> Target -> String -> IO CF +parseCF opts target content = do + cf <- runErr $ parseRawCF (lbnfFile opts) content -- Some backends do not allow the grammar name to coincide with -- one of the category or constructor names. @@ -162,9 +167,13 @@ parseCF opts target content = do ] -- Warn or fail if the grammar uses names not unique modulo upper/lowercase. - when False $ - case nub $ filter (`notElem` nonUniqueNames) $ filter (not . isDefinedRule) $ - concatMap List1.toList $ duplicatesOn (map toLower . wpThing) names of + case nub + . filter (`notElem` nonUniqueNames) + . concatMap List1.toList + . duplicatesOn (map toLower . wpThing) + . filter (not . isDefinedRule) + $ names + of [] -> return () ns | target `elem` [ TargetJava ] -> dieUnlessForce $ unlines $ concat @@ -259,9 +268,9 @@ die msg = do -- | Translate the parsed grammar file into a context-free grammar 'CF'. -- Desugars and type-checks. -getCF :: SharedOptions -> Abs.Grammar -> Err CF -getCF opts (Abs.Grammar defs) = do - (pragma, rules) <- partitionEithers . concat <$> mapM transDef defs `runTrans` opts +getCF :: FilePath -> Abs.Grammar -> Err CF +getCF inputFile (Abs.Grammar defs) = do + (pragma, rules) <- partitionEithers . concat <$> mapM transDef defs `runTrans` inputFile let reservedWords = nub [ t | r <- rules, isParsable r, Right t <- rhsRule r, not $ all isSpace t ] -- Issue #204: exclude keywords from internal rules -- Issue #70: whitespace separators should be treated like "", at least in the parser @@ -345,10 +354,10 @@ instance FixTokenCats (CFG f) where } -- | Translation monad. -newtype Trans a = Trans { unTrans :: ReaderT SharedOptions Err a } - deriving (Functor, Applicative, Monad, MonadReader SharedOptions, MonadError String) +newtype Trans a = Trans { unTrans :: ReaderT FilePath Err a } + deriving (Functor, Applicative, Monad, MonadReader FilePath, MonadError String) -runTrans :: Trans a -> SharedOptions -> Err a +runTrans :: Trans a -> FilePath -> Err a runTrans m opts = unTrans m `runReaderT` opts transDef :: Abs.Def -> Trans [Either Pragma Rule] @@ -447,7 +456,7 @@ coercionRules c0 n = do ebnfRules :: Abs.Identifier -> [Abs.RHS] -> Trans [Rule] ebnfRules (Abs.Identifier ((line, col), c)) rhss = do - file <- asks lbnfFile + file <- ask let wp = WithPosition $ Position file line col let rule x rhs = Rule (wp x) (wp $ strToCat c) rhs Parsable return @@ -487,7 +496,7 @@ transCat :: Abs.Cat -> Trans (WithPosition Cat) transCat = \case Abs.ListCat cat -> fmap ListCat <$> transCat cat Abs.IdCat (Abs.Identifier ((line, col), c)) -> do - file <- asks lbnfFile + file <- ask return $ WithPosition (Position file line col) $ strToCat c transLabel :: Abs.Label -> Trans RFun @@ -500,7 +509,7 @@ transLabel = \case transIdent :: Abs.Identifier -> Trans RString transIdent (Abs.Identifier ((line, col), str)) = do - file <- asks lbnfFile + file <- ask return $ WithPosition (Position file line col) str transArg :: Abs.Arg -> (String, Base) diff --git a/source/src/BNFC/Options.hs b/source/src/BNFC/Options.hs index 09cd477ec..ac5fdbf65 100644 --- a/source/src/BNFC/Options.hs +++ b/source/src/BNFC/Options.hs @@ -63,6 +63,7 @@ data Mode data Target = TargetC | TargetCpp | TargetCppNoStl | TargetHaskell | TargetHaskellGadt | TargetLatex | TargetJava | TargetOCaml | TargetPygments + | TargetTreeSitter | TargetCheck deriving (Eq, Bounded, Enum, Ord) @@ -80,6 +81,7 @@ instance Show Target where show TargetJava = "Java" show TargetOCaml = "OCaml" show TargetPygments = "Pygments" + show TargetTreeSitter = "Tree-sitter" show TargetCheck = "Check LBNF file" -- | Which version of Alex is targeted? @@ -258,6 +260,7 @@ printTargetOption = ("--" ++) . \case TargetJava -> "java" TargetOCaml -> "ocaml" TargetPygments -> "pygments" + TargetTreeSitter -> "tree-sitter" TargetCheck -> "check" printAlexOption :: AlexVersion -> String @@ -309,6 +312,8 @@ targetOptions = "Output OCaml code for use with ocamllex and menhir (short for --ocaml --menhir)" , Option "" ["pygments"] (NoArg (\o -> o {target = TargetPygments})) "Output a Python lexer for Pygments" + , Option "" ["tree-sitter"] (NoArg (\o -> o {target = TargetTreeSitter})) + "Output grammar.js file for use with tree-sitter" , Option "" ["check"] (NoArg (\ o -> o{target = TargetCheck })) "No output. Just check input LBNF file" ] @@ -524,6 +529,7 @@ instance Maintained Target where TargetJava -> True TargetOCaml -> True TargetPygments -> True + TargetTreeSitter -> True TargetCheck -> True instance Maintained AlexVersion where diff --git a/source/src/Makefile b/source/src/Makefile index 043c24270..0ffaa63d7 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -62,4 +62,8 @@ fake-cabal : rm-fake-cabal : rm inferior-haskell-find-project-root.cabal +.PHONY: clean +clean : + rm BNFC/Lex.hs BNFC/Par.hs BNFC/*.bak + #EOF diff --git a/source/stack-8.10.2.yaml b/source/stack-8.10.2.yaml deleted file mode 100644 index 59a210daf..000000000 --- a/source/stack-8.10.2.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: nightly-2020-12-14 -compiler: ghc-8.10.2 -compiler-check: match-exact diff --git a/source/stack-8.10.3.yaml b/source/stack-8.10.3.yaml deleted file mode 100644 index 8a12f53cb..000000000 --- a/source/stack-8.10.3.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: lts-17.2 -compiler: ghc-8.10.3 -compiler-check: match-exact diff --git a/source/stack-8.10.4.yaml b/source/stack-8.10.4.yaml deleted file mode 100644 index df32574a6..000000000 --- a/source/stack-8.10.4.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: lts-17.13 -compiler: ghc-8.10.4 -compiler-check: match-exact diff --git a/source/stack-8.10.5.yaml b/source/stack-8.10.5.yaml deleted file mode 100644 index 8bb7ae0e3..000000000 --- a/source/stack-8.10.5.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: lts-18.0 -compiler: ghc-8.10.5 -compiler-check: match-exact diff --git a/source/stack-8.10.7.yaml b/source/stack-8.10.yaml similarity index 59% rename from source/stack-8.10.7.yaml rename to source/stack-8.10.yaml index ba432be3e..e2c4d8f46 100644 --- a/source/stack-8.10.7.yaml +++ b/source/stack-8.10.yaml @@ -1,3 +1,3 @@ resolver: lts-18.28 compiler: ghc-8.10.7 -compiler-check: match-exact +compiler-check: newer-minor diff --git a/source/stack-8.2.2.yaml b/source/stack-8.2.yaml similarity index 100% rename from source/stack-8.2.2.yaml rename to source/stack-8.2.yaml diff --git a/source/stack-8.4.4.yaml b/source/stack-8.4.yaml similarity index 100% rename from source/stack-8.4.4.yaml rename to source/stack-8.4.yaml diff --git a/source/stack-8.6.4.yaml b/source/stack-8.6.4.yaml deleted file mode 100644 index b9d693723..000000000 --- a/source/stack-8.6.4.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resolver: lts-13.19 - diff --git a/source/stack-8.6.5.yaml b/source/stack-8.6.yaml similarity index 100% rename from source/stack-8.6.5.yaml rename to source/stack-8.6.yaml diff --git a/source/stack-8.8.2.yaml b/source/stack-8.8.2.yaml deleted file mode 100644 index a780162de..000000000 --- a/source/stack-8.8.2.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resolver: lts-15.3 - diff --git a/source/stack-8.8.3.yaml b/source/stack-8.8.3.yaml deleted file mode 100644 index 6484e3ab0..000000000 --- a/source/stack-8.8.3.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resolver: lts-15.8 - diff --git a/source/stack-8.8.4.yaml b/source/stack-8.8.yaml similarity index 58% rename from source/stack-8.8.4.yaml rename to source/stack-8.8.yaml index 0fa323dc0..636ab4aa1 100644 --- a/source/stack-8.8.4.yaml +++ b/source/stack-8.8.yaml @@ -1,3 +1,3 @@ resolver: lts-16.31 compiler: ghc-8.8.4 -compiler-check: match-exact +compiler-check: newer-minor diff --git a/source/stack-9.0.1.yaml b/source/stack-9.0.1.yaml deleted file mode 100644 index cc7ecfa5d..000000000 --- a/source/stack-9.0.1.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: nightly-2022-01-04 -compiler: ghc-9.0.1 -# compiler-check: match-exact diff --git a/source/stack-9.0.2.yaml b/source/stack-9.0.yaml similarity index 58% rename from source/stack-9.0.2.yaml rename to source/stack-9.0.yaml index 91f685579..212f94280 100644 --- a/source/stack-9.0.2.yaml +++ b/source/stack-9.0.yaml @@ -1,3 +1,3 @@ resolver: lts-19.33 compiler: ghc-9.0.2 -compiler-check: match-exact +compiler-check: newer-minor diff --git a/source/stack-9.2.1.yaml b/source/stack-9.2.1.yaml deleted file mode 100644 index 7230ff806..000000000 --- a/source/stack-9.2.1.yaml +++ /dev/null @@ -1,33 +0,0 @@ -resolver: ghc-9.2.1 -compiler: ghc-9.2.1 -# compiler-check: match-exact - -extra-deps: -- alex-3.2.6 -- cabal-doctest-1.0.9 -- happy-1.20.0 -- string-qq-0.0.4 - -# For --test: -- HUnit-1.6.2.0 -- QuickCheck-2.14.2 -- ansi-terminal-0.11 -- base-compat-0.12.1 -- call-stack-0.4.0 -- clock-0.8.2 -- code-page-0.2.1 -- colour-2.3.6 -- doctest-0.20.0 -- ghc-paths-0.1.0.12@rev:3 -- hspec-2.9.4 -- hspec-core-2.9.4 -- hspec-discover-2.9.4 -- hspec-expectations-0.8.2 -- primitive-0.7.3.0 -- quickcheck-io-0.2.0 -- random-1.2.1 -- setenv-0.1.1.3 -- splitmix-0.1.0.4 -- syb-0.7.2.1 -- temporary-1.3 -- tf-random-0.5 diff --git a/source/stack-9.2.4.yaml b/source/stack-9.2.4.yaml deleted file mode 100644 index 3be3da6ba..000000000 --- a/source/stack-9.2.4.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: nightly-2022-10-18 -compiler: ghc-9.2.4 -compiler-check: match-exact diff --git a/source/stack-9.2.5.yaml b/source/stack-9.2.5.yaml deleted file mode 100644 index e7a88bc00..000000000 --- a/source/stack-9.2.5.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: lts-20.4 -compiler: ghc-9.2.5 -compiler-check: match-exact diff --git a/source/stack-9.2.7.yaml b/source/stack-9.2.7.yaml deleted file mode 100644 index 561928b78..000000000 --- a/source/stack-9.2.7.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: lts-20.13 -compiler: ghc-9.2.7 -compiler-check: match-exact diff --git a/source/stack-9.2.8.yaml b/source/stack-9.2.yaml similarity index 58% rename from source/stack-9.2.8.yaml rename to source/stack-9.2.yaml index a45d7fc7b..504a1bf1f 100644 --- a/source/stack-9.2.8.yaml +++ b/source/stack-9.2.yaml @@ -1,3 +1,3 @@ resolver: lts-20.26 compiler: ghc-9.2.8 -compiler-check: match-exact +compiler-check: newer-minor diff --git a/source/stack-9.4.3.yaml b/source/stack-9.4.3.yaml deleted file mode 100644 index 3c82bd55b..000000000 --- a/source/stack-9.4.3.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: nightly-2022-12-12 -compiler: ghc-9.4.3 -compiler-check: match-exact diff --git a/source/stack-9.4.4.yaml b/source/stack-9.4.4.yaml deleted file mode 100644 index 2090bb595..000000000 --- a/source/stack-9.4.4.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: nightly-2023-03-04 -compiler: ghc-9.4.4 -compiler-check: match-exact diff --git a/source/stack-9.4.5.yaml b/source/stack-9.4.5.yaml deleted file mode 100644 index 1985c9f11..000000000 --- a/source/stack-9.4.5.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: lts-21.0 -compiler: ghc-9.4.5 -compiler-check: match-exact diff --git a/source/stack-9.4.yaml b/source/stack-9.4.yaml new file mode 100644 index 000000000..9034c9280 --- /dev/null +++ b/source/stack-9.4.yaml @@ -0,0 +1,3 @@ +resolver: lts-21.25 +compiler: ghc-9.4.8 +compiler-check: newer-minor diff --git a/source/stack-9.6.2.yaml b/source/stack-9.6.2.yaml deleted file mode 100644 index 3c77feb2e..000000000 --- a/source/stack-9.6.2.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resolver: nightly-2023-06-26 -compiler: ghc-9.6.2 -compiler-check: match-exact diff --git a/source/stack-9.6.yaml b/source/stack-9.6.yaml new file mode 100644 index 000000000..97984ed16 --- /dev/null +++ b/source/stack-9.6.yaml @@ -0,0 +1,3 @@ +resolver: lts-22.23 +compiler: ghc-9.6.5 +compiler-check: newer-minor diff --git a/source/stack-9.8.yaml b/source/stack-9.8.yaml new file mode 100644 index 000000000..7deed1673 --- /dev/null +++ b/source/stack-9.8.yaml @@ -0,0 +1,6 @@ +resolver: nightly-2024-05-30 +compiler: ghc-9.8.2 +compiler-check: newer-minor + +packages: +- . diff --git a/source/test/BNFC/Backend/TreeSitterSpec.hs b/source/test/BNFC/Backend/TreeSitterSpec.hs new file mode 100644 index 000000000..1651a10ad --- /dev/null +++ b/source/test/BNFC/Backend/TreeSitterSpec.hs @@ -0,0 +1,25 @@ +module BNFC.Backend.TreeSitterSpec where + +import BNFC.Options +import BNFC.GetCF + +import Test.Hspec +import BNFC.Hspec + +import BNFC.Backend.TreeSitter -- SUT + +calcOptions = defaultOptions { lang = "Calc" } +getCalc = parseCF calcOptions TargetTreeSitter $ + unlines [ "EAdd. Exp ::= Exp \"+\" Exp1 ;" + , "ESub. Exp ::= Exp \"-\" Exp1 ;" + , "EMul. Exp1 ::= Exp1 \"*\" Exp2 ;" + , "EDiv. Exp1 ::= Exp1 \"/\" Exp2 ;" + , "EInt. Exp2 ::= Integer ;" + , "coercions Exp 2 ;" ] + +spec = do + + describe "Tree-Sitter backend" $ do + it "creates the grammar.js file" $ do + calc <- getCalc + makeTreeSitter calcOptions calc `shouldGenerate` "grammar.js" diff --git a/stack-8.10.2.yaml b/stack-8.10.2.yaml deleted file mode 100644 index ce0f0e531..000000000 --- a/stack-8.10.2.yaml +++ /dev/null @@ -1,152 +0,0 @@ -resolver: ghc-8.10.2 -compiler: ghc-8.10.2 -compiler-check: match-exact - -extra-deps: -# For BNFC, package 'source' -- alex-3.2.5 -- happy-1.19.12 -- semigroups-0.19.1 -- string-qq-0.0.4 - -# For --test and package 'testing' -- Diff-0.4.0 -- HTF-0.14.0.3 -- HUnit-1.6.0.0 -- QuickCheck-2.13.2 -- aeson-1.5.3.0 -- ansi-terminal-0.11 -- assoc-1.0.2 -- async-2.2.2 -- attoparsec-0.13.2.4 -- base-compat-0.11.1 -- base-compat-batteries-0.11.1 -- base-orphans-0.8.2 -- base64-bytestring-1.2.0.0 -- bifunctors-5.5.7 -- blaze-builder-0.4.1.0 -- cabal-doctest-1.0.8 -- call-stack-0.2.0 -- clock-0.8 -- code-page-0.2 -- colour-2.3.5 -- comonad-5.0.6 -- constraints-0.12 -- cpphs-1.20.9.1 -- data-fix-0.3.0 -- distributive-0.6.2 -- dlist-0.8.0.8 -- doctest-0.17 -- enclosed-exceptions-1.0.3 -- ghc-paths-0.1.0.12 -- hashable-1.3.0.0 -- haskell-src-1.0.3.1 -- hspec-2.7.4 -- hspec-core-2.7.4 -- hspec-discover-2.7.4 -- hspec-expectations-0.8.2 -- integer-logarithms-1.0.3 -- lifted-async-0.10.1.2 -- lifted-base-0.2.3.12 -- monad-control-1.0.2.3 -- old-locale-1.0.0.7 -- old-time-1.1.0.3 -- polyparse-1.13 -- primitive-0.7.1.0 -- quickcheck-io-0.2.0 -- random-1.1 -# - random-1.2.0 # dependency cycle, and HTF does not like it -- regex-base-0.94.0.0 -- regex-compat-0.95.2.0 -- regex-posix-0.96.0.0 -- scientific-0.3.6.2 -- setenv-0.1.1.3 -- shelly-1.9.0 -- splitmix-0.0.5 -- strict-0.4 -- syb-0.7.1 -- tagged-0.8.6 -- temporary-1.3 -- tf-random-0.5 -- th-abstraction-0.3.2.0 -- these-1.1.1.1 -- time-compat-1.9.3 -- transformers-base-0.4.5.2 -- transformers-compat-0.6.5 -- type-equality-1 -- unix-compat-0.5.2 -- unordered-containers-0.2.12.0 -- uuid-types-1.0.3 -- vector-0.12.1.2 -- xmlgen-0.6.2.2 - -# NOT NEEDED -# - ListLike-4.7.1 -# - STMonadTrans-0.4.4 -# - ansi-terminal-0.10.3 -# - ansi-wl-pprint-0.6.9 -# - blaze-html-0.9.1.2 -# - blaze-markup-0.8.2.7 -# - boxes-0.1.5 -# - case-insensitive-1.2.1.0 -# - clock-0.8 -# - cmdargs-0.10.20 -# - colour-2.3.5 -# - conduit-1.3.2 -# - data-default-0.7.1.1 -# - data-default-class-0.1.2.0 -# - data-default-instances-containers-0.0.1 -# - data-default-instances-dlist-0.0.1 -# - data-default-instances-old-locale-0.0.1 -# - data-hash-0.2.0.1 -# - edit-distance-0.2.2.1 -# - equivalence-0.3.5 -# - extensible-exceptions-0.1.1.4 -# - extra-1.7.2 -# - fail-4.9.0.0 -# - filemanip-0.3.6.3 -# - filepattern-0.1.2 -# - fmlist-0.9.3 -# - generic-deriving-1.13.1 -# - gitrev-1.3.1 -# - hashtables-1.2.3.4 -# - haskell-lexer-1.1 -# - hostname-1.0 -# - ieee754-0.8.0 -# - libyaml-0.1.2 -# - mono-traversable-1.0.15.1 -# - murmur-hash-0.1.0.9 -# - network-uri-2.6.3.0 -# - optparse-applicative-0.16.0.0 -# - pretty-show-1.10 -# - process-extras-0.7.4 -# - regex-tdfa-1.3.1.0 -# - resourcet-1.2.3 -# - safe-0.3.19 -# - split-0.2.3.4 -# - tasty-1.2.3 -# - tasty-hunit-0.10.0.2 -# - tasty-quickcheck-0.10.1.1 -# - tasty-silver-3.1.15 -# - temporary-1.3 -# - test-framework-0.8.2.0 -# - test-framework-hunit-0.3.0.2 -# - text-icu-0.7.0.1 -# - unbounded-delays-0.1.1.0 -# - unliftio-core-0.2.0.1 -# - uri-encode-1.5.0.6 -# - utf8-string-1.0.1.1 -# - vector-algorithms-0.8.0.3 -# - wcwidth-0.0.2 -# - xml-1.3.14 -# - yaml-0.11.3.0 -# - zlib-0.6.2.2 - -flags: - transformers-compat: - five-three: true - -# Local packages, usually specified by relative directory name -packages: -- 'source' -- 'testing' diff --git a/stack-8.10.3.yaml b/stack-8.10.3.yaml deleted file mode 100644 index 3c3c4cd16..000000000 --- a/stack-8.10.3.yaml +++ /dev/null @@ -1,11 +0,0 @@ -resolver: lts-17.2 -compiler: ghc-8.10.3 -compiler-check: match-exact - -packages: -- source -- testing - -extra-deps: -- haskell-src-1.0.3.1 -- HTF-0.15.0.0 diff --git a/stack-8.10.4.yaml b/stack-8.10.4.yaml deleted file mode 100644 index 78fd6806b..000000000 --- a/stack-8.10.4.yaml +++ /dev/null @@ -1,11 +0,0 @@ -resolver: lts-17.13 -compiler: ghc-8.10.4 -compiler-check: match-exact - -packages: -- source -- testing - -# `testing` depends on more recent `HTF` -extra-deps: -- HTF-0.15.0.0 diff --git a/stack-8.10.7.yaml b/stack-8.10.yaml similarity index 83% rename from stack-8.10.7.yaml rename to stack-8.10.yaml index c56ac78d3..22358dd36 100644 --- a/stack-8.10.7.yaml +++ b/stack-8.10.yaml @@ -1,6 +1,6 @@ resolver: lts-18.28 compiler: ghc-8.10.7 -compiler-check: match-exact +compiler-check: newer-minor packages: - source diff --git a/stack-8.2.2.yaml b/stack-8.2.yaml similarity index 100% rename from stack-8.2.2.yaml rename to stack-8.2.yaml diff --git a/stack-8.4.4.yaml b/stack-8.4.yaml similarity index 100% rename from stack-8.4.4.yaml rename to stack-8.4.yaml diff --git a/stack-8.6.5.yaml b/stack-8.6.yaml similarity index 100% rename from stack-8.6.5.yaml rename to stack-8.6.yaml diff --git a/stack-8.8.4.yaml b/stack-8.8.yaml similarity index 83% rename from stack-8.8.4.yaml rename to stack-8.8.yaml index 80609f73f..8bdd0fdcd 100644 --- a/stack-8.8.4.yaml +++ b/stack-8.8.yaml @@ -1,6 +1,6 @@ resolver: lts-16.31 compiler: ghc-8.8.4 -compiler-check: match-exact +compiler-check: newer-minor packages: - source diff --git a/stack-9.0.2.yaml b/stack-9.0.yaml similarity index 71% rename from stack-9.0.2.yaml rename to stack-9.0.yaml index 577c4f194..ff9c713dd 100644 --- a/stack-9.0.2.yaml +++ b/stack-9.0.yaml @@ -1,6 +1,6 @@ resolver: lts-19.33 compiler: ghc-9.0.2 -compiler-check: match-exact +compiler-check: newer-minor packages: - source diff --git a/stack-9.10.yaml b/stack-9.10.yaml new file mode 100644 index 000000000..fd2519f04 --- /dev/null +++ b/stack-9.10.yaml @@ -0,0 +1,13 @@ +resolver: nightly-2024-10-30 +compiler: ghc-9.10.1 +compiler-check: newer-minor + +packages: +- source +- testing + +extra-deps: +- directory-1.3.8.3 #.5 +- filepath-1.4.300.2 # 1.5.3.0 +- process-1.6.19.0 #.23.0 +- unix-2.8.5.1 diff --git a/stack-9.2.2.yaml b/stack-9.2.2.yaml deleted file mode 100644 index ced9dcc3b..000000000 --- a/stack-9.2.2.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: nightly-2022-03-25 -compiler: ghc-9.2.2 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.2.4.yaml b/stack-9.2.4.yaml deleted file mode 100644 index ef1501024..000000000 --- a/stack-9.2.4.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: nightly-2022-10-18 -compiler: ghc-9.2.4 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.2.5.yaml b/stack-9.2.5.yaml deleted file mode 100644 index 4ab48df36..000000000 --- a/stack-9.2.5.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: lts-20.11 -compiler: ghc-9.2.5 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.2.7.yaml b/stack-9.2.7.yaml deleted file mode 100644 index 5af85478d..000000000 --- a/stack-9.2.7.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: lts-20.13 -compiler: ghc-9.2.7 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.2.8.yaml b/stack-9.2.yaml similarity index 71% rename from stack-9.2.8.yaml rename to stack-9.2.yaml index c7cce663b..d49f6ef12 100644 --- a/stack-9.2.8.yaml +++ b/stack-9.2.yaml @@ -1,6 +1,6 @@ resolver: lts-20.26 compiler: ghc-9.2.8 -compiler-check: match-exact +compiler-check: newer-minor packages: - source diff --git a/stack-9.4.3.yaml b/stack-9.4.3.yaml deleted file mode 100644 index 1ae1b347b..000000000 --- a/stack-9.4.3.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: nightly-2022-12-12 -compiler: ghc-9.4.3 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.4.4.yaml b/stack-9.4.4.yaml deleted file mode 100644 index 860d72420..000000000 --- a/stack-9.4.4.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: nightly-2023-03-04 -compiler: ghc-9.4.4 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.4.5.yaml b/stack-9.4.5.yaml deleted file mode 100644 index fa797a6fe..000000000 --- a/stack-9.4.5.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: lts-21.0 -compiler: ghc-9.4.5 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.4.yaml b/stack-9.4.yaml new file mode 100644 index 000000000..ce2490cff --- /dev/null +++ b/stack-9.4.yaml @@ -0,0 +1,7 @@ +resolver: lts-21.25 +compiler: ghc-9.4.8 +compiler-check: newer-minor + +packages: +- source +- testing diff --git a/stack-9.6.2.yaml b/stack-9.6.2.yaml deleted file mode 100644 index 30db7cd58..000000000 --- a/stack-9.6.2.yaml +++ /dev/null @@ -1,7 +0,0 @@ -resolver: nightly-2023-06-26 -compiler: ghc-9.6.2 -compiler-check: match-exact - -packages: -- source -- testing diff --git a/stack-9.6.yaml b/stack-9.6.yaml new file mode 100644 index 000000000..b8505777f --- /dev/null +++ b/stack-9.6.yaml @@ -0,0 +1,7 @@ +resolver: lts-22.39 +compiler: ghc-9.6.6 +compiler-check: newer-minor + +packages: +- source +- testing diff --git a/stack-9.8.yaml b/stack-9.8.yaml new file mode 100644 index 000000000..c83ceff5a --- /dev/null +++ b/stack-9.8.yaml @@ -0,0 +1,11 @@ +resolver: nightly-2024-10-21 +compiler: ghc-9.8.2 +compiler-check: newer-minor + +packages: +- source +- testing + +# extra-deps: +# - aeson-2.2.1.0 +# - th-abstraction-0.6.0.0 diff --git a/testing/bnfc-system-tests.cabal b/testing/bnfc-system-tests.cabal index 25cb87361..6fb569877 100644 --- a/testing/bnfc-system-tests.cabal +++ b/testing/bnfc-system-tests.cabal @@ -14,7 +14,7 @@ name: bnfc-system-tests -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 2.9.5.0 +version: 2.9.6.0 -- A short (one-line) description of the package. synopsis: System tests for BNFC @@ -50,8 +50,11 @@ build-type: Simple cabal-version: >=1.10 tested-with: - GHC == 9.6.2 - GHC == 9.4.5 + GHC == 9.12.0 + GHC == 9.10.1 + GHC == 9.8.2 + GHC == 9.6.6 + GHC == 9.4.8 GHC == 9.2.8 GHC == 9.0.2 GHC == 8.10.7 @@ -87,10 +90,9 @@ executable bnfc-system-tests , HUnit >= 1.2 , shelly >= 1.9 , filepath - -- filepath >= 1.4.2.1 , text - , HTF >= 0.14.0.5 - -- API change in HTF-0.15.0.0 (issue #416) + , HTF >= 0.15.0.0 + -- API change in HTF-0.15 (issue #416) , random , string-qq diff --git a/testing/regression-tests/479_LabelsCaseSensitive/good01.in b/testing/regression-tests/479_LabelsCaseSensitive/good01.in new file mode 100644 index 000000000..27969d2ba --- /dev/null +++ b/testing/regression-tests/479_LabelsCaseSensitive/good01.in @@ -0,0 +1 @@ +2 ^ (2 ** 2) \ No newline at end of file diff --git a/testing/regression-tests/479_LabelsCaseSensitive/good01.out b/testing/regression-tests/479_LabelsCaseSensitive/good01.out new file mode 100644 index 000000000..96ac70f2b --- /dev/null +++ b/testing/regression-tests/479_LabelsCaseSensitive/good01.out @@ -0,0 +1,10 @@ + +Parse Successful! + +[Abstract Syntax] + +Eexp (EInt 2) (EExp (EInt 2) (EInt 2)) + +[Linearized tree] + +2 ^ (2 ** 2) diff --git a/testing/regression-tests/479_LabelsCaseSensitive/test.cf b/testing/regression-tests/479_LabelsCaseSensitive/test.cf new file mode 100644 index 000000000..07062e2b3 --- /dev/null +++ b/testing/regression-tests/479_LabelsCaseSensitive/test.cf @@ -0,0 +1,10 @@ +-- Andreas, 2024-04-23, issue #479: +-- Support case-variants in labels also in the C backend. + +Eexp. Exp ::= Exp "^" Exp1 ; +EExp. Exp ::= Exp "**" Exp1 ; +EInt. Exp1 ::= Integer ; + +coercions Exp 1 ; + +comment "--" ; diff --git a/testing/src/ParameterizedTests.hs b/testing/src/ParameterizedTests.hs index 16215fee7..ce0c945c5 100644 --- a/testing/src/ParameterizedTests.hs +++ b/testing/src/ParameterizedTests.hs @@ -72,11 +72,12 @@ currentRegressionTest :: Test currentRegressionTest = makeTestSuite "Current parameterized test" $ map (`makeTestCase` ("regression-tests" cur)) parameters where + cur = "479_LabelsCaseSensitive" -- cur = "comments" -- cur = "358_MixFixLists" -- cur = "289_LexerKeywords" -- cur = "249_unicode" - cur = "266_define" + -- cur = "266_define" -- cur = "235_SymbolsOverlapTokens" -- cur = "202_comments" -- cur = "278_Keywords" @@ -192,7 +193,8 @@ testCases :: TestParameters -> [Test] testCases params = map (makeTestCase params) $ map ("regression-tests/" ++) $ - [ "266_define" + [ "479_LabelsCaseSensitive" + , "266_define" , "358_MixFixLists" , "235_SymbolsOverlapTokens" , "278_Keywords" @@ -366,7 +368,7 @@ parameters = concat , [ TP { tpName = "C" , tpBnfcOptions = ["--c"] , tpBuild = do - let flags = "CC_OPTS=-Wstrict-prototypes -Werror" + let flags = "CC_OPTS=-Wstrict-prototypes -Wno-sign-compare -Werror" tpMake [flags] tpMake [flags, "Skeleton.o"] , tpRunTestProg = \ lang args -> do