From 231d139277919eb042e6b9115d239a3168233496 Mon Sep 17 00:00:00 2001
From: Stoney Jackson <dr.stoney@gmail.com>
Date: Sun, 28 Apr 2024 17:49:58 +0000
Subject: [PATCH] refactor!: convert plcc.py to python package plcc

BREAKING CHANGE:

plcc is now a Python package, and plcc.py has been removed.
So plcc.py can no longer be called directly like this

    python3 path/to/plcc.py grammar

Instead, use plcc like this

    plcc grammar

---

This commit restructures the PLCC codebase into that of a
conventional Python project. This should make it easier to
redesign the internal structure of PLCC, making it easier to
maintain and add new functionality. It should also help us
prepare to distribute PLCC through PyPI, making it easier
to install. Here is a summary of changes.

- Convert plcc.py into python package plcc
- Remove environment variable LIBPLCC
- Move src/Std/ under src/plcc (the PLCC Python package)
- Move lib/jackson under src/plcc (the PLCC Python package)
- Pull common functionality of scripts into common.bash

---

Related Issues

- Related to #119
- Closes #121
- Closes #120
---
 .gitpod.yml                                   |   6 +--
 .reuse/dep5                                   |   4 +-
 README.md                                     |   5 +-
 containers/configurable/Dockerfile            |   2 +-
 containers/plcc/Dockerfile                    |   2 +-
 installers/plcc/env.bash                      |   7 +--
 installers/plcc/install.bash                  |   4 +-
 src/parse                                     |  49 -----------------
 src/plcc                                      |  12 -----
 src/{langs => plcc}/__init__.py               |   0
 src/{plcc.py => plcc/__main__.py}             |  28 +++++-----
 src/plcc/bin/common.bash                      |  47 ++++++++++++++++
 src/plcc/bin/parse                            |  28 ++++++++++
 src/plcc/bin/plcc                             |   4 ++
 src/plcc/bin/plccmk                           |  18 +++++++
 src/plcc/bin/rep                              |   5 ++
 src/plcc/bin/scan                             |   5 ++
 src/{langs => plcc}/java.py                   |   0
 src/{ => plcc/lib}/Std/ILazy.java             |   0
 src/{ => plcc/lib}/Std/IMatch.java            |   0
 src/{ => plcc/lib}/Std/IScan.java             |   0
 src/{ => plcc/lib}/Std/ITrace.java            |   0
 src/{ => plcc/lib}/Std/PLCCException.java     |   0
 src/{ => plcc/lib}/Std/Parse.java             |   0
 src/{ => plcc/lib}/Std/ParseJsonAst.java      |   0
 src/{ => plcc/lib}/Std/ProcessFiles.java      |   0
 src/{ => plcc/lib}/Std/Rep.java               |   0
 src/{ => plcc/lib}/Std/Scan.java              |   0
 src/{ => plcc/lib}/Std/Token.pattern          |   0
 src/{ => plcc/lib}/Std/Token.template         |   0
 src/{ => plcc/lib}/Std/Trace.java             |   0
 .../jackson/jackson-annotations-2.15.2.jar    | Bin
 .../plcc/lib}/jackson/jackson-core-2.15.2.jar | Bin
 .../lib}/jackson/jackson-databind-2.15.2.jar  | Bin
 src/{langs => plcc}/python.py                 |   0
 src/{ => plcc}/version.py                     |   0
 src/plccmk                                    |  51 ------------------
 src/rep                                       |  20 -------
 src/scan                                      |  21 --------
 tests/parse/parses.bats                       |  21 --------
 tests/parse/parses/given-grammar.plcc         |   6 +++
 tests/parse/parses/given-program.lang         |   1 +
 tests/parse/parses/parses.bats                |  10 ++++
 43 files changed, 151 insertions(+), 205 deletions(-)
 delete mode 100755 src/parse
 delete mode 100755 src/plcc
 rename src/{langs => plcc}/__init__.py (100%)
 rename src/{plcc.py => plcc/__main__.py} (98%)
 create mode 100644 src/plcc/bin/common.bash
 create mode 100755 src/plcc/bin/parse
 create mode 100755 src/plcc/bin/plcc
 create mode 100755 src/plcc/bin/plccmk
 create mode 100755 src/plcc/bin/rep
 create mode 100755 src/plcc/bin/scan
 rename src/{langs => plcc}/java.py (100%)
 rename src/{ => plcc/lib}/Std/ILazy.java (100%)
 rename src/{ => plcc/lib}/Std/IMatch.java (100%)
 rename src/{ => plcc/lib}/Std/IScan.java (100%)
 rename src/{ => plcc/lib}/Std/ITrace.java (100%)
 rename src/{ => plcc/lib}/Std/PLCCException.java (100%)
 rename src/{ => plcc/lib}/Std/Parse.java (100%)
 rename src/{ => plcc/lib}/Std/ParseJsonAst.java (100%)
 rename src/{ => plcc/lib}/Std/ProcessFiles.java (100%)
 rename src/{ => plcc/lib}/Std/Rep.java (100%)
 rename src/{ => plcc/lib}/Std/Scan.java (100%)
 rename src/{ => plcc/lib}/Std/Token.pattern (100%)
 rename src/{ => plcc/lib}/Std/Token.template (100%)
 rename src/{ => plcc/lib}/Std/Trace.java (100%)
 rename {lib => src/plcc/lib}/jackson/jackson-annotations-2.15.2.jar (100%)
 rename {lib => src/plcc/lib}/jackson/jackson-core-2.15.2.jar (100%)
 rename {lib => src/plcc/lib}/jackson/jackson-databind-2.15.2.jar (100%)
 rename src/{langs => plcc}/python.py (100%)
 rename src/{ => plcc}/version.py (100%)
 delete mode 100755 src/plccmk
 delete mode 100755 src/rep
 delete mode 100755 src/scan
 delete mode 100644 tests/parse/parses.bats
 create mode 100644 tests/parse/parses/given-grammar.plcc
 create mode 100644 tests/parse/parses/given-program.lang
 create mode 100644 tests/parse/parses/parses.bats

diff --git a/.gitpod.yml b/.gitpod.yml
index d7ea8948..6d057627 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -7,10 +7,8 @@ tasks:
       echo "INSTALLING latest JAVA (a PLCC dependency)"
       sdk install java < /dev/null
       echo ""
-      echo "INSTALLING PLCC in $GITPOD_REPO_ROOT/src"
-      echo 'export LIBPLCC="$GITPOD_REPO_ROOT/src"
-      export PATH="$LIBPLCC:$PATH"
-      ' >> "$HOME/.bashrc"
+      echo "INSTALLING PLCC from source"
+      echo 'export PATH="$GITPOD_REPO_ROOT/src/plcc/bin:$PATH"' >> "$HOME/.bashrc"
       echo ""
       echo "INSTALLING reuse (for licenses: https://reuse.software/)"
       pip install --upgrade pip
diff --git a/.reuse/dep5 b/.reuse/dep5
index 0afb804b..1598e8e2 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -15,6 +15,6 @@ Copyright:
   Copyright (C) 2023  PLCC Community <https://discord.gg/EVtNSxS9E2>
 License: GPL-3.0-or-later
 
-Files: lib/jackson/*
+Files: plcc/lib/jackson/*
 Copyright: Copyright 2007-, Tatu Saloranta (tatu.saloranta@iki.fi)
-License: Apache-2.0
\ No newline at end of file
+License: Apache-2.0
diff --git a/README.md b/README.md
index 8bd19851..4b5739f6 100644
--- a/README.md
+++ b/README.md
@@ -47,8 +47,9 @@ image: gitpod/workspace-full:latest
 tasks:
   - name: Install PLCC
     command: |
-        /bin/bash -c "$(\curl -fsSL https://github.com/ourPLCC/plcc/raw/main/installers/plcc/install.bash)" \
-          >> ~/.bashrc
+        /bin/bash -c "$(\
+          \curl -fsSL https://github.com/ourPLCC/plcc/raw/main/installers/plcc/install.bash \
+        )" >> ~/.bashrc
         exec bash
 ```
 
diff --git a/containers/configurable/Dockerfile b/containers/configurable/Dockerfile
index 4a1ee76b..67c77eda 100644
--- a/containers/configurable/Dockerfile
+++ b/containers/configurable/Dockerfile
@@ -45,4 +45,4 @@ RUN bash -c 'curl -s https://get.sdkman.io | bash'
 RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && sdk install java $JAVA_VERSION"
 
 COPY --chown=$USERNAME:$USERNAME . $HOME/.plcc
-ENV PATH="$HOME/.plcc/src:${PATH}" LIBPLCC="$HOME/.plcc/src"
+ENV PATH="$HOME/.plcc/src/plcc/bin:${PATH}"
diff --git a/containers/plcc/Dockerfile b/containers/plcc/Dockerfile
index cc99ffcc..904a6f91 100644
--- a/containers/plcc/Dockerfile
+++ b/containers/plcc/Dockerfile
@@ -28,7 +28,7 @@ RUN addgroup -S my && adduser -S my -G my
 
 # Copy over plcc from downloader stage.
 COPY --chown=plcc:plcc . /plcc
-ENV PATH="/plcc/src:${PATH}" LIBPLCC="/plcc/src"
+ENV PATH="/plcc/src/plcc/bin:${PATH}"
 
 # Change user to dev.
 WORKDIR /workdir
diff --git a/installers/plcc/env.bash b/installers/plcc/env.bash
index 7e895f8b..5a0cc613 100755
--- a/installers/plcc/env.bash
+++ b/installers/plcc/env.bash
@@ -1,9 +1,10 @@
 #!/usr/bin/env bash
+PLCC_DIR="$(dirname -- "${BASH_SOURCE[0]}" )/../.."
+PLCC_DIR="$(cd -- "${PLCC_DIR}" &> /dev/null && pwd)"
 
 echo "
-export LIBPLCC=\"${HOME}/.local/lib/plcc/src\"
-export PATH=\"\${LIBPLCC}:\$PATH\"
+export PATH=\"${PLCC_DIR}/src/plcc/bin:\$PATH\"
 function plcc-con() {
     docker run --rm -it -v \"\$PWD:/workdir\" --user \"\$(id -u):\$(id -g)\" ghcr.io/ourplcc/plcc:latest \"\$@\"
 }
-"
\ No newline at end of file
+"
diff --git a/installers/plcc/install.bash b/installers/plcc/install.bash
index 93de9aa8..cc0e388d 100755
--- a/installers/plcc/install.bash
+++ b/installers/plcc/install.bash
@@ -3,6 +3,6 @@
 set -euo pipefail
 
 PLCC_HOME="${HOME}/.local/lib/plcc"
-git clone https://github.com/ourPLCC/plcc.git "${PLCC_HOME}"
+git clone -b "${PLCC_GIT_BRANCH:-main}" https://github.com/ourPLCC/plcc.git "${PLCC_HOME}"
 echo "# Add the following line to the end of your .bashrc or .zshrc"
-"${PLCC_HOME}/installers/plcc/rchook.bash"
\ No newline at end of file
+"${PLCC_HOME}/installers/plcc/rchook.bash"
diff --git a/src/parse b/src/parse
deleted file mode 100755
index 9aa29cb1..00000000
--- a/src/parse
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-JACKSON_VERSION="2.15.2"
-LIBPLCC_LIB="$(cd -- "${LIBPLCC}/.." &> /dev/null ; pwd)"
-JACKSON_ANNOTATIONS="${LIBPLCC_LIB}/lib/jackson/jackson-annotations-${JACKSON_VERSION}.jar"
-JACKSON_CORE="${LIBPLCC_LIB}/lib/jackson/jackson-core-${JACKSON_VERSION}.jar"
-JACKSON_DATABIND="${LIBPLCC_LIB}/lib/jackson/jackson-databind-${JACKSON_VERSION}.jar"
-CP="${JACKSON_ANNOTATIONS}:${JACKSON_CORE}:${JACKSON_DATABIND}"
-
-if [[ -z "${CLASSPATH:-}" ]] ; then
-    CLASSPATH="./Java:${CP}"
-    export CLASSPATH
-else
-    CLASSPATH="./Java:${CLASSPATH}:${CP}"
-fi
-
-[ -d Java ] || {
-    echo "Java directory missing" >&2
-    exit 1
-}
-
-[ -f Java/Parse.class ] || {
-    echo "Java/Parse.class missing" >&2
-    exit 2
-}
-
-if  echo "$*" | grep -- "--json_ast" &> /dev/null
-then
-
-    ARGS=()
-    while [ $# -gt 0 ] ; do
-        case "$1" in
-            --json_ast)
-                shift
-            ;;
-            *)
-                ARGS+=("$1")
-                shift
-            ;;
-        esac
-    done
-
-    if ! java ParseJsonAst "${ARGS[@]}" ; then
-        >&2 echo "Did you forget to pass --json_ast to plccmk?"
-        exit 1
-    fi
-else
-    java Parse $*
-fi
diff --git a/src/plcc b/src/plcc
deleted file mode 100755
index bd59c3ed..00000000
--- a/src/plcc
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-LIB="${LIBPLCC:-/home/fossumtv/PL/src}"
-PYTHON3=python3
-PLCC="$LIB/plcc.py"
-
-[ -d "$LIB" ] || {
-        echo "$LIB: no such directory" >&2
-        exit 1
-}
-
-$PYTHON3 "$PLCC" "$@"
diff --git a/src/langs/__init__.py b/src/plcc/__init__.py
similarity index 100%
rename from src/langs/__init__.py
rename to src/plcc/__init__.py
diff --git a/src/plcc.py b/src/plcc/__main__.py
similarity index 98%
rename from src/plcc.py
rename to src/plcc/__main__.py
index fb747268..f3667e0b 100644
--- a/src/plcc.py
+++ b/src/plcc/__main__.py
@@ -21,12 +21,13 @@
 import sys
 import re
 import os
+import pathlib
 import io
 import shutil
 import tempfile
 
-from langs.java import spec as java_spec
-from langs.python import spec as python_spec
+from plcc.java import spec as java_spec
+from plcc.python import spec as python_spec
 
 argv = sys.argv[1:] # skip over the command-line argument
 
@@ -72,10 +73,7 @@ def debug2(msg):
     debug(msg, level=2)
 
 def LIBPLCC():
-    try:
-        return os.environ['LIBPLCC']
-    except KeyError:
-        death("undefined LIBPLCC environment variable -- quitting")
+    return str(pathlib.Path(__file__).parent)
 
 def main():
     global argv
@@ -108,8 +106,8 @@ def main():
 
     # Handle --version option.
     if 'version' in flags and flags['version']:
-        import version
-        print(version.get_version())
+        import plcc.version
+        print(plcc.version.get_version())
         sys.exit(0)
 
     jsonAstInit()
@@ -257,7 +255,7 @@ def lexFinishUp():
     if not dst:
         death('illegal destdir flag value')
     try:
-        os.mkdir(dst)
+        os.mkdir(str(dst))
         debug('[lexFinishUp] ' + dst + ': destination subdirectory created')
     except FileExistsError:
         debug('[lexFinishUp] ' + dst + ': destination subdirectory exists')
@@ -267,15 +265,13 @@ def lexFinishUp():
     if not getFlag('Token'):
         return # do not create any automatically generated scanner-related files
     libplcc = getFlag('libplcc')
-    if not libplcc:
-        death('illegal libplcc flag value')
-    std = libplcc + '/Std'
+    std = pathlib.Path(libplcc) / 'lib' / 'Std'
     try:
-        os.mkdir(std)
+        os.mkdir(str(std))
     except FileExistsError:
         pass
     except:
-        death(std + ': cannot access directory')
+        death(str(std) + ': cannot access directory')
     fname = '{}/{}'.format(dst, 'Token.java')
     try:
         tokenFile = open(fname, 'w')
@@ -392,7 +388,7 @@ def parFinishUp():
     # copy the Std parser-related files
     dst = getFlag('destdir')
     libplcc = getFlag('libplcc')
-    std = libplcc + '/Std'
+    std = pathlib.Path(libplcc) / 'lib' / 'Std'
     for fname in STDP:
         if getFlag(fname):
             debug('[parFinishUp] copying {} from {} to {} ...'.format(fname, std, dst))
@@ -891,7 +887,7 @@ def semFinishUp(stubs, destFlag='destdir', ext='.java'):
     if not dst:
         death('illegal destdir flag value')
     try:
-        os.mkdir(dst)
+        os.mkdir(str(dst))
         debug('[semFinishUp] ' + dst + ': destination subdirectory created')
     except FileExistsError:
         debug('[semFinishUp] ' + dst + ': destination subdirectory exists')
diff --git a/src/plcc/bin/common.bash b/src/plcc/bin/common.bash
new file mode 100644
index 00000000..34b3ebe3
--- /dev/null
+++ b/src/plcc/bin/common.bash
@@ -0,0 +1,47 @@
+
+init() {
+    set -euo pipefail
+    if is_first_call_to_init ; then return 0 ; fi
+    define_PLCC_DIR
+    update_PYTHONPATH
+    update_CLASSPATH
+}
+
+is_first_call_to_init() {
+    if [[ -n "${PLCC_FIRST_CALL_TO_INIT:-}" ]] ; then
+        return 0
+    else
+        PLCC_FIRST_CALL_TO_INIT='false'
+        export PLCC_FIRST_CALL_TO_INIT
+        return 1
+    fi
+}
+
+define_PLCC_DIR() {
+    PLCC_DIR="$( abspath "$( dirname -- "${BASH_SOURCE[0]}" )/../.." )"
+    export PLCC_DIR
+}
+
+update_PYTHONPATH() {
+    PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${PLCC_DIR}"
+    export PYTHONPATH
+}
+
+update_CLASSPATH() {
+    JACKSON_VERSION="2.15.2"
+    JACKSON_ANNOTATIONS="${PLCC_DIR}/plcc/lib/jackson/jackson-annotations-${JACKSON_VERSION}.jar"
+    JACKSON_CORE="${PLCC_DIR}/plcc/lib/jackson/jackson-core-${JACKSON_VERSION}.jar"
+    JACKSON_DATABIND="${PLCC_DIR}/plcc/lib/jackson/jackson-databind-${JACKSON_VERSION}.jar"
+    CP="./Java:${JACKSON_ANNOTATIONS}:${JACKSON_CORE}:${JACKSON_DATABIND}"
+    CLASSPATH="${CLASSPATH:+${CLASSPATH}:}${CP}"
+    export CLASSPATH
+}
+
+abspath() { echo "$( cd -- "${1}" &> /dev/null && pwd )" ; }
+
+assert_file_exists (){
+    [ -f "${1}" ] || {
+        echo "${1} missing" >&2
+        exit 2
+    }
+}
diff --git a/src/plcc/bin/parse b/src/plcc/bin/parse
new file mode 100755
index 00000000..69a79b85
--- /dev/null
+++ b/src/plcc/bin/parse
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+source "$(dirname -- "${BASH_SOURCE[0]}" )/common.bash" && init
+
+assert_file_exists Java/Parse.class
+
+if  echo "$*" | grep -- "--json_ast" &> /dev/null
+then
+
+    ARGS=()
+    while [ $# -gt 0 ] ; do
+        case "$1" in
+            --json_ast)
+                shift
+            ;;
+            *)
+                ARGS+=("$1")
+                shift
+            ;;
+        esac
+    done
+
+    if ! java ParseJsonAst "${ARGS[@]}" ; then
+        >&2 echo "Did you forget to pass --json_ast to plccmk?"
+        exit 1
+    fi
+else
+    java Parse "$@"
+fi
diff --git a/src/plcc/bin/plcc b/src/plcc/bin/plcc
new file mode 100755
index 00000000..e7e6f083
--- /dev/null
+++ b/src/plcc/bin/plcc
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+source "$(dirname -- "${BASH_SOURCE[0]}" )/common.bash" && init
+
+python3 -m plcc "$@"
diff --git a/src/plcc/bin/plccmk b/src/plcc/bin/plccmk
new file mode 100755
index 00000000..979a2935
--- /dev/null
+++ b/src/plcc/bin/plccmk
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+source "$(dirname -- "${BASH_SOURCE[0]}" )/common.bash" && init
+
+if [[ "${1:-}" == "-c" ]]
+then
+        rm -f Java/*.java Java/*.class
+        shift
+fi
+
+if [ $# -eq 0 ]
+then
+        DEFAULT=spec
+        [ -f "$DEFAULT" ] || DEFAULT=grammar
+        set - $DEFAULT
+fi
+
+plcc "$@"
+(cd ./Java ; javac *.java)
diff --git a/src/plcc/bin/rep b/src/plcc/bin/rep
new file mode 100755
index 00000000..983c4ccb
--- /dev/null
+++ b/src/plcc/bin/rep
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+source "$(dirname -- "${BASH_SOURCE[0]}" )/common.bash" && init
+
+assert_file_exists Java/Rep.class
+java Rep "$@"
diff --git a/src/plcc/bin/scan b/src/plcc/bin/scan
new file mode 100755
index 00000000..72c0d066
--- /dev/null
+++ b/src/plcc/bin/scan
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+source "$(dirname -- "${BASH_SOURCE[0]}" )/common.bash" && init
+
+assert_file_exists Java/Scan.class
+java Scan
diff --git a/src/langs/java.py b/src/plcc/java.py
similarity index 100%
rename from src/langs/java.py
rename to src/plcc/java.py
diff --git a/src/Std/ILazy.java b/src/plcc/lib/Std/ILazy.java
similarity index 100%
rename from src/Std/ILazy.java
rename to src/plcc/lib/Std/ILazy.java
diff --git a/src/Std/IMatch.java b/src/plcc/lib/Std/IMatch.java
similarity index 100%
rename from src/Std/IMatch.java
rename to src/plcc/lib/Std/IMatch.java
diff --git a/src/Std/IScan.java b/src/plcc/lib/Std/IScan.java
similarity index 100%
rename from src/Std/IScan.java
rename to src/plcc/lib/Std/IScan.java
diff --git a/src/Std/ITrace.java b/src/plcc/lib/Std/ITrace.java
similarity index 100%
rename from src/Std/ITrace.java
rename to src/plcc/lib/Std/ITrace.java
diff --git a/src/Std/PLCCException.java b/src/plcc/lib/Std/PLCCException.java
similarity index 100%
rename from src/Std/PLCCException.java
rename to src/plcc/lib/Std/PLCCException.java
diff --git a/src/Std/Parse.java b/src/plcc/lib/Std/Parse.java
similarity index 100%
rename from src/Std/Parse.java
rename to src/plcc/lib/Std/Parse.java
diff --git a/src/Std/ParseJsonAst.java b/src/plcc/lib/Std/ParseJsonAst.java
similarity index 100%
rename from src/Std/ParseJsonAst.java
rename to src/plcc/lib/Std/ParseJsonAst.java
diff --git a/src/Std/ProcessFiles.java b/src/plcc/lib/Std/ProcessFiles.java
similarity index 100%
rename from src/Std/ProcessFiles.java
rename to src/plcc/lib/Std/ProcessFiles.java
diff --git a/src/Std/Rep.java b/src/plcc/lib/Std/Rep.java
similarity index 100%
rename from src/Std/Rep.java
rename to src/plcc/lib/Std/Rep.java
diff --git a/src/Std/Scan.java b/src/plcc/lib/Std/Scan.java
similarity index 100%
rename from src/Std/Scan.java
rename to src/plcc/lib/Std/Scan.java
diff --git a/src/Std/Token.pattern b/src/plcc/lib/Std/Token.pattern
similarity index 100%
rename from src/Std/Token.pattern
rename to src/plcc/lib/Std/Token.pattern
diff --git a/src/Std/Token.template b/src/plcc/lib/Std/Token.template
similarity index 100%
rename from src/Std/Token.template
rename to src/plcc/lib/Std/Token.template
diff --git a/src/Std/Trace.java b/src/plcc/lib/Std/Trace.java
similarity index 100%
rename from src/Std/Trace.java
rename to src/plcc/lib/Std/Trace.java
diff --git a/lib/jackson/jackson-annotations-2.15.2.jar b/src/plcc/lib/jackson/jackson-annotations-2.15.2.jar
similarity index 100%
rename from lib/jackson/jackson-annotations-2.15.2.jar
rename to src/plcc/lib/jackson/jackson-annotations-2.15.2.jar
diff --git a/lib/jackson/jackson-core-2.15.2.jar b/src/plcc/lib/jackson/jackson-core-2.15.2.jar
similarity index 100%
rename from lib/jackson/jackson-core-2.15.2.jar
rename to src/plcc/lib/jackson/jackson-core-2.15.2.jar
diff --git a/lib/jackson/jackson-databind-2.15.2.jar b/src/plcc/lib/jackson/jackson-databind-2.15.2.jar
similarity index 100%
rename from lib/jackson/jackson-databind-2.15.2.jar
rename to src/plcc/lib/jackson/jackson-databind-2.15.2.jar
diff --git a/src/langs/python.py b/src/plcc/python.py
similarity index 100%
rename from src/langs/python.py
rename to src/plcc/python.py
diff --git a/src/version.py b/src/plcc/version.py
similarity index 100%
rename from src/version.py
rename to src/plcc/version.py
diff --git a/src/plccmk b/src/plccmk
deleted file mode 100755
index 29786849..00000000
--- a/src/plccmk
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-
-LIB="${LIBPLCC:-/usr/local/pub/plcc/PLCC}"
-PYTHON3=python3
-PLCC="$LIB/plcc.py"
-
-JACKSON_VERSION="2.15.2"
-LIBPLCC_LIB="$(cd -- "${LIBPLCC}/.." &> /dev/null ; pwd)"
-JACKSON_ANNOTATIONS="${LIBPLCC_LIB}/lib/jackson/jackson-annotations-${JACKSON_VERSION}.jar"
-JACKSON_CORE="${LIBPLCC_LIB}/lib/jackson/jackson-core-${JACKSON_VERSION}.jar"
-JACKSON_DATABIND="${LIBPLCC_LIB}/lib/jackson/jackson-databind-${JACKSON_VERSION}.jar"
-CP="${JACKSON_ANNOTATIONS}:${JACKSON_CORE}:${JACKSON_DATABIND}"
-
-if [[ -z "${CLASSPATH:-}" ]] ; then
-        CLASSPATH="${CP}"
-        export CLASSPATH
-else
-        CLASSPATH="${CLASSPATH}:${CP}"
-fi
-
-if [ "$1" = "-c" ];
-then
-        rm Java/*.java Java/*.class &>/dev/null
-        shift
-fi
-
-if [ $# -gt 0 ];
-then
-        FILES="$@"
-else
-        DEFAULT=spec
-        [ -f "$DEFAULT" ] || DEFAULT=grammar
-        FILES="${FILE:-$DEFAULT}"
-fi
-
-[ -d "$LIB" ] || {
-        echo "$LIB: no such directory" >&2
-        exit 1
-}
-
-$PYTHON3 "$PLCC" $FILES || {
-        echo "cannot compile $FILES" >&2
-        exit 4
-}
-
-[ -d Java ] || {
-        echo "Java directory missing" >&2
-        exit 5
-}
-
-(cd ./Java ; javac *.java)
diff --git a/src/rep b/src/rep
deleted file mode 100755
index 13eb3a5a..00000000
--- a/src/rep
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-if [[ -z "${CLASSPATH:-}" ]] ; then
-    CLASSPATH="./Java"
-    export CLASSPATH
-else
-    CLASSPATH="./Java:${CLASSPATH}"
-fi
-
-[ -d "${PWD}/Java" ] || {
-    echo "Java directory missing" >&2
-    exit 1
-}
-
-[ -f "${PWD}/Java/Rep.class" ] || {
-    echo "Java/Rep.class missing" >&2
-    exit 2
-}
-
-java Rep $*
diff --git a/src/scan b/src/scan
deleted file mode 100755
index 3397323b..00000000
--- a/src/scan
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-if [[ -z "${CLASSPATH:-}" ]] ; then
-    CLASSPATH="./Java"
-    export CLASSPATH
-else
-    CLASSPATH="./Java:${CLASSPATH}"
-fi
-
-
-[ -d Java ] || {
-    echo "Java directory missing" >&2
-    exit 1
-}
-
-[ -f Java/Scan.class ] || {
-    echo "Java/Scan.class missing" >&2
-    exit 2
-}
-
-java Scan
diff --git a/tests/parse/parses.bats b/tests/parse/parses.bats
deleted file mode 100644
index 98ed6ba0..00000000
--- a/tests/parse/parses.bats
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bats
-
-load '../relocate_to_temp.bash'
-
-@test "PLCC parses." {
-  relocate_to_temp
-
-  cat << EOF > grammar
-A 'A'
-B 'B'
-skip OTHER '.'
-%
-<p> ::= <aaa> B
-<aaa> **= A
-EOF
-
-  RESULT="$(plccmk -c grammar > /dev/null && echo "A asdf A fdsa A B" | parse -n)"
-
-  echo "RESULT: $RESULT"
-  [[ "$RESULT" =~ .*OK.* ]]
-}
diff --git a/tests/parse/parses/given-grammar.plcc b/tests/parse/parses/given-grammar.plcc
new file mode 100644
index 00000000..efd6f02a
--- /dev/null
+++ b/tests/parse/parses/given-grammar.plcc
@@ -0,0 +1,6 @@
+A 'A'
+B 'B'
+skip OTHER '.'
+%
+<p> ::= <aaa> B
+<aaa> **= A
diff --git a/tests/parse/parses/given-program.lang b/tests/parse/parses/given-program.lang
new file mode 100644
index 00000000..738cbf82
--- /dev/null
+++ b/tests/parse/parses/given-program.lang
@@ -0,0 +1 @@
+A asdf A fdsa A B
diff --git a/tests/parse/parses/parses.bats b/tests/parse/parses/parses.bats
new file mode 100644
index 00000000..a1877009
--- /dev/null
+++ b/tests/parse/parses/parses.bats
@@ -0,0 +1,10 @@
+#!/usr/bin/env bats
+
+load '../../relocate_to_temp.bash'
+
+@test "PLCC parses." {
+  relocate_to_temp
+
+  plccmk -c given-grammar.plcc
+  # parse -n < given-program.lang
+}