-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Mantle allows you to create an ANTLR grammar file and generate most of the code that will parser users' commands. Your job will to be to write the grammar file and then to implement the specific "visitor" class that defines all the different commands that a user can actually type.
You may use Maven Central to include Mantle in your project. Your final JAR must include Mantle, which you can do using your build tool's shading technology.
Mantle separates platform-agnostic (common) functionality from platform-specific functionality. If you have a one-platform plugin, just include both common and the platform-specific package in your build file. If you have a multi-platform plugin, include common in your corresponding "common" project and include the platform-specific package in your platform-specific packages.
The examples below are written assuming a single-platform project.
For [platform], current options are:
-
common: For all core Mantle functionality. For multi-platform projects, this should be in your "common" equivalent project. For single-platform project, include this in your build file along with the platform-specific dependency. -
bukkit: For bukkit/spigot/paper projects. -
sponge8: For sponge projects using API 8
Latest version: 0.0.0
build.gradle
plugins {
id 'antlr'
id 'com.github.johnrengelman.shadow' version '7.0.0'
}
repositories {
mavenCentral()
}
dependencies {
antlr 'org.antlr:antlr4:4.9.3'
implementation 'me.pietelite.mantle:common:[version]'
implementation 'me.pietelite.mantle:[platform]:[version]'
}
generateGrammarSource {
arguments += ["-visitor", "-lib", "src/main/antlr/path/to/antlr/file/", "-package", "your.project.package"]
}
shadowJar {
relocate 'me.pietelite.mantle', 'your.project.package.libs.mantle'
relocate 'org.antlr', 'your.project.package.libs.antlr'
relocate 'com.vmware.antlr4c3', 'your.project.package.libs.c3' // used for command completion
}
pom.xml: UNTESTED, Gradle is recommended.
<project ...>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>me.pietelite.mantle</pattern>
<shadedPattern>com.yourplugin.libs.mantle</shadedPattern>
</relocation>
<relocation>
<pattern>org.antlr</pattern>
<shadedPattern>com.yourplugin.libs.antlr</shadedPattern>
</relocation>
<relocation>
<pattern>com.vmware.antlr4c3</pattern>
<shadedPattern>com.yourplugin.libs.c3</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.3</version>
<executions>
<execution>
<configuration>
<goals>
<goal>antlr4</goal>
</goals>
<visitor>true</visitor>
<sourceDirectory>src/main/antlr/path/to/antlr/file/</libDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
...
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
...
<dependency>
<groupId>me.pietelite.mantle</groupId>
<artifactId>[platform]</artifactId>
<version>[version]</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.9.3</version>
</dependency>
</dependencies>
</project>
Look here to get a detailed education on ANTLR4; this tutorial will only touch on a few relevant topics.
Start by creating your grammar file in your project at yourproject/src/main/antlr/com/your/artifict/id/PluginName.g4. If your artifact id was net.minecraft, and your project was called Creeper, you may put the file at creeper/src/main/antlr/net/minecraft/Creeper.g4.
The actual file will contain a series of definitions of rules. Each rule basically defines what kind of other rules or "tokens" can come after it, where tokens are just text.
Unless you already know how to use ANTLR, put this at the end of your file:
// MANTLE NODES
identifier: ID | SINGLE_QUOTE ID+ SINGLE_QUOTE | DOUBLE_QUOTE ID+ DOUBLE_QUOTE;
ID: [a-zA-Z0-9\-_]+;
ID_SET: ID (COMMA ID)+;
COMMA: ',';
SINGLE_QUOTE: '\'';
DOUBLE_QUOTE: '"';
WS : [ \t\r\n]+ -> channel(HIDDEN); // skip spaces, tabs, newlines
// END MANTLE NODES
These are good rules and tokens to have for your custom rules and will also setup the ANTLR parsing appropriately. Use the identifier rule wherever there is a custom parameter.
Look at the test module of the project to see what a possible ANTLR file may look like.
Double check that you have included arguments to this task: -visitor -lib src/main/antlr/path/to/antlr/file/ -package your.project.package.
Use the ANTLR build process to "Generate Grammar Source". The generated code should appear in build/generated-src/. Some of the files should be a ...Visitor classes. One is an abstract class and the other is an interface. You may use either.
Implement a Mantle CommandConnector. You can use CommandConnector.builder(). Use the generated lexer and parser to populate those fields in the command connector. Implement your grammar's generated ...Visitor class to return from the executor.
Use the platform-specific command registrar to register your command connector. Then you are done!
Here are examples of projects that use Mantle. The links may become stale.