diff --git a/muscript/src/main/java/io/gitlab/jfronny/muscript/StarScriptIngester.java b/muscript/src/main/java/io/gitlab/jfronny/muscript/StarScriptIngester.java new file mode 100644 index 0000000..de8f1a7 --- /dev/null +++ b/muscript/src/main/java/io/gitlab/jfronny/muscript/StarScriptIngester.java @@ -0,0 +1,90 @@ +package io.gitlab.jfronny.muscript; + +import io.gitlab.jfronny.commons.log.*; + +import java.util.*; +import java.util.stream.*; + +public class StarScriptIngester { + private static final Logger LOGGER = Logger.forName("MuScript"); + /** Naive conversion of starscript syntax to muscript */ + public static String starScriptToMu(String source) { + StringBuilder result = new StringBuilder(); + StringBuilder currbuf = new StringBuilder(); + State state = State.Surrounding; + for (char c : source.toCharArray()) { + switch (state) { + case Surrounding -> { + if (c == '{') { + if (!currbuf.isEmpty()) { + if (!result.isEmpty()) result.append(" || "); + result.append(enquote(currbuf.toString())); + } + currbuf = new StringBuilder(); + state = State.UnquotedInner; + } else currbuf.append(c); + } + case UnquotedInner -> { + switch (c) { + case '}' -> { + if (!currbuf.isEmpty()) { + if (!result.isEmpty()) result.append(" || "); + result.append("(").append(currbuf).append(")"); + } + currbuf = new StringBuilder(); + state = State.Surrounding; + } + case '\'' -> { + currbuf.append(c); + state = State.SingleQuoteInner; + } + case '"' -> { + currbuf.append(c); + state = State.DoubleQuoteInner; + } + default -> currbuf.append(c); + } + } + case SingleQuoteInner -> { + currbuf.append(c); + if (c == '\'') state = State.UnquotedInner; + } + case DoubleQuoteInner -> { + currbuf.append(c); + if (c == '"') state = State.UnquotedInner; + } + } + } + if (!currbuf.isEmpty() && !result.isEmpty()) result.append(" || "); + switch (state) { + case Surrounding -> { + if (!currbuf.isEmpty()) result.append(enquote(currbuf.toString())); + } + case UnquotedInner -> { + LOGGER.warn("Starscript code segment improperly closed, closing automatically"); + if (!currbuf.isEmpty()) result.append("(").append(currbuf).append(")"); + } + case SingleQuoteInner -> { + LOGGER.warn("Quote in starscript swallows ending, completing with closing quote"); + if (!currbuf.isEmpty()) result.append("(").append(currbuf).append("')"); + } + case DoubleQuoteInner -> { + LOGGER.warn("Quote in starscript swallows ending, completing with closing quote"); + if (!currbuf.isEmpty()) result.append("(").append(currbuf).append("\")"); + } + } + return result.toString(); + } + + /** Creates quotes around a string, supports strings containing quotes */ + private static String enquote(String literalText) { + if (!literalText.contains("'")) return "'" + literalText + "'"; + if (!literalText.contains("\"")) return "\"" + literalText + "\""; + return Arrays.stream(literalText.split("'")).map(s -> "'" + s + "'") + .collect(Collectors.joining(" || \"'\" || ")); + } + + enum State { + Surrounding, UnquotedInner, SingleQuoteInner, DoubleQuoteInner + } +} diff --git a/muscript/src/test/java/io/gitlab/jfronny/muscript/test/StarScriptIngesterTest.java b/muscript/src/test/java/io/gitlab/jfronny/muscript/test/StarScriptIngesterTest.java new file mode 100644 index 0000000..469e733 --- /dev/null +++ b/muscript/src/test/java/io/gitlab/jfronny/muscript/test/StarScriptIngesterTest.java @@ -0,0 +1,15 @@ +package io.gitlab.jfronny.muscript.test; + +import io.gitlab.jfronny.muscript.*; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class StarScriptIngesterTest { + @Test + void ingestionTest() { + assertEquals("'Hello ' || (name) || '!'", StarScriptIngester.starScriptToMu("Hello {name}!")); + assertEquals("('Only \"Content')", StarScriptIngester.starScriptToMu("{'Only \"Content'}")); + assertEquals("(a + c / 75) || ' equals ' || (b)", StarScriptIngester.starScriptToMu("{a + c / 75} equals {b}")); + } +}