Fix parser
authorLanius Trolling <lanius@laniustrolling.dev>
Mon, 7 Nov 2022 22:32:52 +0000 (17:32 -0500)
committerLanius Trolling <lanius@laniustrolling.dev>
Mon, 7 Nov 2022 22:32:52 +0000 (17:32 -0500)
src/main/kotlin/info/mechyrdia/lore/parser.kt

index f8bce6928041541457d9449b8661e74824fcc551..8737a05f6e0e63bc582a9629f7036a2cd178787d 100644 (file)
@@ -1,7 +1,6 @@
 package info.mechyrdia.lore
 
 data class TextParserScope<TContext>(
-       var buffer: String = "",
        val write: Appendable,
        val tags: TextParserTags<TContext>,
        val ctx: TContext
@@ -9,27 +8,24 @@ data class TextParserScope<TContext>(
 
 sealed class TextParserState<TContext>(
        val scope: TextParserScope<TContext>,
-       val insideTags: List<Pair<TextParserTagType.Indirect<TContext>, String?>>,
+       val insideTags: List<Pair<String, String?>>,
        val insideDirectTags: List<String>
 ) {
        abstract fun processCharacter(char: Char): TextParserState<TContext>
        abstract fun processEndOfText()
        
        protected fun appendText(text: String) {
-               scope.buffer += censorText(text)
-       }
-       
-       protected fun appendTextRaw(text: String) {
-               scope.buffer += text
-       }
-       
-       protected fun flushBuffer() {
                scope.write.append(
-                       insideTags.foldRight(scope.buffer) { (tag, param), t ->
-                               tag.process(param, t, scope.ctx)
+                       insideTags.foldRight(censorText(text)) { (tag, param), t ->
+                               (scope.tags[tag] as? TextParserTagType.Indirect<TContext>)
+                                       ?.process(param, t, scope.ctx)
+                                       ?: "[$tag${param?.let { "=$it" } ?: ""}]$t[/$tag]"
                        }
                )
-               scope.buffer = ""
+       }
+       
+       protected fun appendTextRaw(text: String) {
+               scope.write.append(text)
        }
        
        class Initial<TContext>(scope: TextParserScope<TContext>) : TextParserState<TContext>(scope, listOf(), listOf()) {
@@ -45,7 +41,7 @@ sealed class TextParserState<TContext>(
                }
        }
        
-       class PlainText<TContext>(scope: TextParserScope<TContext>, val text: String, insideTags: List<Pair<TextParserTagType.Indirect<TContext>, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
+       class PlainText<TContext>(scope: TextParserScope<TContext>, val text: String, insideTags: List<Pair<String, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
                override fun processCharacter(char: Char): TextParserState<TContext> {
                        return if (char == '[') {
                                appendText(text)
@@ -66,11 +62,10 @@ sealed class TextParserState<TContext>(
                
                override fun processEndOfText() {
                        appendText(text)
-                       flushBuffer()
                }
        }
        
-       class NoFormatText<TContext>(scope: TextParserScope<TContext>, val text: String, insideTags: List<Pair<TextParserTagType.Indirect<TContext>, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
+       class NoFormatText<TContext>(scope: TextParserScope<TContext>, val text: String, insideTags: List<Pair<String, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
                override fun processCharacter(char: Char): TextParserState<TContext> {
                        val newText = text + char
                        return if (newText.endsWith("[/$NO_FORMAT_TAG]")) {
@@ -86,11 +81,10 @@ sealed class TextParserState<TContext>(
                
                override fun processEndOfText() {
                        appendText(text)
-                       flushBuffer()
                }
        }
        
-       class OpenTag<TContext>(scope: TextParserScope<TContext>, val tag: String, insideTags: List<Pair<TextParserTagType.Indirect<TContext>, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
+       class OpenTag<TContext>(scope: TextParserScope<TContext>, val tag: String, insideTags: List<Pair<String, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
                override fun processCharacter(char: Char): TextParserState<TContext> {
                        return if (char == ']') {
                                if (tag.equals(NO_FORMAT_TAG, ignoreCase = true))
@@ -99,19 +93,10 @@ sealed class TextParserState<TContext>(
                                        (scope.tags[tag] as? TextParserTagType.Direct<TContext>)?.begin(null, scope.ctx)?.let {
                                                appendTextRaw(it)
                                        }
-                                       flushBuffer()
                                        
                                        PlainText(scope, "", insideTags, insideDirectTags + tag)
-                               } else if (scope.tags[tag] is TextParserTagType.Indirect<TContext>) {
-                                       val tagType = scope.tags[tag] as TextParserTagType.Indirect<TContext>
-                                       flushBuffer()
-                                       
-                                       PlainText(scope, "", insideTags + (tagType to null), insideDirectTags)
-                               } else {
-                                       appendText("[$tag]")
-                                       
-                                       PlainText(scope, "", insideTags, insideDirectTags)
-                               }
+                               } else
+                                       PlainText(scope, "", insideTags + (tag to null), insideDirectTags)
                        } else if (char == '/' && tag == "")
                                CloseTag(scope, tag, insideTags, insideDirectTags)
                        else if (char == '=' && tag != "")
@@ -122,51 +107,37 @@ sealed class TextParserState<TContext>(
                
                override fun processEndOfText() {
                        appendText("[$tag")
-                       flushBuffer()
                }
        }
        
-       class TagParam<TContext>(scope: TextParserScope<TContext>, val tag: String, val param: String, insideTags: List<Pair<TextParserTagType.Indirect<TContext>, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
+       class TagParam<TContext>(scope: TextParserScope<TContext>, val tag: String, val param: String, insideTags: List<Pair<String, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
                override fun processCharacter(char: Char): TextParserState<TContext> {
                        return if (char == ']') {
-                               when (val tagType = scope.tags[tag]) {
-                                       is TextParserTagType.Direct<TContext> -> {
-                                               appendTextRaw(tagType.begin(param, scope.ctx))
-                                               flushBuffer()
-                                               
-                                               PlainText(scope, "", insideTags, insideDirectTags + tag)
-                                       }
+                               val tagType = scope.tags[tag]
+                               if (tagType is TextParserTagType.Direct<TContext>) {
+                                       appendTextRaw(tagType.begin(param, scope.ctx))
                                        
-                                       is TextParserTagType.Indirect<TContext> -> {
-                                               flushBuffer()
-                                               PlainText(scope, "", insideTags + (tagType to param), insideDirectTags)
-                                       }
-                                       else -> {
-                                               appendText("[$tag=$param]")
-                                               
-                                               PlainText(scope, "", insideTags, insideDirectTags)
-                                       }
-                               }
+                                       PlainText(scope, "", insideTags, insideDirectTags + tag)
+                               } else
+                                       PlainText(scope, "", insideTags + (tag to param), insideDirectTags)
                        } else
                                TagParam(scope, tag, param + char, insideTags, insideDirectTags)
                }
                
                override fun processEndOfText() {
                        appendText("[$tag=$param")
-                       flushBuffer()
                }
        }
        
-       class CloseTag<TContext>(scope: TextParserScope<TContext>, val tag: String, insideTags: List<Pair<TextParserTagType.Indirect<TContext>, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
+       class CloseTag<TContext>(scope: TextParserScope<TContext>, val tag: String, insideTags: List<Pair<String, String?>>, insideDirectTags: List<String>) : TextParserState<TContext>(scope, insideTags, insideDirectTags) {
                override fun processCharacter(char: Char): TextParserState<TContext> {
                        return if (char == ']') {
                                val tagType = scope.tags[tag]
                                if (tagType is TextParserTagType.Direct<TContext> && insideDirectTags.last().equals(tag, ignoreCase = true)) {
                                        appendTextRaw(tagType.end(scope.ctx))
-                                       flushBuffer()
+                                       
                                        PlainText(scope, "", insideTags, insideDirectTags.dropLast(1))
-                               } else if (insideTags.isNotEmpty() && insideTags.last().first == scope.tags[tag]) {
-                                       flushBuffer()
+                               } else if (insideTags.isNotEmpty() && insideTags.last().first.equals(tag, ignoreCase = true)) {
                                        PlainText(scope, "", insideTags.dropLast(1), insideDirectTags)
                                } else {
                                        appendText("[/$tag]")
@@ -177,7 +148,6 @@ sealed class TextParserState<TContext>(
                
                override fun processEndOfText() {
                        appendText("[/$tag")
-                       flushBuffer()
                }
        }
        
@@ -200,7 +170,7 @@ sealed class TextParserState<TContext>(
                        val builder = StringBuilder()
                        try {
                                val fixedText = text.replace("\r\n", "\n").replace('\r', '\n')
-                               fixedText.fold<TextParserState<TContext>>(Initial(TextParserScope("", builder, tags, context))) { state, char -> state.processCharacter(char) }.processEndOfText()
+                               fixedText.fold<TextParserState<TContext>>(Initial(TextParserScope(builder, tags, context))) { state, char -> state.processCharacter(char) }.processEndOfText()
                        } catch (ex: Exception) {
                                return ParseOutcome("<p>$builder</p><h1>Internal Error!</h1><pre>${ex.stackTraceToString()}</pre>", false)
                        }