RPG Parser
This is a parser for the RPG language, both in the fixed and in the free format.
It handles RPGLE (fixed and free format) and DDS, and offers preliminary support for RPG III (RPG/400).
| Dialect | Extensions | Status |
|---|---|---|
| RPG IV (ILE RPG) | rpgle, rpglem, rpgleinc, sqlrpgle | Fully supported, fixed and free format |
| DDS | dds, pf, lf, prtf, dspf | Fully supported |
| RPG III (RPG/400) | rpg, rpg3, rpg38, rpgsrc, sqlrpg | Preliminary |
RPG III members produce the same kind of AST as RPG IV ones. Calculation, file description, extension and input specifications are fully mapped; output specifications are mapped on a best-effort basis; control and line counter specifications are consumed without a representation in the AST. Unsupported constructs produce positioned issues rather than a failure: the parser always attempts to return an AST.
It is intended to be used mainly as a JVM library. It can also be used as a command line tool.
The parser works in three different stages:
- First a list of tokens are created from some input stream (typically a File)
- Then a parse-tree is obtained by grouping the tokens and recognizing structures
- Finally an Abstract Syntax Tree (AST) is derived from the parse-tree. While the AST resembles closely the parse-tree it contains re-arrangements and simplifications that make it easier to work with.
The AST is built using the Kolasu library. This open-source library has been built by Strumenta. This tutorial on Kolasu explains how the library can be used: Building advanced parsers using Kolasu.
The AST can be used to perform analysis on the code or transformations of the code. An example of transformations that can be created is transpilation.
Beyond the core parser, the distribution also includes modules for symbol resolution across a codebase and editor-oriented analysis (dependency graphs, sequence diagrams).
Contents of the package
- Full JAR file with all dependencies
- Windows and Linux scripts to execute the JAR
- Documentation in HTML format
- An example project in Java setup with Gradle that shows how to use the RPG Parser
- An example project in Kotlin setup with Gradle that shows how to use the RPG Parser
How to use the parser
You can use the parser as a library (i.e., from code) or as a standalone program, from the command line.
How to use from the command line
This document describes how to use the RPG parser from the command line. The CLI is implemented in com.strumenta.rpgparser.cli and is distributed as a standalone JAR (rpgparser-<version>-all.jar) together with launcher scripts for Windows and Linux.
Prerequisites
- Java Runtime Environment (JRE) on the classpath. The parser has been tested with JVM 11.
- A valid Strumenta license file for the
parsecommand. Parsing will not run unless a license is registered with--license.
Invoking the CLI
Run the JAR with java -jar:
java -jar rpgparser-<version>-all.jar COMMAND [COMMAND_OPTIONS] [ARGUMENTS...]
Running the JAR without a subcommand prints the top-level help.
Command-name casing
Subcommand names are case-sensitive. Use the exact spelling below:
| Correct name | Common mistake |
|---|---|
downloadlicense | downloadLicense, download-license |
parse | — |
License
Most commands require a commercial license.
Commands that require --license
| Command | Option | Requirement |
|---|---|---|
parse | --license PATH | Required. Path to an existing, readable license file. |
The license path can be passed as --license path/to/file.license or --license=path/to/file.license.
The license file must exist and be readable. Symlinks are accepted.
Commands that do not require a license
| Command | Purpose |
|---|---|
downloadlicense | Download a new license from the Strumenta license service. |
Downloading a license
Use downloadlicense to obtain or refresh a license. Provide your credentials and the destination path:
java -jar rpgparser-<version>-all.jar downloadlicense USERNAME PASSWORD path/to/license.file
On success, the CLI prints confirmation and the license validity period:
License successfully downloaded at path/to/license.file
StartDate: Mon Nov 04 01:00:00 CET 2024
EndDate: Sat Dec 07 01:00:00 CET 2024
Downloaded licenses expire depending on your subscription or contract. Anytime you download a license, it will be downloaded with the updated expiration date.
Commands
parse — parse RPG files
Parses one or more RPG source files (or directories) and writes each AST to a file. Supported extensions are .rpgle, .sqlrpgle, and .dds (case-insensitive). When you pass a file with another extension explicitly, it is treated as RPG LE (.rpgle). When walking directories, files with unrecognized extensions are skipped.
java -jar rpgparser-<version>-all.jar parse --license=my.license [OPTIONS] INPUT [INPUT]...
| Option | Description |
|---|---|
--license PATH | Required. License file. |
-c, --charset TEXT | Charset used to read input files. Default: UTF-8. |
--ignore-positions / --consider-positions | Control whether source positions are included in the AST. Positions are included by default (--consider-positions). |
-f, --format [json|xml] | Output format for serialized ASTs. Default: json. |
-o, --output PATH | Directory where output files are stored. Default: current directory (.). The directory is created if it does not exist. |
-s, --stats | Print statistics on how many files were processed successfully and how many had errors. |
-e, --error-stats | Print statistics on the prevalence of different error messages. |
--no-output | Parse without writing AST files. Useful together with --stats or --error-stats. |
-v, --verbose | Print additional progress messages (including per-file error/warning counts). |
-h, --help | Show command help. |
Arguments
| Argument | Description |
|---|---|
INPUT | Required (at least one). Path to a file or directory. Directories are walked recursively. At least one input must be provided; otherwise the CLI exits with an error. |
Output layout
- For each processed source file, the CLI writes
<output-dir>/<filename>.jsonor<output-dir>/<filename>.xml(for exampleMYPGM.rpglebecomesMYPGM.rpgle.json). - When an input is a directory, the output mirrors the input directory structure under
--output, using the directory name as a subdirectory.
Examples
Parse a single file and write JSON next to the current directory:
java -jar rpgparser-<version>-all.jar parse --license=strumenta.license example.rpgle
Parse multiple inputs into a chosen output directory, with XML output and verbose logging:
java -jar rpgparser-<version>-all.jar parse --license=strumenta.license -f xml -o ./out -v sources/ example.sqlrpgle
Parse a directory and only print processing statistics (no AST files):
java -jar rpgparser-<version>-all.jar parse --license=strumenta.license --no-output --stats ./rpg-sources
Each JSON or XML file contains the AST (root) and any parsing issues.
downloadlicense — download a license
Described in Downloading a license above.
Getting help
Help is available at every level:
# Top-level help and command list
java -jar rpgparser-<version>-all.jar --help
# Help for a specific command
java -jar rpgparser-<version>-all.jar parse --help
java -jar rpgparser-<version>-all.jar downloadlicense --help
Quick reference
| Goal | Command |
|---|---|
| Write AST JSON files | parse --license=… INPUT… |
| Write AST XML files | parse --license=… -f xml -o OUT_DIR INPUT… |
| Parse without writing files | parse --license=… --no-output [--stats] [--error-stats] INPUT… |
| Obtain a license | downloadlicense USER PASS PATH |
How to use as a library
You can use this parser as any other library, directly from your code.
Download a license
You can also download an updated license using the method download license in the LicenseValidation class.
LicenseValidation lv = new LicenseValidation();
lv.downloadLicense("user", "pass", "location.license");
Using a license
This parser requires a license to be used.
You can use LicenseManager to register the license by providing the license file as argument.
You need to register the license once in the program.
import com.strumenta.kolasu.commercial.LicenseManager;
import com.strumenta.rpgparser.RPGKolasuParser;
[..]
LicenseManager.INSTANCE.registerLicense(new File("data/example.license"));
You can then instantiate the parser to parse your RPG code (either as a string or as a file). The simplest approach is to let the parser choose the file type from the extension:
RPGKolasuParser rpgParser = RPGKolasuParser.parserFromExtension(rpgFile);
ParsingResult<CompilationUnit> result = rpgParser.parse(rpgFile);
You can also construct a parser for a specific file type (RPGLE, SQLRPGLE, or DDS):
RPGKolasuParser rpgParser = new RPGKolasuParser(RPGFileType.RPGLE);
ParsingResult<CompilationUnit> result = rpgParser.parse(input);
Consult the cookbook for more examples of uses of the parser.