All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.org.antlr.v4.kotlinruntime.tree.IterativeParseTreeWalker.kt Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
// Copyright 2017-present Strumenta and contributors, licensed under Apache 2.0.
// Copyright 2024-present Strumenta and contributors, licensed under BSD 3-Clause.
package org.antlr.v4.kotlinruntime.tree

import org.antlr.v4.kotlinruntime.misc.IntegerStack

/**
 * An iterative (read: non-recursive) pre-order and post-order tree walker that
 * doesn't use the thread stack but heap-based stacks. Makes it possible to
 * process deeply nested parse trees.
 */
public open class IterativeParseTreeWalker : ParseTreeWalker() {
  override fun walk(listener: ParseTreeListener, t: ParseTree) {
    val nodeStack = ArrayDeque()
    val indexStack = IntegerStack()
    var currentNode: ParseTree? = t
    var currentIndex = 0

    while (currentNode != null) {
      // Pre-order visit
      when (currentNode) {
        is ErrorNode -> listener.visitErrorNode(currentNode)
        is TerminalNode -> listener.visitTerminal(currentNode)
        else -> enterRule(listener, currentNode as RuleNode)
      }

      // Move down to first child, if exists
      if (currentNode.childCount > 0) {
        nodeStack.addFirst(currentNode)
        indexStack.push(currentIndex)
        currentIndex = 0
        currentNode = currentNode.getChild(0)
        continue
      }

      // No child nodes, so walk tree
      do {
        // Post-order visit
        if (currentNode is RuleNode) {
          exitRule(listener, currentNode)
        }

        // No parent, so no siblings
        if (nodeStack.isEmpty()) {
          currentNode = null
          currentIndex = 0
          break
        }

        // Move to next sibling if possible
        currentNode = nodeStack.first().getChild(++currentIndex)

        if (currentNode != null) {
          break
        }

        // No next, sibling, so move up
        currentNode = nodeStack.removeFirst()
        currentIndex = indexStack.pop()

        // The original condition was 'currentNode != null',
        // but since nodeStack.removeFirst() throws if there
        // is no element, the condition is always true
      } while (true)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy