Skip to content

Commit

Permalink
feat: first version of the KDL 2.0 parser
Browse files Browse the repository at this point in the history
  • Loading branch information
alightgoesout committed Mar 13, 2024
1 parent 26c0783 commit 40c7de0
Show file tree
Hide file tree
Showing 380 changed files with 4,992 additions and 7,330 deletions.
28 changes: 14 additions & 14 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

name: Gradle CI

on:
push:
branches: [ trunk ]
branches:
- trunk
pull_request:
branches: [ trunk ]
branches:
- trunk

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: gradle build
- uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
distribution: temurin
java-version: 11
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Build with Gradle
run: ./gradlew build
38 changes: 0 additions & 38 deletions .github/workflows/release.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Copyright 2022 Hannah Kolbeck
Copyright 2024 Romain Delamare

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
Expand All @@ -12,4 +13,3 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

70 changes: 25 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,47 @@
# KDL4j
# KDL4j v2

A Java implementation of a parser for the [KDL Document Language](https://github.com/kdl-org/kdl).
A Java implementation of a parser for the [KDL Document Language](https://github.com/kdl-org/kdl). Supports KDL
version `2.0.0-draft.4`.

This library targets Java 11 as a minimum version.

## Status

![Gradle CI](https://github.com/hkolbeck/kdl4j/workflows/Gradle%20CI/badge.svg)

This project is beta-quality. It's been extensively tested, but the spec it implements is still in flux.

## Usage

### Parsing

```java
final KDLParser parser = new KDLParser();

final KDLDocument documentFromString = parser.parse("node_name \"arg\"")
// OR
final KDLDocument documentFromReader = parser.parse(new FileReader("some/file.kdl"))
import kdl.parse.KDLParser;

// Parse from a String
var documentFromString = KDLParser.parse("node_name \"arg\"");
// Parse from an InputStream
var documentFromReader = KDLParser.parse(new ByteArrayInputStream(/**/));
// Parse from a file
var documentFromReader = KDLParser.parse(Paths.get("path", "to", "file"));
```

`KDLDocument` objects, and all descendants of `KDLObject`, are immutable and threadsafe, though that is not true of their
`Builder` objects. If you need to make changes to a `KDLDocument`, use the `filter()` and `mutate()` functions explained below.

### Searching and Mutating Documents

Several utilities are provided for finding nodes in documents. Each presents the same interface, but the way they search
the document differs. There are three search types:

* RootSearch - Searches entirely at the root, primarily used for mutations to the root as discussed below
* GeneralSearch - Searches for nodes anywhere in the tree matching a single, possibly compound, node predicate
* PathedSearch - Searches for nodes down a specified path. At each level a different node predicate can be specified

Each provides four methods for searching or mutating documents:

* `anyMatch(document)` - Returns true if any node matches the search, false otherwise
* `filter(document, trim)` - Removes all nodes from the tree not on a branch that matches the predicates of the search. if
`trim` is set, removes all their non-matching children
* `list(document, trim)` - Produces a new document with all matching nodes at the root. If `trim` is set, removes all
their non-matching children
* `mutate(document, mutation)` - Applies a provided `Mutation` to every matching node in the tree, depth first.

There are 3 types of `Mutations` provided, and users may provide custom mutations. Provided are `AddMutation`,
`SubtractMutation`, and `SetMutation`. Each performs functions hinted at by the name. See individual javadocs for details.

### Printing

By default, calling `document.toKDL()` or `document.writeKDL(writer)` will print the structure with:
* 4 space indents
* No semicolons
* Printable ASCII characters which can be escaped, escaped
* Empty children printed
* `null` arguments and properties with `null` values printed
* `\n` (unicode `\u{0a}`) for newlines
The `KDLPrinter` class allows printing a KDL document to a `String`, a `Writer`, an `OutputStream` or to a file. By
default, it:

- prints one character tabulation for each indentation level
- does not print node separators (`;`)
- does not print braces for nodes without children
- prints arguments and properties with null value
- uses `E` as the exponent character in decimal values

Any of these can be changed by creating a new PrintConfig object and passing it into the print method. See the javadocs
on PrintConfig for more information.
Any of these can be changed by creating a `PrintConfiguration` and passing it to the `KDLPrinter` constructor.

## Contributing

Please read the Code of Conduct before opening any issues or pull requests.

Besides code fixes, the easiest way to contribute is by generating test cases. Check out
[the test cases directory](https://github.com/hkolbeck/kdl4j/tree/trunk/src/test/resources/test_cases) to see the existing ones.
Besides code fixes, the easiest way to contribute is by generating test cases. Check out
[the test cases directory](src/test/resources/test_cases) to see the
existing ones.
See the README there for more details.
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ java {
}
}

tasks.compileJava {
options.javaModuleVersion = provider { version as String }
}

tasks.test {
useJUnitPlatform()
finalizedBy(tasks.jacocoTestReport)
Expand All @@ -55,6 +59,8 @@ tasks.jacocoTestReport {
val mockitoVersion = "5.10.0"

dependencies {
implementation("jakarta.annotation:jakarta.annotation-api:2.1.1")

testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testImplementation("org.assertj:assertj-core:3.25.3")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=0.3.0
version=2.0.0.beta-1
16 changes: 0 additions & 16 deletions src/main/java/kdl/Fuzzer.java

This file was deleted.

42 changes: 42 additions & 0 deletions src/main/java/kdl/KDLBoolean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package kdl;

import jakarta.annotation.Nonnull;
import java.util.Objects;
import java.util.Optional;

/**
* A KDL boolean value.
*/
public class KDLBoolean extends KDLValue<Boolean> {
/**
* Creates a new {@link KDLBoolean}.
*
* @param type the type of the value
* @param value the value
*/
public KDLBoolean(@Nonnull Optional<String> type, boolean value) {
super(type);
this.value = value;
}

@Nonnull
@Override
public Boolean getValue() {
return value;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
var that = (KDLBoolean) o;
return value == that.value && Objects.equals(type, that.type);
}

@Override
public int hashCode() {
return Objects.hash(value, type);
}

private final boolean value;
}
52 changes: 52 additions & 0 deletions src/main/java/kdl/KDLDocument.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package kdl;

import jakarta.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* A KDL document.
*/
public class KDLDocument {
/**
* Creates a new document
*
* @param nodes the nodes in the document
*/
public KDLDocument(@Nonnull List<KDLNode> nodes) {
this.nodes = Collections.unmodifiableList(nodes);
}

/**
* The nodes of the document.
*
* @return an immutable list containing the nodes of the document
*/
@Nonnull
public List<KDLNode> getNodes() {
return nodes;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
var that = (KDLDocument) o;
return Objects.equals(nodes, that.nodes);
}

@Override
public int hashCode() {
return Objects.hash(nodes);
}

@Override
public String toString() {
return "KDLDocument[" + nodes.stream().map(KDLNode::toString).collect(Collectors.joining(", ")) + ']';
}

@Nonnull
private final List<KDLNode> nodes;
}
Loading

0 comments on commit 40c7de0

Please sign in to comment.