Skip to main content

How to Parse RPG Code

This is the most basic of examples: it shows how to parse some RPG code into a CompilationUnit.

Add Dependencies

repositories {
mavenLocal()
mavenCentral()
flatDir {
dirs("deps")
}
}

dependencies {
implementation(files("deps/rpgparser-2.2.0-all.jar"))
}

Parse a file

Create an RPGKolasuParser from the file extension (or with an explicit RPGFileType), register your license, and call parse. The root of a successful parse is a CompilationUnit.

import com.strumenta.kolasu.commercial.LicenseManager
import com.strumenta.kolasu.parsing.ParsingResult
import com.strumenta.rpgparser.RPGKolasuParser
import com.strumenta.rpgparser.model.CompilationUnit
import com.strumenta.rpgparser.model.DataStructure
import com.strumenta.rpgparser.model.StandaloneField
import java.io.File

fun processRPGFile(rpgFile: File, license: File) {
println("== Processing RPG file ${rpgFile.path} ==\n")
if (!rpgFile.exists() || !rpgFile.isFile) {
println("File not found or not a file, skipping")
return
}

LicenseManager.registerLicense(license)
val parser = RPGKolasuParser.parserFromExtension(rpgFile)
val result: ParsingResult<CompilationUnit> = parser.parse(rpgFile)

if (result.issues.isNotEmpty()) {
println("Issues in file: ${result.issues.size}")
for (issue in result.issues) {
println(" - $issue")
}
}

val cu = result.root
if (cu == null) {
println("Compilation unit not built, skipping")
return
}

if (cu.dataDefinitions.isEmpty()) {
println("No data definitions")
} else {
println("Data definitions: ${cu.dataDefinitions.size}")
for (dd in cu.dataDefinitions) {
when (dd) {
is StandaloneField -> println(" - standalone field ${dd.name}")
is DataStructure -> {
val name = dd.name ?: "unnamed @ line ${dd.position?.start?.line}"
println(" - data structure $name")
}
else -> println(" - $dd")
}
}
}

println("Procedures: ${cu.procedures.size}")
cu.procedures.forEach { println(" - ${it.name}") }

println("Subroutines: ${cu.subroutines.size}")
cu.subroutines.forEach { println(" - ${it.name}") }
}

You can use the method we just created very easily.

fun main() {
processRPGFile(
File("examples/QRPGLESRC/MYPGM.rpgle"),
File("licenses/strumenta.license")
)
}

Choose a file type explicitly

parserFromExtension covers the common case. To parse DDS, SQLRPGLE, or RPG III sources when the extension is ambiguous, construct the parser with an explicit type:

val ddsParser = RPGKolasuParser(RPGFileType.DDS)
val sqlParser = RPGKolasuParser(RPGFileType.SQLRPGLE)
val rpg3Parser = RPGKolasuParser(RPGFileType.RPG3)

Free-format RPGLE is detected automatically when the source starts with **FREE.