-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from alllex/error-descriptions
User-friendly unmatched token errors
- Loading branch information
Showing
8 changed files
with
276 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package me.alllex.parsus.util | ||
|
||
internal fun replaceNonPrintable(string: String): String { | ||
return buildString { | ||
for (char in string) { | ||
append(replaceNonPrintable(char)) | ||
} | ||
} | ||
} | ||
|
||
internal fun replaceNonPrintable(char: Char): Char { | ||
return when (char) { | ||
' ' -> '␣' // U+2423 OPEN BOX | ||
'\n' -> '' // U+2424 SYMBOL FOR NEWLINE | ||
'\r' -> '␍' // U+240D SYMBOL FOR CARRIAGE RETURN | ||
'\t' -> '␉' // U+2409 SYMBOL FOR HORIZONTAL TABULATION | ||
else -> char | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package me.alllex.parsus | ||
|
||
import assertk.assertions.isEqualTo | ||
import assertk.assertions.prop | ||
import me.alllex.parsus.parser.Grammar | ||
import me.alllex.parsus.parser.ParseError | ||
import me.alllex.parsus.parser.map | ||
import me.alllex.parsus.parser.times | ||
import me.alllex.parsus.token.literalToken | ||
import me.alllex.parsus.token.regexToken | ||
import kotlin.test.Test | ||
|
||
class ParseErrorTest { | ||
|
||
@Test | ||
fun unmatchedTokenErrorsProvideUserFriendlyDescriptions() { | ||
object : Grammar<String>() { | ||
val ab by literalToken("ab") | ||
val cd by literalToken("cd") | ||
override val root by ab * cd map { (v1, v2) -> "${v1.text}-${v2.text}" } | ||
}.run { | ||
|
||
assertParsed("abcd").isEqualTo("ab-cd") | ||
|
||
assertNotParsed("abab").prop(ParseError::describe).isEqualTo( | ||
"Unmatched token at offset=2, when expected: LiteralToken('cd')\n" + """ | ||
Expected token: LiteralToken('cd') | ||
| offset=2 (or after ignored tokens) | ||
abab | ||
^^ Previous token: LiteralToken('ab') at offset=0 | ||
""".trimIndent() + "\n" | ||
) | ||
|
||
assertNotParsed("cd").prop(ParseError::describe).isEqualTo( | ||
"Unmatched token at offset=0, when expected: LiteralToken('ab')\n" + """ | ||
Expected token: LiteralToken('ab') | ||
| offset=0 (or after ignored tokens) | ||
cd | ||
""".trimIndent() + "\n" | ||
) | ||
|
||
assertNotParsed("abcdab").prop(ParseError::describe).isEqualTo( | ||
"Unmatched token at offset=4, when expected: Token(EOF)\n" + """ | ||
Expected token: Token(EOF) | ||
| offset=4 (or after ignored tokens) | ||
cdab | ||
^^ Previous token: LiteralToken('cd') at offset=2 | ||
""".trimIndent() + "\n" | ||
) | ||
} | ||
} | ||
|
||
@Test | ||
fun lastMatchDescriptionIsPresentWhenThereAreIgnoredTokensInBetween() { | ||
object : Grammar<String>() { | ||
val ws by literalToken(" ", ignored = true) | ||
val ab by literalToken("ab") | ||
val cd by literalToken("cd") | ||
override val root by ab * cd map { (v1, v2) -> "${v1.text}-${v2.text}" } | ||
}.run { | ||
assertParsed("ab cd").isEqualTo("ab-cd") | ||
|
||
assertNotParsed("ab ab").prop(ParseError::describe).isEqualTo( | ||
"Unmatched token at offset=2, when expected: LiteralToken('cd')\n" + """ | ||
Expected token: LiteralToken('cd') | ||
| offset=2 (or after ignored tokens) | ||
ab␣ab | ||
^^ Previous token: LiteralToken('ab') at offset=0 | ||
""".trimIndent() + "\n" | ||
) | ||
} | ||
} | ||
|
||
@Test | ||
fun unprintableCharactersAreReplacedInErrors() { | ||
object : Grammar<String>() { | ||
val ws by regexToken("\\s+") | ||
val ab by literalToken("ab") | ||
@Suppress("unused") | ||
val cd by literalToken("cd") | ||
override val root by ws * ab map { (v1, v2) -> "${v1.text}-${v2.text}" } | ||
}.run { | ||
assertParsed(" \t\r\nab").isEqualTo(" \t\r\n-ab") | ||
|
||
assertNotParsed(" \t\r\ncd").prop(ParseError::describe).isEqualTo( | ||
"Unmatched token at offset=4, when expected: LiteralToken('ab')\n" + """ | ||
Expected token: LiteralToken('ab') | ||
| offset=4 (or after ignored tokens) | ||
␣␉␍cd | ||
^^^^ Previous token: RegexToken(ws [\s+]) at offset=0 | ||
""".trimIndent() + "\n" | ||
) | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters