Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException when combining a Tuple2 parser #29

Open
Benjozork opened this issue Aug 22, 2020 · 3 comments
Open

ClassCastException when combining a Tuple2 parser #29

Benjozork opened this issue Aug 22, 2020 · 3 comments

Comments

@Benjozork
Copy link

Benjozork commented Aug 22, 2020

Hello,

The following code :

val typePrefix by (type * -znws * parser(this::referenceParser) * -znws * -assign)

// ...

val traitFunction    by parser(this::functionSignature) use { CyanTraitDeclaration.Element.Function(CyanFunctionDeclaration(this, null), span) }
val traitProperty    by structProperty                  use { CyanTraitDeclaration.Element.Property(ident, type, span) }
val traitElement     by (traitFunction or traitProperty)
val traitDeclaration by (typePrefix * -znws * -trait * -znws * -lcur * -znws * (separatedTerms(traitElement, newLine)
    .use { toTypedArray() }) * -znws * -rcur) use { CyanTraitDeclaration(t2, t3, span(t1, t3.last())) }

Yields the following exception :

com.github.h0tk3y.betterParse.utils.Tuple2 cannot be cast to com.github.h0tk3y.betterParse.lexer.TokenMatch
java.lang.ClassCastException: com.github.h0tk3y.betterParse.utils.Tuple2 cannot be cast to com.github.h0tk3y.betterParse.lexer.TokenMatch
	at cyan.compiler.parser.CyanModuleParser$$special$$inlined$and2Operator$2.invoke(andFunctions.kt:9)
	at cyan.compiler.parser.CyanModuleParser$$special$$inlined$and2Operator$2.invoke(andFunctions.kt)
	at com.github.h0tk3y.betterParse.combinators.AndCombinator.tryParse(AndCombinator.kt:60)
	at com.github.h0tk3y.betterParse.combinators.MapCombinator.tryParse(MapCombinator.kt:14)
	at com.github.h0tk3y.betterParse.combinators.OrCombinator.tryParse(OrCombinator.kt:13)
	at com.github.h0tk3y.betterParse.combinators.AndCombinator.tryParse(AndCombinator.kt:40)
	at com.github.h0tk3y.betterParse.combinators.AndCombinator.tryParse(AndCombinator.kt:40)
	at com.github.h0tk3y.betterParse.combinators.SeparatedCombinator.tryParse(Separated.kt:16)
	at com.github.h0tk3y.betterParse.combinators.MapCombinator.tryParse(MapCombinator.kt:14)
	at com.github.h0tk3y.betterParse.combinators.MapCombinator.tryParse(MapCombinator.kt:14)
	at com.github.h0tk3y.betterParse.combinators.AndCombinator.tryParse(AndCombinator.kt:40)
	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:65)
	at cyan.compiler.parser.StatementsTest.doTest(StatementsTest.kt:29)
	at cyan.compiler.parser.StatementsTest.access$doTest(StatementsTest.kt:24)
	at cyan.compiler.parser.StatementsTest$TypeDeclarations.trait with one function(StatementsTest.kt:34)
        <...>

From a quick look into the code, it seems like in andFunctions.kt this is function is called for the first * operator in typePrefix * -znws * -trait :

@JvmName("and2") inline infix fun <reified T1, reified T2, reified T3>
    AndCombinator<Tuple2<T1, T2>>.and(p3: Parser<T3>) =
    AndCombinator(consumers + p3, {
        Tuple3(it[0] as T1, it[1] as T2, it[2] as T3)
    })

But looking at the debugger, I see values packed into a tuple and not "flat mapped" (don't know if that makess sense, couldn't think of a better way to put it) :

image

Here, t1 of element 0 (which is the result of typePrefix) is the match for token type, and t2 is from parser(this::referenceParser). Yet, the code thinks t1 is element 0, and t2 is element 1, while they are in fact both inside element 0. This obviously causes a ClassCastException when it tries to cast element 0 into what I assume reified type parameter T1 is (TokenMatch).

I couldn't figure out which part of the library laid out those elements like that, which is where I'm stuck.

I hope this all made sense, and thanks in advance.

@Benjozork Benjozork changed the title ClassCastException when combinding a Tuple2 parser ClassCastException when combining a Tuple2 parser Aug 22, 2020
@richardhundt
Copy link

@Benjozork did you manage to solve this for Cyan? I've run into exactly the same problem, on a much smaller grammar

@richardhundt
Copy link

I think the issue is that the SkipParser throws away type information, so the reified types don't propagate, and for some reason Kotlin doesn't complain.

public class SkipParser(public val innerParser: Parser<*>)

Can't this be made generic?

@Benjozork
Copy link
Author

Hey, it's been a long time since I worked on cyan and I think I just reshuffled the parser a bit to where it wasn't causing an issue and forgot about it. Sorry I don't have a more useful solution 😬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants