Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.kotlinruntime.atn
import com.strumenta.kotlinmultiplatform.Arrays
import com.strumenta.kotlinmultiplatform.Collections
import org.antlr.v4.kotlinruntime.Recognizer
import org.antlr.v4.kotlinruntime.RuleContext
import org.antlr.v4.kotlinruntime.atn.SemanticContext.*
import org.antlr.v4.kotlinruntime.misc.MurmurHash
/** A tree structure used to record the semantic context in which
* an ATN configuration is valid. It's either a single predicate,
* a conjunction `p1&&p2`, or a sum of products `p1||p2`.
*
*
* I have scoped the [AND], [OR], and [Predicate] subclasses of
* [SemanticContext] within the scope of this outer class.
*/
abstract class SemanticContext {
/**
* For context independent predicates, we evaluate them without a local
* context (i.e., null context). That way, we can evaluate them without
* having to create proper rule-specific context during prediction (as
* opposed to the parser, which creates them naturally). In a practical
* sense, this avoids a cast exception from RuleContext to myruleContext.
*
*
* For context dependent predicates, we must pass in a local context so that
* references such as $arg evaluate properly as _localctx.arg. We only
* capture context dependent predicates in the context in which we begin
* prediction, so we passed in the outer context here in case of context
* dependent predicate evaluation.
*/
abstract fun eval(parser: Recognizer<*, *>, parserCallStack: RuleContext): Boolean
/**
* Evaluate the precedence predicates for the context and reduce the result.
*
* @param parser The parser instance.
* @param parserCallStack
* @return The simplified semantic context after precedence predicates are
* evaluated, which will be one of the following values.
*
* * [.NONE]: if the predicate simplifies to `true` after
* precedence predicates are evaluated.
* * `null`: if the predicate simplifies to `false` after
* precedence predicates are evaluated.
* * `this`: if the semantic context is not changed as a result of
* precedence predicate evaluation.
* * A non-`null` [SemanticContext]: the new simplified
* semantic context after precedence predicates are evaluated.
*
*/
open fun evalPrecedence(parser: Recognizer<*, *>, parserCallStack: RuleContext): SemanticContext? {
return this
}
class Predicate : SemanticContext {
val ruleIndex: Int
val predIndex: Int
val isCtxDependent: Boolean // e.g., $i ref in pred
constructor() {
this.ruleIndex = -1
this.predIndex = -1
this.isCtxDependent = false
}
constructor(ruleIndex: Int, predIndex: Int, isCtxDependent: Boolean) {
this.ruleIndex = ruleIndex
this.predIndex = predIndex
this.isCtxDependent = isCtxDependent
}
override fun eval(parser: Recognizer<*, *>, parserCallStack: RuleContext): Boolean {
val localctx = if (isCtxDependent) parserCallStack else null
return parser.sempred(localctx!!, ruleIndex, predIndex)
}
override fun hashCode(): Int {
var hashCode = MurmurHash.initialize()
hashCode = MurmurHash.update(hashCode, ruleIndex)
hashCode = MurmurHash.update(hashCode, predIndex)
hashCode = MurmurHash.update(hashCode, if (isCtxDependent) 1 else 0)
hashCode = MurmurHash.finish(hashCode, 3)
return hashCode
}
override fun equals(other: Any?): Boolean {
if (other !is Predicate) return false
if (this === other) return true
return this.ruleIndex == other.ruleIndex &&
this.predIndex == other.predIndex &&
this.isCtxDependent == other.isCtxDependent
}
override fun toString(): String {
return "{$ruleIndex:$predIndex}?"
}
}
class PrecedencePredicate(val precedence: Int = 0)
: SemanticContext(), Comparable {
override fun eval(parser: Recognizer<*, *>, parserCallStack: RuleContext): Boolean {
return parser.precpred(parserCallStack, precedence)
}
override fun evalPrecedence(parser: Recognizer<*, *>, parserCallStack: RuleContext): SemanticContext? {
return if (parser.precpred(parserCallStack, precedence)) {
NONE
} else {
null
}
}
override fun compareTo(other: PrecedencePredicate): Int {
return precedence - other.precedence
}
override fun hashCode(): Int {
var hashCode = 1
hashCode = 31 * hashCode + precedence
return hashCode
}
override fun equals(other: Any?): Boolean {
if (other !is PrecedencePredicate) {
return false
}
if (this === other) {
return true
}
return this.precedence == other.precedence
}
override// precedence >= _precedenceStack.peek()
fun toString(): String {
return "{$precedence>=prec}?"
}
}
/**
* This is the base class for semantic context "operators", which operate on
* a collection of semantic context "operands".
*
* @since 4.3
*/
abstract class Operator : SemanticContext() {
/**
* Gets the operands for the semantic context operator.
*
* @return a collection of [SemanticContext] operands for the
* operator.
*
* @since 4.3
*/
abstract val operands: Collection
}
/**
* A semantic context which is true whenever none of the contained contexts
* is false.
*/
class AND(a: SemanticContext, b: SemanticContext) : Operator() {
val opnds: Array
override val operands: Collection
get() = opnds.toList()
init {
val operands = HashSet()
if (a is AND)
operands.addAll(a.opnds.toList())
else
operands.add(a)
if (b is AND)
operands.addAll(b.opnds.toList())
else
operands.add(b)
val precedencePredicates = filterPrecedencePredicates(operands)
if (precedencePredicates.isNotEmpty()) {
// interested in the transition with the lowest precedence
val reduced = Collections.min(precedencePredicates)
operands.add(reduced)
}
opnds = operands.toTypedArray()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is AND) return false
return Arrays.equals(this.opnds, other.opnds)
}
override fun hashCode(): Int {
TODO()
//return MurmurHash.hashCode(opnds, AND::class.java!!.hashCode())
}
/**
* {@inheritDoc}
*
*
*
* The evaluation of predicates by this context is short-circuiting, but
* unordered.
*/
override fun eval(parser: Recognizer<*, *>, parserCallStack: RuleContext): Boolean {
for (opnd in opnds) {
if (!opnd.eval(parser, parserCallStack)) return false
}
return true
}
override fun evalPrecedence(parser: Recognizer<*, *>, parserCallStack: RuleContext): SemanticContext? {
var differs = false
val operands = ArrayList()
for (context in opnds) {
val evaluated = context.evalPrecedence(parser, parserCallStack)
differs = differs or (evaluated !== context)
if (evaluated == null) {
// The AND context is false if any element is false
return null
} else if (evaluated !== NONE) {
// Reduce the result by skipping true elements
operands.add(evaluated)
}
}
if (!differs) {
return this
}
if (operands.isEmpty()) {
// all elements were true, so the AND context is true
return NONE
}
var result: SemanticContext? = operands[0]
for (i in 1 until operands.size) {
result = and(result, operands[i])
}
return result
}
override fun toString(): String {
return opnds.toList().joinToString("&&")
}
}
/**
* A semantic context which is true whenever at least one of the contained
* contexts is true.
*/
class OR(a: SemanticContext, b: SemanticContext) : Operator() {
val opnds: Array
override val operands: Collection
get() = opnds.toList()
init {
val operands = HashSet()
if (a is OR)
operands.addAll(a.opnds.toList())
else
operands.add(a)
if (b is OR)
operands.addAll(b.opnds.toList())
else
operands.add(b)
val precedencePredicates = filterPrecedencePredicates(operands)
if (precedencePredicates.isNotEmpty()) {
// interested in the transition with the highest precedence
val reduced = Collections.max(precedencePredicates)
operands.add(reduced)
}
this.opnds = operands.toTypedArray()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is OR) return false
return Arrays.equals(this.opnds, other.opnds)
}
override fun hashCode(): Int {
TODO()
//return MurmurHash.hashCode(opnds, OR::class.java!!.hashCode())
}
/**
* {@inheritDoc}
*
*
*
* The evaluation of predicates by this context is short-circuiting, but
* unordered.
*/
override fun eval(parser: Recognizer<*, *>, parserCallStack: RuleContext): Boolean {
for (opnd in opnds) {
if (opnd.eval(parser, parserCallStack)) return true
}
return false
}
override fun evalPrecedence(parser: Recognizer<*, *>, parserCallStack: RuleContext): SemanticContext? {
var differs = false
val operands = ArrayList()
for (context in opnds) {
val evaluated = context.evalPrecedence(parser, parserCallStack)
differs = differs or (evaluated !== context)
if (evaluated === NONE) {
// The OR context is true if any element is true
return NONE
} else if (evaluated != null) {
// Reduce the result by skipping false elements
operands.add(evaluated)
}
}
if (!differs) {
return this
}
if (operands.isEmpty()) {
// all elements were false, so the OR context is false
return null
}
var result: SemanticContext? = operands[0]
for (i in 1 until operands.size) {
result = or(result, operands[i])
}
return result
}
override fun toString(): String {
return opnds.toList().joinToString("||")
}
}
companion object {
/**
* The default [SemanticContext], which is semantically equivalent to
* a predicate of the form `{true}?`.
*/
val NONE: SemanticContext = Predicate()
fun and(a: SemanticContext?, b: SemanticContext?): SemanticContext? {
if (a == null || a === NONE) return b
if (b == null || b === NONE) return a
val result = AND(a, b)
return if (result.opnds.size == 1) {
result.opnds[0]
} else result
}
/**
*
* @see ParserATNSimulator.getPredsForAmbigAlts
*/
fun or(a: SemanticContext?, b: SemanticContext?): SemanticContext? {
if (a == null) return b
if (b == null) return a
if (a === NONE || b === NONE) return NONE
val result = OR(a, b)
return if (result.opnds.size == 1) {
result.opnds[0]
} else result
}
private fun filterPrecedencePredicates(collection: MutableCollection): List {
var result: ArrayList? = null
val iterator = collection.iterator()
while (iterator.hasNext()) {
val context = iterator.next()
if (context is PrecedencePredicate) {
if (result == null) {
result = ArrayList()
}
result.add(context)
iterator.remove()
}
}
return result ?: emptyList()
}
}
}