You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This might be a duplicate of #29. But there's no solution in that issue, and it's almost three years old.
Using Kotlin 1.8.20, and better-parse 0.4.4, this code (which is supposed to parse an Android resource qualifier string, like values-en-rGB-land-v28) has a runtime error:
data classMobileCodes(valmcc:String, valmnc:String? = null)
data classLocale(vallang:String, valregion:String? = null, valscript:String? = null)
data classConfigurationQualifier(valmobileCodes:MobileCodes? = null, vallocale:Locale? = null)
/** * Parse an Android `values-*` resource directory name and extract the configuration qualifiers * * Directory name has the following components in a specific order, listed in * https://developer.android.com/guide/topics/resources/providing-resources#table2*/classValuesParser : Grammar<ConfigurationQualifier>() {
// Tokenizersprivateval values by literalToken("values")
privateval sep by literalToken("-")
privateval mobileCodes by regexToken("(?i:mcc\\d+)(?i:mnc\\d+)?")
privateval locale by regexToken("(?i:[a-z]{2,3})(?i:-r([a-z]{2,3}))?(?=-|$)")
privateval bcpStartTag by regexToken("(?i:b\\+[a-z]{2,3})")
privateval bcpSubtag by regexToken("(?i:\\+[a-z]+)")
privateval layoutDirection by regexToken("(?i:ldrtl|ldltr)")
privateval smallestWidth by regexToken("(?i:sw\\d+dp)")
privateval availableDimen by regexToken("(?i:[wh]\\d+dp)")
privateval screenSize by regexToken("(?i:small|normal|large|xlarge)")
privateval screenAspect by regexToken("(?i:long|notlong)")
privateval roundScreen by regexToken("(?i:round|notround)")
privateval wideColorGamut by regexToken("(?i:widecg|nowidecg)")
privateval highDynamicRange by regexToken("(?i:highdr|lowdr)")
privateval screenOrientation by regexToken("(?i:port|land)")
privateval uiMode by regexToken("(?i:car|desk|television|appliance|watch|vrheadset)")
privateval nightMode by regexToken("(?i:night|notNight)")
privateval screenDpi by regexToken("(?i:(?:l|m|h|x|xx|xxx|no|tv|any|\\d+)dpi)")
privateval touchScreen by regexToken("(?i:notouch|finger)")
privateval keyboardAvailability by regexToken("(?i:keysexposed|keyshidden|keyssoft)")
privateval inputMethod by regexToken("(?i:nokeys|qwerty|12key)")
privateval navKeyAvailability by regexToken("(?i:naxexposed|navhidden)")
privateval navMethod by regexToken("(?i:nonav|dpad|trackball|wheel)")
privateval platformVersion by regexToken("(?i:v\\d+)")
// Parsersprivateval mobileCodesParser by mobileCodes use {
val parts =this.text.split("-")
MobileCodes(mcc = parts[0], mnc = parts.getOrNull(1))
}
privateval localeParser by locale use {
val parts =this.text.split("-r".toRegex(), 2)
Locale(lang = parts[0], region = parts.getOrNull(1))
}
privateval bcpLocaleParser = bcpStartTag and zeroOrMore(bcpSubtag) use {
Locale(
lang =this.t1.text.split("+")[1],
script =this.t2.getOrNull(0)?.text?.split("+")?.get(1),
region =this.t2.getOrNull(1)?.text?.split("+")?.get(1)
)
}
privateval qualifier = skip(values) and
optional(skip(sep) and mobileCodesParser) and
optional(skip(sep) and (localeParser or bcpLocaleParser)) and
optional(skip(sep) and layoutDirection) and
optional(skip(sep) and smallestWidth) and
optional(skip(sep) and availableDimen) and
optional(skip(sep) and screenSize) and
optional(skip(sep) and screenAspect) and
optional(skip(sep) and roundScreen) and
optional(skip(sep) and wideColorGamut) and
optional(skip(sep) and highDynamicRange) and
optional(skip(sep) and screenOrientation) and
optional(skip(sep) and uiMode) and
optional(skip(sep) and nightMode) and
optional(skip(sep) and screenDpi) and
optional(skip(sep) and touchScreen) and
optional(skip(sep) and keyboardAvailability) and
optional(skip(sep) and inputMethod) and
optional(skip(sep) and navKeyAvailability) and
optional(skip(sep) and navMethod) and
optional(skip(sep) and platformVersion)
privateval qualifierParser by qualifier use {
// Here, the type of `this` is // Tuple5<Tuple16<MobileCodes?, Locale?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?>, TokenMatch?, TokenMatch?, TokenMatch?, TokenMatch?>.`<anonymous>`(): ConfigurationQualifierConfigurationQualifier(
mobileCodes =this.t1.t1,
locale =this.t1.t2
)
}
overrideval rootParser by qualifierParser
}
The error is:
null cannot be cast to non-null type com.github.h0tk3y.betterParse.utils.Tuple16<app.tusky.mklanguages.MobileCodes?, app.tusky.mklanguages.Locale?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?>
java.lang.NullPointerException: null cannot be cast to non-null type com.github.h0tk3y.betterParse.utils.Tuple16<app.tusky.mklanguages.MobileCodes?, app.tusky.mklanguages.Locale?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?, com.github.h0tk3y.betterParse.lexer.TokenMatch?>
at app.tusky.mklanguages.ValuesParser$special$$inlined$and4$2.invoke(andFunctions.kt:42)
at app.tusky.mklanguages.ValuesParser$special$$inlined$and4$2.invoke(andFunctions.kt:41)
at com.github.h0tk3y.betterParse.combinators.AndCombinator.tryParse(AndCombinator.kt:72)
at com.github.h0tk3y.betterParse.combinators.MapCombinator.tryParse(MapCombinator.kt:14)
at com.github.h0tk3y.betterParse.parser.ParserKt.tryParseToEnd(Parser.kt:18)
at com.github.h0tk3y.betterParse.parser.ParserKt.parseToEnd(Parser.kt:29)
at com.github.h0tk3y.betterParse.grammar.GrammarKt.parseToEnd(Grammar.kt:70)
at app.tusky.mklanguages.ValuesParserTest$ParseLocale.returns the expected locale(ValuesParserTest.kt:54)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestTemplateMethod(TimeoutExtension.java:94)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:202)
at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
If the number of parsers is kept to 16 or below it works. E.g., by making the following modifications to the bottom half of the file:
// Replace `qualifier` and `qualifierParser` with:
private val qualifier = skip(values) and
optional(skip(sep) and mobileCodesParser) and
optional(skip(sep) and (localeParser or bcpLocaleParser)) and
optional(skip(sep) and layoutDirection) and
optional(skip(sep) and smallestWidth) and
optional(skip(sep) and availableDimen) and
optional(skip(sep) and screenSize) and
optional(skip(sep) and screenAspect) and
optional(skip(sep) and roundScreen) and
optional(skip(sep) and wideColorGamut) and
optional(skip(sep) and highDynamicRange) and
optional(skip(sep) and screenOrientation) and
optional(skip(sep) and uiMode) and
optional(skip(sep) and nightMode) and
optional(skip(sep) and screenDpi) and
optional(skip(sep) and touchScreen) and
optional(skip(sep) and keyboardAvailability) // and
// optional(skip(sep) and inputMethod) and
// optional(skip(sep) and navKeyAvailability) and
// optional(skip(sep) and navMethod) and
// optional(skip(sep) and platformVersion)
private val qualifierParser by qualifier use {
ConfigurationQualifier(
mobileCodes = this.t1,
locale = this.t2
)
}
then the string values-en-rGB-land successfully parses.
The text was updated successfully, but these errors were encountered:
Thanks for this report! Now that a use case appeared for such a long and-chain, I think I will have to increase the number of generated tuple classes and the supported chain length. If building the library from sources in an included build is fine for you, you can try to tweak this in
This might be a duplicate of #29. But there's no solution in that issue, and it's almost three years old.
Using Kotlin 1.8.20, and better-parse 0.4.4, this code (which is supposed to parse an Android resource qualifier string, like
values-en-rGB-land-v28
) has a runtime error:The error is:
If the number of parsers is kept to 16 or below it works. E.g., by making the following modifications to the bottom half of the file:
then the string
values-en-rGB-land
successfully parses.The text was updated successfully, but these errors were encountered: