SAS Parser
This is a parser for the SAS language.
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 makes easier working with it.
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 could be used to perform analysis on the code or transformations of the code.
An example of transformations that can be created is transpilation.
Contents of the package
- Full JAR file with all dependencies
- Windows e Linux scripts to execute the JAR
- Documentation in HTML format
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 SAS parser from the command line. The CLI is implemented in com.strumenta.sas.parser.Main and is distributed as a standalone 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. Serialization issues have been reported with JVM 16 and later.
- A valid Strumenta license file for all parsing commands (
parse,jsonast, andmodel). Parsing will not run unless a license is registered with--license.
Invoking the CLI
Run the JAR with java -jar:
java -jar sas-parser-with-dependencies-<version>-all.jar [GLOBAL_OPTIONS] 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 |
|---|---|
jsonast | jsonAst, jsonAST, JsonAst |
downloadlicense | downloadLicense, download-license |
parse | — |
model | — |
metamodel | — |
Global options
These options apply to the parser configuration and must be placed before the subcommand name:
| Option | Description |
|---|---|
--parse-native-sql | When set, native SQL fragments embedded in SAS code are parsed during post-processing. Off by default. |
--report-error-nodes | When set, ErrorNode instances in the AST are reported as semantic issues. Enabled by default; the flag is present mainly for explicit documentation of the behavior. |
-h, --help | Show top-level help. |
Example:
java -jar sas-parser-with-dependencies-<version>-all.jar --parse-native-sql parse --license=my.license example.sas
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. |
jsonast | --license PATH | Required. |
model | --license PATH | Required. |
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. |
metamodel | Generate the EMF metamodel for the SAS AST (no parsing of user SAS files). |
Downloading a license
Use downloadlicense to obtain or refresh a license. Provide your credentials and the destination path:
java -jar sas-parser-with-dependencies-<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 a single file to stdout
Parses one SAS file and writes the parsing result to standard output.
java -jar sas-parser-with-dependencies-<version>-all.jar parse --license=my.license [OPTIONS] FILE
| Option | Description |
|---|---|
--license PATH | Required. License file. |
-f, --format [json] | Output format. Only json is available (default). |
-h, --help | Show command help. |
Arguments
| Argument | Description |
|---|---|
FILE | Required. Path to a single .sas file. Must exist, be a regular file, and be readable. |
Example
java -jar sas-parser-with-dependencies-<version>-all.jar parse --license=strumenta.license examples.sas
The JSON output on stdout contains the AST (root) and any parsing issues.
jsonast — export AST as JSON files
Parses one or more SAS files or directories and writes one JSON file per input file.
java -jar sas-parser-with-dependencies-<version>-all.jar jsonast --license=my.license [OPTIONS] [INPUTS]... [OUTPUT]
| 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. |
-v, --verbose | Print additional progress messages. |
-h, --help | Show command help. |
Arguments
| Argument | Description |
|---|---|
INPUTS | One or more files or directories to parse. When omitted, behavior depends on the remaining arguments (see below). |
OUTPUT | Optional output directory (not a file). Defaults to the current working directory. The directory is created if it does not exist. |
Output layout
- Single file input: writes
<output-dir>/<basename-without-.sas>.json. - Directory input: recursively walks the directory tree. Only files whose name ends with
.sas(case-insensitive) are processed. The output mirrors the input directory structure underOUTPUT/<input-directory-name>/.
Example
java -jar sas-parser-with-dependencies-<version>-all.jar jsonast --license=strumenta.license examples.sas .
model — export AST as EMF models
Parses input files and saves each AST as an EMF model (JSON or XMI), together with a metamodel description.
java -jar sas-parser-with-dependencies-<version>-all.jar model --license=my.license [OPTIONS] [INPUTS]...
| 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 appear in the AST. |
-v, --verbose | Print additional progress messages. |
--metamodel PATH | Path to an existing metamodel file to reuse. When omitted, a metamodel is generated next to each output file as metamodel.json or metamodel.xmi. |
-o, --output PATH | Output directory. Default: current directory (.). |
-imm, --include-metamodel | Embed the metamodel inside each saved model file. Off by default. |
--xmi | Save models as .xmi instead of .json. Off by default. |
-h, --help | Show command help. |
Arguments
| Argument | Description |
|---|---|
INPUTS | One or more SAS files or directories to parse (same conventions as jsonast). |
Output layout
For each input file, the CLI writes a model file under --output, preserving the relative path of the input. The file extension is .json by default, or .xmi when --xmi is set. A metamodel file is saved alongside the model unless --metamodel points to an existing one.
Example
java -jar sas-parser-with-dependencies-<version>-all.jar model --license=strumenta.license -o ./out --verbose myprogram.sas
metamodel — generate the AST metamodel
Generates the EMF metamodel for the SAS language. This command does not parse user SAS code and does not require a license.
java -jar sas-parser-with-dependencies-<version>-all.jar metamodel [OPTIONS]
| Option | Description |
|---|---|
-o, --output PATH | File where the metamodel is stored. |
-ik, --include-kolasu | Include Kolasu types in the exported metamodel. |
-v, --verbose | Print additional progress messages. |
-h, --help | Show command help. |
Example
java -jar sas-parser-with-dependencies-<version>-all.jar metamodel -o build/metamodel/SAS.xmi -v
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 sas-parser-with-dependencies-<version>-all.jar --help
# Help for a specific command
java -jar sas-parser-with-dependencies-<version>-all.jar parse --help
java -jar sas-parser-with-dependencies-<version>-all.jar jsonast --help
java -jar sas-parser-with-dependencies-<version>-all.jar model --help
java -jar sas-parser-with-dependencies-<version>-all.jar metamodel --help
java -jar sas-parser-with-dependencies-<version>-all.jar downloadLicense --help
Quick reference
| Goal | Command |
|---|---|
| Print AST JSON on stdout | parse --license=… FILE |
| Write AST JSON files to a directory | jsonast --license=… INPUT [OUTPUT_DIR] |
| Write EMF model files | model --license=… -o OUT_DIR INPUT… |
| Generate the language metamodel | metamodel -o PATH |
| Obtain a license | downloadLicense USER PASS PATH |
| Parse embedded native SQL | Add --parse-native-sql before the subcommand |
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 the static method registerLicense to register the license by providing the license file as argument.
You need to register the license once in the program.
import com.strumenta.sas.parser.SASLanguage;
[..]
SASLanguage.Companion.registerLicense(new File("data/example.license"));
You can then instantiate the parser to parse your SAS code (either as a string or as a file).
SASLanguage sasLanguage = new SASLanguage();
sasLanguage.parse(input);
Consult the cookbook for more examples of uses of the parser.