Skip to content

Commit

Permalink
add a very basic abnf reader
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastian-toepfer committed Nov 15, 2023
1 parent f42a59a commit a0ec2aa
Show file tree
Hide file tree
Showing 36 changed files with 2,968 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* The MIT License
*
* Copyright 2023 sebastian.
*
* 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 rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE 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.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader;

import io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.RuleList;

public interface ABNF {
RuleList rules();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* The MIT License
*
* Copyright 2023 sebastian.
*
* 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 rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE 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.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader;

import static io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader.UsefulCodepoints.SOLIDUS;

import io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.element.Alternative;
import io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.element.Element;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

class AlternativeExtractor implements Extractor, ExtractorOwner {

static Extractor of(
final ExtractorOwner owner,
final Element element,
final ElementEndDetector endOfElementDelimiter
) {
return new AlternativeExtractor(owner, List.of(element), endOfElementDelimiter, RepetitionExtractor::of);
}

private final ExtractorOwner owner;
private final List<Element> elements;
private final ElementEndDetector endOfElementDetector;
private final Function<AlternativeExtractor, Extractor> newElement;

private AlternativeExtractor(
final ExtractorOwner owner,
final Collection<Element> elements,
final ElementEndDetector endOfElementDelimiter,
final Function<AlternativeExtractor, Extractor> newElement
) {
this.owner = Objects.requireNonNull(owner);
this.elements = List.copyOf(elements);
this.endOfElementDetector = Objects.requireNonNull(endOfElementDelimiter);
this.newElement = Objects.requireNonNull(newElement);
}

@Override
public Extractor append(final int codePoint) {
final Extractor result;
final ElementEndDetector currentEndOfElementDetector = endOfElementDetector.append(codePoint);
if (currentEndOfElementDetector.isEndReached()) {
result = currentEndOfElementDetector.applyTo(owner.imDone(asCreator()));
} else if (Character.isWhitespace(codePoint)) {
result = new AlternativeExtractor(owner, elements, currentEndOfElementDetector, newElement);
} else if (codePoint == SOLIDUS) {
result = new AlternativeExtractor(owner, elements, currentEndOfElementDetector, RepetitionExtractor::of);
} else {
result = newElement.apply(this).append(codePoint);
}
return result;
}

@Override
public Extractor imDone(final Creator creator) {
final Collection<Element> newElements = new ArrayList<>(elements);
newElements.add(creator.createAs(Element.class));
return new AlternativeExtractor(owner, newElements, endOfElementDetector, p -> owner.imDone(p.asCreator()));
}

@Override
public Creator finish() {
return owner.imDone(asCreator()).finish();
}

private Creator asCreator() {
return new Creator() {
@Override
public <T> T createAs(final Class<T> cls) {
return cls.cast(Alternative.of(elements));
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* The MIT License
*
* Copyright 2023 sebastian.
*
* 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 rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE 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.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader;

import static io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader.UsefulCodepoints.QUOTATION_MARK;

import io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.element.StringElement;
import java.util.Objects;

class CharValExtractor implements Extractor {

static Extractor of(final ExtractorOwner owner) {
return new CharValExtractor(owner, "");
}

private final ExtractorOwner owner;
private final String value;

private CharValExtractor(final ExtractorOwner owner, final String value) {
this.owner = Objects.requireNonNull(owner);
this.value = Objects.requireNonNull(value);
}

@Override
public Extractor append(final int codePoint) {
final Extractor result;
if (codePoint == QUOTATION_MARK) {
result = owner.imDone(asCreator());
} else {
result = new CharValExtractor(owner, value.concat(Character.toString(codePoint)));
}
return result;
}

private Creator asCreator() {
return new Creator() {
@Override
public <T> T createAs(final Class<T> cls) {
return cls.cast(StringElement.of(value));
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* The MIT License
*
* Copyright 2023 sebastian.
*
* 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 rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE 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.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader;

class CodePointBasedElementEndDelimiter implements ElementEndDetector {

private final int stop;
private final boolean reachStop;

CodePointBasedElementEndDelimiter(final int stop) {
this(stop, false);
}

private CodePointBasedElementEndDelimiter(final int stop, final boolean reachStop) {
this.stop = stop;
this.reachStop = reachStop;
}

@Override
public ElementEndDetector append(final int codePoint) {
return new CodePointBasedElementEndDelimiter(stop, codePoint == stop);
}

@Override
public boolean isEndReached() {
return reachStop;
}

@Override
public Extractor applyTo(final Extractor imDone) {
return imDone.append(stop);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* The MIT License
*
* Copyright 2023 sebastian.
*
* 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 rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE 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.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader;

import static io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader.UsefulCodepoints.SOLIDUS;

import io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.element.Concatenation;
import io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.element.Element;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

class ConcatenationExtractor implements Extractor, ExtractorOwner {

static Extractor of(final ExtractorOwner owner) {
return new ConcatenationExtractor(owner, List.of(), new NewLineDetector());
}

static Extractor of(final ExtractorOwner owner, final int stop) {
return new ConcatenationExtractor(owner, List.of(), new CodePointBasedElementEndDelimiter(stop));
}

private final ExtractorOwner owner;
private final List<Element> elements;
private final ElementEndDetector endOfElementDelimiter;

private ConcatenationExtractor(
final ExtractorOwner owner,
final Collection<Element> elements,
final ElementEndDetector endOfElementDelimiter
) {
this.owner = Objects.requireNonNull(owner);
this.elements = List.copyOf(elements);
this.endOfElementDelimiter = endOfElementDelimiter;
}

@Override
public Extractor append(final int codePoint) {
final Extractor result;
final ElementEndDetector currentEndOfElementDetector = endOfElementDelimiter.append(codePoint);
if (currentEndOfElementDetector.isEndReached()) {
result = currentEndOfElementDetector.applyTo(owner.imDone(asCreator()));
} else if (Character.isWhitespace(codePoint)) {
result = new ConcatenationExtractor(owner, elements, currentEndOfElementDetector);
} else if (codePoint == SOLIDUS) {
final List<Element> newElements = new ArrayList<>(elements);
final Element element = newElements.remove(newElements.size() - 1);
result =
AlternativeExtractor.of(
new ConcatenationExtractor(owner, newElements, currentEndOfElementDetector),
element,
currentEndOfElementDetector
);
} else {
result = RepetitionExtractor.of(this).append(codePoint);
}
return result;
}

@Override
public Creator finish() {
return owner.imDone(asCreator()).finish();
}

private Creator asCreator() {
return new Creator() {
@Override
public <T> T createAs(final Class<T> cls) {
final Element result;
if (elements.size() == 1) {
result = elements.iterator().next();
} else {
result = Concatenation.of(elements);
}
return cls.cast(result);
}
};
}

@Override
public Extractor imDone(final Creator creator) {
final Collection<Element> newElements = new ArrayList<>(elements);
newElements.add(creator.createAs(Element.class));
return new ConcatenationExtractor(owner, newElements, endOfElementDelimiter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* The MIT License
*
* Copyright 2023 sebastian.
*
* 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 rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE 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.
*/
package io.github.sebastiantoepfer.jsonschema.vocabulary.format.assertion.abnf.reader;

interface Creator {
<T> T createAs(Class<T> cls);
}
Loading

0 comments on commit a0ec2aa

Please sign in to comment.