An OpenRewrite language module for Pascal. Enables lossless semantic tree (LST) parsing, round-trip printing, visitor-based analysis, and recipe-driven refactoring of Pascal source code.
This project exists to bring the Moderne platform's tooling - Prethink for AI-assisted code comprehension, TriGrep for structural search, and OpenRewrite recipes for automated refactoring - to Pascal codebases.
The immediate goal is to support analysis of two Free Pascal projects:
- Asuro OS - a hobby operating system written in Free Pascal (~660 source files, ~100K lines)
- Wasuro - a WebAssembly virtual machine, also in Free Pascal
- The parser handles pure Pascal syntax and successfully parses 659 of 660 files in the Asuro codebase with full round-trip fidelity (the remaining file uses an unsupported Free Pascal extension)
- The
rewrite-pascal-generatormodule produces Moderne-compatible V2 LST artifacts that the Moderne CLI (mod run) accepts - Prethink runs against the generated LSTs, though its built-in discovery recipes are Java/JS-focused - Pascal-specific discovery recipes (unit dependency graphs, procedure signatures, record types) are a planned next step
The parser currently supports pure Pascal syntax (ISO 7185 / Turbo Pascal style). It does not yet support Delphi or ObjFPC language extensions such as:
- Classes and objects (
class,object,interfaceas OOP construct) - Generics (
TList<T>) - Anonymous methods and closures
- Advanced RTTI and attributes
- Operator overloading
try/except/finallyexception handling- String interpolation
Support for Free Pascal's {$mode objfpc} and {$mode delphi} extensions is planned for future phases. Compiler directives are parsed and preserved but not interpreted.
- Programs and units with
usesclauses,interface/implementationsections - Declarations:
var,const,typesections - Types: records (packed/bitpacked), enums, sets, arrays, pointers, variant records, subranges
- Procedures and functions with parameters (
var,const,out), local declarations, nested routines - Control flow:
if/then/else,for/to/downto,while/do,repeat/until,case/of,with - Expressions: arithmetic, comparison, boolean, bitwise (
shl/shr/xor), field access, indexing, type casts, set values - Comments:
{ },(* *),//line comments - Compiler directives:
{$mode},{$H+}, etc. - Inline assembly blocks (
asm ... end)
All whitespace and comments are preserved in the LST for lossless round-trip fidelity.
| Module | Description |
|---|---|
rewrite-pascal |
Core language module: parser, printer, visitor, and LST node definitions |
rewrite-pascal-remote |
Remote serialization support (Sender/Receiver/Validator) for distributed LST processing |
rewrite-pascal-generator |
Standalone tool to parse Pascal projects and produce Moderne-compatible LST artifacts |
Requires Java 17+ and uses Gradle 8.12 (wrapper included).
./gradlew buildRun tests:
./gradlew testThe rewrite-pascal-generator module produces Moderne-compatible .ast.jar artifacts from Pascal source trees. It requires the Moderne CLI to be installed (for its bundled Java 25 runtime and serialization library).
# Build the generator fat JAR
./gradlew :rewrite-pascal-generator:fatJar
# Run it against a Pascal project (use ; as classpath separator on Windows, : on Linux/macOS)
~/.moderne/cli/dist/jre/bin/java \
-cp "rewrite-pascal-generator/build/libs/*-all.jar;~/.moderne/cli/dist/lib/moderne-cli.jar" \
org.openrewrite.pascal.generator.PascalLstGenerator /path/to/pascal/projectThe output is written to /path/to/pascal/project/.moderne/build/ as a V2-format LST artifact. This artifact can then be used with mod run to execute OpenRewrite recipes:
mod run /path/to/pascal/project --recipe=<RecipeName>import org.openrewrite.pascal.PascalParser;
import org.openrewrite.SourceFile;
PascalParser parser = PascalParser.builder().build();
Stream<SourceFile> trees = parser.parse(
"""
program Hello;
begin
WriteLn('Hello, World!');
end.
"""
);The LST reuses the Java tree infrastructure (Pas extends J) following the same pattern as rewrite-python. This means:
PascalVisitorextendsJavaVisitor- Java-based visitors can traverse Pascal trees- Padding types (
JLeftPadded,JRightPadded,JContainer) preserve whitespace - The
Markerssystem stores keyword casing and other source-level metadata
The parser is a hand-written recursive descent parser with a custom lexer - no external parser generator dependency.
- OpenRewrite BOM 8.45.0 (
rewrite-core,rewrite-java) rewrite-remote0.28.0 (for the remote module)- Lombok 1.18.34 (compile-only)
- JUnit 5.11.4 (test)
This project was built in part with the assistance of AI (Claude Opus 4.6). The development workflow followed a tight feedback loop:
- Write or generate parser code for a Pascal construct
- Compile and run the test suite
- Analyze failures by comparing printed output against the original source
- Fix the parser or printer and repeat
This loop is a natural fit for OpenRewrite's lossless parsing model. The correctness criterion is simple and absolute - the printed output of a parsed file must be identical to the original input, byte for byte. There is no ambiguity about whether the parser is correct: either the round-trip produces the exact original source (including all whitespace, comments, and casing), or it doesn't. That binary signal made it straightforward for AI to identify what was wrong, propose a fix, and verify it in the next iteration.