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

Improve nullability support for generated parsers #142

Merged
merged 4 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ public open class ParserRuleContext : RuleContext {
if (o is TerminalNode) {
val symbol = o.symbol

if (symbol!!.type == ttype) {
if (symbol.type == ttype) {
j++

if (j == i) {
Expand All @@ -273,7 +273,7 @@ public open class ParserRuleContext : RuleContext {
if (o is TerminalNode) {
val symbol = o.symbol

if (symbol!!.type == ttype) {
if (symbol.type == ttype) {
tokens.add(o)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ package org.antlr.v4.kotlinruntime.tree
import org.antlr.v4.kotlinruntime.Token

public interface TerminalNode : ParseTree {
public val symbol: Token?
public val symbol: Token
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@ import org.antlr.v4.kotlinruntime.RuleContext
import org.antlr.v4.kotlinruntime.Token
import org.antlr.v4.kotlinruntime.misc.Interval

public open class TerminalNodeImpl(override var symbol: Token?) : TerminalNode {
public open class TerminalNodeImpl(override var symbol: Token) : TerminalNode {
private var parent: ParseTree? = null

override val childCount: Int = 0

override val text: String
get() = symbol!!.text!!
get() = symbol.text!!

override val payload: Token?
override val payload: Token
get() = symbol

override val sourceInterval: Interval
get() {
val tempSymbol = symbol ?: return Interval.INVALID
val tokenIndex = tempSymbol.tokenIndex
val tokenIndex = symbol.tokenIndex
return Interval(tokenIndex, tokenIndex)
}

Expand All @@ -46,10 +45,10 @@ public open class TerminalNodeImpl(override var symbol: Token?) : TerminalNode {
toString()

override fun toString(): String =
if (symbol!!.type == Token.EOF) {
if (symbol.type == Token.EOF) {
"<EOF>"
} else {
symbol!!.text!!
symbol.text!!
}

override fun toStringTree(): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,23 @@ public object Trees {

public fun getNodeText(t: Tree, ruleNames: List<String>?): String {
if (ruleNames != null) {
if (t is RuleContext) {
val ruleIndex = t.ruleContext.ruleIndex
val ruleName = ruleNames[ruleIndex]
val altNumber = t.altNumber

return if (altNumber != ATN.INVALID_ALT_NUMBER) {
"$ruleName:$altNumber"
} else {
ruleName
when (t) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we factor out the return?

Copy link
Contributor Author

@lppedd lppedd Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot as that's a non-local return (when inside of an if). Will be supported starting from Kotlin 2.0.

Copy link
Contributor Author

@lppedd lppedd Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, wrong answer. We cannot, as it requires an else branch to return something. We don't want that, we want it to continue over the rest of the method, as it was doing with if-elseif.

is RuleContext -> {
val ruleIndex = t.ruleContext.ruleIndex
val ruleName = ruleNames[ruleIndex]
val altNumber = t.altNumber
return if (altNumber != ATN.INVALID_ALT_NUMBER) {
"$ruleName:$altNumber"
} else {
ruleName
}
}
} else if (t is ErrorNode) {
return t.toString()
} else if (t is TerminalNode) {
val symbol = t.symbol

if (symbol != null) {
return symbol.text!!
is ErrorNode -> {
return t.toString()
}
is TerminalNode -> {
val text = t.symbol.text
return text ?: throw IllegalStateException("Symbol text should not be null")
}
}
}
Expand Down Expand Up @@ -189,7 +189,7 @@ public object Trees {
) {
// Check this node (the root) first
if (findTokens && t is TerminalNode) {
if (t.symbol!!.type == index) {
if (t.symbol.type == index) {
nodes.add(t)
}
} else if (!findTokens && t is ParserRuleContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public open class ParseTreePatternMatcher(public val lexer: Lexer, public val pa
var mismatchedNode: ParseTree? = null

// Both are tokens and they have same type
if (tree.symbol?.type == patternTree.symbol?.type) {
if (tree.symbol.type == patternTree.symbol.type) {
if (patternTree.symbol is TokenTagToken) { // x and <ID>
val tokenTagToken = patternTree.symbol as TokenTagToken

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public open class XPathTokenElement(tokenName: String, protected var tokenType:

for (c in Trees.getChildren(t)) {
if (c is TerminalNode) {
if (c.symbol!!.type == tokenType && !invert || c.symbol!!.type != tokenType && invert) {
if (c.symbol.type == tokenType && !invert || c.symbol.type != tokenType && invert) {
nodes.add(c)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -741,23 +741,23 @@ TokenTypeDecl(t) ::= "var <t.name>: Int"
TokenListDecl(t) ::= "<t.name>: MutableList\<Token> = ArrayList\<Token>()"
RuleContextDecl(r) ::= "<r.name>: <r.ctxName>? = null"
RuleContextListDecl(rdecl) ::= "<rdecl.name>: MutableList\<<rdecl.ctxName>> = ArrayList\<<rdecl.ctxName>>()"
ContextTokenGetterDecl(t) ::= "public fun <t.name>(): TerminalNode? = getToken(Tokens.<t.name>.id, 0)"
ContextTokenGetterDecl(t) ::= "public fun <t.name>(): TerminalNode<if(t.optional)>?<endif> = getToken(Tokens.<t.name>.id, 0)<if(!t.optional)>!!<endif>"
ContextTokenListGetterDecl(t) ::= "public fun <t.name>(): List\<TerminalNode> = getTokens(Tokens.<t.name>.id)"

ContextTokenListIndexedGetterDecl(t) ::= <<
public fun <t.name>(i: Int): TerminalNode = getToken(Tokens.<t.name>.id, i)!!
>>

ContextRuleGetterDecl(r) ::= <<
public fun find<r.escapedName; format="cap">(): <r.ctxName>? = getRuleContext(<r.ctxName>::class, 0)
public fun get<r.escapedName; format="cap">(): <r.ctxName><if(r.optional)>?<endif> = getRuleContext(<r.ctxName>::class, 0)<if(!r.optional)>!!<endif>
>>

ContextRuleListGetterDecl(r) ::= <<
public fun find<r.escapedName; format="cap">(): List\<<r.ctxName>\> = getRuleContexts(<r.ctxName>::class)
public fun get<r.escapedName; format="cap">(): List\<<r.ctxName>\> = getRuleContexts(<r.ctxName>::class)
>>

ContextRuleListIndexedGetterDecl(r) ::= <<
public fun find<r.escapedName; format="cap">(i: Int): <r.ctxName>? = getRuleContext(<r.ctxName>::class, i)
public fun get<r.escapedName; format="cap">(i: Int): <r.ctxName>? = getRuleContext(<r.ctxName>::class, i)
>>

LexerRuleContext() ::= "RuleContext"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,21 @@ class MiniCalcParserTest {
val lexer = MiniCalcLexer(input)
val parser = MiniCalcParser(CommonTokenStream(lexer))
val root = parser.miniCalcFile()
val line = root.findLine(0)!!
val statement = line.findStatement()!!
val line = root.getLine(0)!!
val statement = line.getStatement()

@Suppress("UNUSED_VARIABLE")
val inputDeclStmt = statement as MiniCalcParser.InputDeclarationStatementContext
val inputDecl = statement.findInputDeclaration()!!
val inputDecl = statement.getInputDeclaration()

val inputKw = inputDecl.INPUT()
assertEquals("input", inputKw!!.text)
assertEquals("input", inputKw.text)

val type = inputDecl.findType()!!
val type = inputDecl.getType()
val intKw = (type as MiniCalcParser.IntegerContext).INT()
assertEquals("Int", intKw!!.text)
assertEquals("Int", intKw.text)

val id = inputDecl.ID()!!
val id = inputDecl.ID()
assertEquals("width", id.text)

val newline = line.NEWLINE()!!
Expand Down