Skip to content

Commit

Permalink
complete migration of antlr#39
Browse files Browse the repository at this point in the history
  • Loading branch information
ericvergnaud committed Feb 26, 2024
1 parent 1f6a704 commit 18deed5
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.antlr.v5.runtime.core.misc.decodeIntsEncodedAs16BitWords
import org.antlr.v5.runtime.core.state.*
import org.antlr.v5.runtime.core.transition.*


/**
* @author Sam Harwell
*/
Expand Down Expand Up @@ -265,8 +266,8 @@ public open class ATNDeserializer(deserializationOptions: ATNDeserializationOpti

var endState: ATNState?
var excludeTransition: Transition? = null

if (atn.ruleToStartState!![i].isLeftRecursiveRule) {
val ruleStartState = atn.ruleToStartState!![i]
if (ruleStartState.isLeftRecursiveRule) {
// Wrap from the beginning of the rule to the StarLoopEntryState
endState = null

Expand All @@ -285,7 +286,7 @@ public open class ATNDeserializer(deserializationOptions: ATNDeserializationOpti
continue
}

if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target is RuleStopState) {
if (maybeLoopEndState.onlyHasEpsilonTransitions() && maybeLoopEndState.transition(0).target is RuleStopState) {
endState = state
break
}
Expand Down Expand Up @@ -314,19 +315,30 @@ public open class ATNDeserializer(deserializationOptions: ATNDeserializationOpti
}

// All transitions leaving the rule start state need to leave blockStart instead
while (atn.ruleToStartState!![i].numberOfTransitions > 0) {
val transition = atn.ruleToStartState!![i].removeTransition(atn.ruleToStartState!![i].numberOfTransitions - 1)
while (ruleStartState.numberOfTransitions > 0) {
val transition = ruleStartState.removeTransition(ruleStartState.numberOfTransitions - 1)
bypassStart.addTransition(transition)
}

// Link the new states
atn.ruleToStartState!![i].addTransition(EpsilonTransition(bypassStart))
ruleStartState.addTransition(EpsilonTransition(bypassStart))
bypassStop.addTransition(EpsilonTransition(endState!!))

val matchState = BasicState()
atn.addState(matchState)
matchState.addTransition(AtomTransition(bypassStop, atn.ruleToTokenType!![i]))
bypassStart.addTransition(EpsilonTransition(matchState))

if (bypassStart.onlyHasEpsilonTransitions()) {
bypassStart.addTransition(EpsilonTransition(matchState))
} else {
val matchState2: ATNState = BasicState()
atn.addState(matchState2)
matchState2.addTransition(bypassStart.transition(0))

bypassStart.removeTransition(0)
bypassStart.addTransition(EpsilonTransition(matchState))
bypassStart.addTransition(EpsilonTransition(matchState2))
}
}

if (deserializationOptions.isVerifyATN) {
Expand Down Expand Up @@ -384,7 +396,7 @@ public open class ATNDeserializer(deserializationOptions: ATNDeserializationOpti
val maybeLoopEndState = state.transition(state.numberOfTransitions - 1).target

if (maybeLoopEndState is LoopEndState) {
if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target is RuleStopState) {
if (maybeLoopEndState.onlyHasEpsilonTransitions() && maybeLoopEndState.transition(0).target is RuleStopState) {
state.isPrecedenceDecision = true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public abstract class ATNState {
public var atn: ATN? = null
public var stateNumber: Int = INVALID_STATE_NUMBER
public var ruleIndex: Int = 0 // at runtime, we don't have Rule objects
public var epsilonOnlyTransitions: Boolean = false
public var epsilonOnlyTransitions: Boolean? = null

/**
* Track the transitions emanating from this ATN state.
Expand Down Expand Up @@ -102,14 +102,10 @@ public abstract class ATNState {
addTransition(transitions.size, e)

public fun addTransition(index: Int, e: Transition) {
if (transitions.isEmpty()) {
epsilonOnlyTransitions = e.isEpsilon
} else if (epsilonOnlyTransitions != e.isEpsilon) {
System.err.println("ATN state $stateNumber has both epsilon and non-epsilon transitions.")
epsilonOnlyTransitions = false
}

var alreadyPresent = false
if(epsilonOnlyTransitions != null && epsilonOnlyTransitions != e.isEpsilon) {
System.err.println("ATN state $stateNumber has both epsilon and non-epsilon transitions.")
}
var alreadyPresent = false

for (t in transitions) {
if (t.target.stateNumber == e.target.stateNumber) {
Expand All @@ -125,6 +121,7 @@ public abstract class ATNState {

if (!alreadyPresent) {
transitions.add(index, e)
recalculateEpsilonOnlyTransitions();
}
}

Expand All @@ -135,32 +132,44 @@ public abstract class ATNState {
return transitions.indexOf(transition)
}

fun findTransition(predicate: java.util.function.Predicate<Transition?>?): Transition? {
return transitions.stream().filter(predicate).findFirst().orElse(null)
}
public fun setTransition(i: Int, e: Transition) {
transitions.removeAt(i);
recalculateEpsilonOnlyTransitions();
if (epsilonOnlyTransitions != null && epsilonOnlyTransitions != e.isEpsilon) {
System.err.println("ATN state $stateNumber has both epsilon and non-epsilon transitions.\n");
}
transitions.add(i, e);
recalculateEpsilonOnlyTransitions();
}

public fun removeTransition(index: Int): Transition {
val result = transitions.removeAt(index)
recalculateEpsilonOnlyTransitions()
return result

public fun setTransition(i: Int, e: Transition) {
transitions[i] = e
}

public fun removeTransition(index: Int): Transition =
transitions.removeAt(index)

public fun removeTransition(transition: Transition): Boolean {
val result = transitions.remove(transition)
recalculateEpsilonOnlyTransitions()
return result
}

fun findTransition(predicate: java.util.function.Predicate<Transition?>?): Transition? {
return transitions.stream().filter(predicate).findFirst().orElse(null)
}



public fun clearTransitions() {
transitions.clear()
}
public fun onlyHasEpsilonTransitions(): Boolean =
epsilonOnlyTransitions
epsilonOnlyTransitions != null && epsilonOnlyTransitions!!

fun recalculateEpsilonOnlyTransitions() {
if (transitions.size == 0) {
epsilonOnlyTransitions = false
epsilonOnlyTransitions = null
} else {
epsilonOnlyTransitions = transitions.stream().allMatch(Transition::isEpsilon)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@ import org.antlr.v5.runtime.core.state.ATNState
*/
@Suppress("MemberVisibilityCanBePrivate")
public object CodePointTransitions {
/**
* Return new [AtomTransition].
*/
public fun createWithCodePoint(target: ATNState, codePoint: Int): Transition =
createWithCodePointRange(target, codePoint, codePoint)

/**
/**
* Return new [AtomTransition] if range represents one atom, else [SetTransition].
*/
public fun createWithCodePointRange(target: ATNState, codePointFrom: Int, codePointTo: Int): Transition =
Expand Down

0 comments on commit 18deed5

Please sign in to comment.