commonMain.agl.automaton.RuntimeTransitionCalculator.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of agl-processor-jvm8 Show documentation
Show all versions of agl-processor-jvm8 Show documentation
Dynamic, scan-on-demand, parsing; when a regular expression is just not enough
The newest version!
/**
* Copyright (C) 2022 Dr. David H. Akehurst (http://dr.david.h.akehurst.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.akehurst.language.agl.automaton
import net.akehurst.language.api.automaton.ParseAction
import net.akehurst.language.agl.automaton.ParserState.Companion.lhs
import net.akehurst.language.agl.runtime.structure.RuntimeRule
internal class RuntimeTransitionCalculator(
val stateSet: ParserStateSet
) {
//internal fun calcFilteredTransitions(prevPrev: ParserState, previousState: ParserState, sourceState: ParserState): Set {
// val transitions = this.calcTransitions(prevPrev, previousState, sourceState)//, gn.lookaheadStack.peek())
// return transitions
//}
private val __transitions = mutableSetOf() // to save time allocating when calcTransitions is called
fun calTransitionsForGoal(sourceState: ParserState, previousState: ParserState): Set {
__transitions.clear()
val widthInto = this.stateSet.buildCache.widthInto(previousState, sourceState)
for (wi in widthInto) {
val rr = wi.to.rule as RuntimeRule
when {
rr.isTerminal -> __transitions.add(this.createWidthOrEmbeddedTransition(sourceState, wi))
else -> error("Should never happen")
}
}
return __transitions
}
fun calcTransitionsForComplete(sourceState: ParserState, previousState: ParserState, prevPrev: ParserState): Set {
__transitions.clear()
val heightOrGraftInto = this.stateSet.buildCache.heightOrGraftInto(prevPrev, previousState, sourceState)
for (hg in heightOrGraftInto) {
when (hg.action) {
ParseAction.GOAL -> {
when {
(sourceState.isGoal && this.stateSet.isSkip) -> {
// must be end of skip. TODO: can do something better than this!
val to = sourceState
__transitions.add(Transition(sourceState, to, ParseAction.GOAL, setOf(Lookahead.EMPTY)))
}
else -> {
//must pass in hg, because for embedded rules, GOAL does not end with EOT
val ts = this.createGoalTransition3(sourceState, hg)
__transitions.add(ts)//, addLh, parentLh))
}
}
}
ParseAction.HEIGHT -> {
val ts = this.createHeightTransition3(sourceState, hg)
__transitions.add(ts)
}
ParseAction.GRAFT -> {
val ts = this.createGraftTransition3(sourceState, hg)
__transitions.add(ts)
}
else -> error("")
}
}
return __transitions
}
fun calcTransitionsForInComplete(source: ParserState, previous: ParserState): Set {
__transitions.clear()
val widthInto = this.stateSet.buildCache.widthInto(previous, source)
for (wi in widthInto) {
val ts = this.createWidthOrEmbeddedTransition(source, wi)
__transitions.add(ts)
}
return __transitions
}
// must use previousState.rulePosition as starting point for finding
// lookahead for height/graft, and previousLookahead to use if end up at End of rule
// due to position or empty rules.
internal fun calcTransitions(
prevPrev: ParserState,
previousState: ParserState,
sourceState: ParserState
): Set {//TODO: add previous in order to filter parent relations
__transitions.clear()
when {
sourceState.isGoal -> {
val widthInto = this.stateSet.buildCache.widthInto(previousState, sourceState)
for (wi in widthInto) {
val rr = wi.to.rule as RuntimeRule
when {
rr.isTerminal -> __transitions.add(this.createWidthOrEmbeddedTransition(sourceState, wi))
else -> error("Should never happen")
}
}
}
sourceState.isAtEnd -> {
val transInfos = this.stateSet.buildCache.heightOrGraftInto(prevPrev, previousState, sourceState)
for (hg in transInfos) {
when (hg.action) {
ParseAction.GOAL -> {
when {
(sourceState.isGoal && this.stateSet.isSkip) -> {
// must be end of skip. TODO: can do something better than this!
val to = sourceState
__transitions.add(Transition(sourceState, to, ParseAction.GOAL, setOf(Lookahead.EMPTY)))
}
else -> {
//must pass in hg, because for embedded rules, GOAL does not end with EOT
val ts = this.createGoalTransition3(sourceState, hg)
__transitions.add(ts)//, addLh, parentLh))
}
}
}
ParseAction.HEIGHT -> {
val ts = this.createHeightTransition3(sourceState, hg)
__transitions.add(ts)
}
ParseAction.GRAFT -> {
val ts = this.createGraftTransition3(sourceState, hg)
__transitions.add(ts)
}
else -> error("")
}
}
}
else -> {
val widthInto = this.stateSet.buildCache.widthInto(previousState, sourceState)
for (wi in widthInto) {
val ts = this.createWidthOrEmbeddedTransition(sourceState, wi)
__transitions.add(ts)
}
}
}
return __transitions
}
internal fun createWidthTransFor(from: ParserState, widthInto: Set): Set {
__transitions.clear()
for (wi in widthInto) {
val ts = this.createWidthOrEmbeddedTransition(from, wi)
__transitions.add(ts)
}
return __transitions
}
private fun createWidthOrEmbeddedTransition(sourceState: ParserState, wi: WidthInfo): Transition {
val rp = wi.to
val lookaheadInfo = Lookahead(wi.lookaheadSet.lhs(this.stateSet), LookaheadSet.EMPTY)
val to = this.stateSet.fetchCompatibleOrCreateState(listOf(rp))
// upLookahead and prevGuard are unused
return Transition(sourceState, to, wi.action, setOf(lookaheadInfo))
}
private fun createHeightTransition3(sourceState: ParserState, hg: TransInfo): Transition {
val to = this.stateSet.fetchCompatibleOrCreateState(hg.to.toList())
val lookaheadInfo = hg.lookahead.map { Lookahead(it.guard.lhs(this.stateSet), it.up.lhs(this.stateSet)) }.toSet()
val trs = Transition(sourceState, to, ParseAction.HEIGHT, lookaheadInfo)
return trs
}
private fun createGraftTransition3(sourceState: ParserState, hg: TransInfo): Transition {
val to = this.stateSet.fetchCompatibleOrCreateState(hg.to.toList())
val lookaheadInfo = hg.lookahead.map { Lookahead(it.guard.lhs(this.stateSet), LookaheadSet.EMPTY) }.toSet()
val trs = Transition(sourceState, to, ParseAction.GRAFT, lookaheadInfo)
return trs
}
private fun createGoalTransition3(sourceState: ParserState, hg: TransInfo): Transition {
val to = this.stateSet.finishState
//// must compute lookaheadInfo, because for embedded grammars, guard for completion of GOAL is not necessarily EOT
//val lookaheadInfo = hg.lhs.map { Lookahead(it.guard.lhs(this.stateSet), LookaheadSet.EMPTY) }.toSet()
val lookaheadInfo = hg.lookahead.map { Lookahead(LookaheadSet.EOT, LookaheadSet.EMPTY) }.toSet()
val trs = Transition(sourceState, to, ParseAction.GOAL, lookaheadInfo)
return trs
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy