All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.leeonky.interpreter.Rules Maven / Gradle / Ivy

The newest version!
package com.github.leeonky.interpreter;

import com.github.leeonky.interpreter.Syntax.CompositeSyntax;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import static com.github.leeonky.util.function.When.when;
import static java.lang.String.format;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.joining;

public class Rules {
    public static , P extends Procedure, PA extends Parser,
            MA extends Parser.Mandatory, T, R, A> Function,
            Syntax> endWith(Predicate

isClose, Supplier message) { return syntax -> new CompositeSyntax(syntax) { private boolean closed; @Override protected void close(P procedure) { if (!closed) throw procedure.getSourceCode().syntaxError(message.get(), 0); } @Override protected boolean isClose(P procedure) { return closed = isClose.test(procedure); } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endWith(Notation notation) { return syntax -> new EndWith<>(syntax, notation); } @SafeVarargs public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endBefore(Notation... notations) { return syntax -> new EndBefore<>(syntax, notations); } public static , O extends Operator, P extends Procedure, E extends Expression, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endWith(String closing) { return syntax -> new CompositeSyntax( syntax.and(Rules.endWith(Notation.notation(closing)))) { @Override public boolean isClose(P procedure) { return !procedure.getSourceCode().hasCode() || procedure.getSourceCode().startsWith(closing); } }; } public static , O extends Operator, P extends Procedure, E extends Expression, PA extends Parser, MA extends Parser.Mandatory, T, R extends MapAble, A> Function, Syntax> endWithPosition(String closing) { return syntax -> new CompositeSyntax(syntax.and(Rules.endWith(closing))) { @Override protected R parse(Syntax syntax, Function factory) { return super.parse(syntax, factory).map(n -> n.setPositionBegin(getToken().getPosition())); } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endBefore(String label) { return syntax -> new EndBeforeString<>(syntax, label); } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endWithLine() { return EndWithLine::new; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> splitBy(Notation notation) { return syntax -> new CompositeSyntax(syntax) { @Override public boolean isSplitter(P procedure) { return procedure.getSourceCode().popWord(notation).isPresent(); } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endWithOptionalLine() { return syntax -> new CompositeSyntax(syntax.and(Rules.endWithLine())) { @Override public void close(P procedure) { } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> optionalSplitBy(Notation splitter) { return syntax -> new CompositeSyntax(syntax) { @Override public boolean isSplitter(P procedure) { procedure.getSourceCode().popWord(splitter); return true; } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> mandatorySplitBy(Notation splitter) { return syntax -> new CompositeSyntax(syntax) { @Override public boolean isSplitter(P procedure) { if (procedure.getSourceCode().popWord(splitter).isPresent()) return true; throw procedure.getSourceCode().syntaxError(format("Should end with `%s`", splitter.getLabel()), 0); } }; } @SuppressWarnings("unchecked") public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax, List>> atLeast(int size) { return syntax -> new CompositeSyntax, List>( (Syntax, List>) syntax) { @Override protected NodeParser parse(Syntax, List> syntax, Function, N> factory) { return procedure -> procedure.getSourceCode().tryFetch(() -> { List list = parser.apply(procedure, syntax); return when(list.size() >= size).optional(() -> factory.apply(list)); }); } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, A> Function, A>, Syntax, A>> enabledBefore(Notation notation) { return syntax -> new CompositeSyntax, A>(syntax) { @Override protected NodeParser parse(Syntax, A> syntax, Function factory) { NodeParser nodeParser = super.parse(syntax, factory); return procedure -> procedure.getSourceCode().tryFetch(() -> nodeParser.parse(procedure).map(node -> procedure.getSourceCode().startsWith(notation) ? node : null)); } }; } public static , P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> Function, Syntax> endOfRow(Notation splitter) { return syntax -> new EndOFRow<>(syntax, splitter); } private static class EndOFRow, P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> extends CompositeSyntax { private final Notation splitter; private boolean isClose; public EndOFRow(Syntax syntax, Notation splitter) { super(syntax); this.splitter = splitter; isClose = false; } @Override public boolean isClose(P procedure) { return isClose = endOfLineOrNoCode(procedure.getSourceCode()) || hasNewLineBeforeSplitter(procedure.getSourceCode()); } private boolean hasNewLineBeforeSplitter(SourceCode sourceCode) { String code = sourceCode.codeBefore(splitter); return code.contains("\r") || code.contains("\n"); } private boolean endOfLineOrNoCode(SourceCode sourceCode) { if (sourceCode.isEndOfLine() || !sourceCode.hasCode()) { if (sourceCode.hasCode()) sourceCode.popChar(Collections.emptyMap()); return true; } return false; } @Override public void close(P procedure) { if (!isClose) throw procedure.getSourceCode().syntaxError("unexpected token", 0); } } private static class EndWithLine, P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> extends CompositeSyntax { private boolean isClose; public EndWithLine(Syntax syntax) { super(syntax); isClose = false; } @Override public boolean isClose(P procedure) { isClose = procedure.getSourceCode().isEndOfLine(); if (isClose && procedure.getSourceCode().hasCode()) procedure.getSourceCode().popChar(Collections.emptyMap()); return isClose; } @Override public void close(P procedure) { if (!isClose) throw procedure.getSourceCode().syntaxError("unexpected token", 0); } } private static class EndWith, P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> extends CompositeSyntax { private final Notation notation; public EndWith(Syntax syntax, Notation notation) { super(syntax); this.notation = notation; } @Override public void close(P procedure) { setToken(procedure.getSourceCode().popWord(notation).orElseThrow(() -> procedure.getSourceCode().syntaxError("Should end with " + quote(notation.getLabel()), 0))); } @Override public boolean isClose(P procedure) { return procedure.getSourceCode().startsWith(notation) || !procedure.getSourceCode().hasCode(); } } private static class EndBefore, P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> extends CompositeSyntax { private final Notation[] notations; private boolean closed; @SafeVarargs public EndBefore(Syntax syntax, Notation... notations) { super(syntax); this.notations = notations; closed = false; } @Override public void close(P procedure) { if (!closed) throw procedure.getSourceCode().syntaxError( "Should end with " + stream(notations).map(Notation::getLabel).collect(joining("`", "`", "` or `")), 0); } @Override public boolean isClose(P procedure) { return closed = stream(notations).anyMatch(procedure.getSourceCode()::startsWith); } } private static class EndBeforeString, P extends Procedure, PA extends Parser, MA extends Parser.Mandatory, T, R, A> extends CompositeSyntax { private final String label; private boolean closed; public EndBeforeString(Syntax syntax, String label) { super(syntax); this.label = label; } @Override public void close(P procedure) { if (!closed) throw procedure.getSourceCode().syntaxError("Should end with " + quote(label), 0); } @Override public boolean isClose(P procedure) { return !procedure.getSourceCode().hasCode() || (closed = procedure.getSourceCode().startsWith(label)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy