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

[Swift] Make ATNDeserializationOptions a simple struct. #2155

Merged
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
93 changes: 39 additions & 54 deletions runtime/Swift/Sources/Antlr4/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,21 @@

import Foundation

///
///
/// This field maps from the serialized ATN string to the deserialized _org.antlr.v4.runtime.atn.ATN_ with
/// bypass alternatives.
///
/// - SeeAlso: `ATNDeserializationOptions.generateRuleBypassTransitions`
///
private var bypassAltsAtnCache = [String: ATN]()

///
/// mutex for bypassAltsAtnCache updates
///
private let bypassAltsAtnCacheMutex = Mutex()


///
/// This is all the parsing support code essentially; most of it is error recovery stuff.
///
open class Parser: Recognizer<ParserATNSimulator> {
Expand Down Expand Up @@ -58,25 +72,6 @@ open class Parser: Recognizer<ParserATNSimulator> {
}
}

///
/// mutex for bypassAltsAtnCache updates
///
private let bypassAltsAtnCacheMutex = Mutex()

///
/// mutex for decisionToDFA updates
///
private let decisionToDFAMutex = Mutex()

///
/// This field maps from the serialized ATN string to the deserialized _org.antlr.v4.runtime.atn.ATN_ with
/// bypass alternatives.
///
/// - SeeAlso: org.antlr.v4.runtime.atn.ATNDeserializationOptions#isGenerateRuleBypassTransitions()
///
private let bypassAltsAtnCache: HashMap<String, ATN> = HashMap<String, ATN>()


///
/// The error handling strategy for the parser. The default value is a new
/// instance of _org.antlr.v4.runtime.DefaultErrorStrategy_.
Expand Down Expand Up @@ -417,23 +412,21 @@ open class Parser: Recognizer<ParserATNSimulator> {
///
/// The ATN with bypass alternatives is expensive to create so we create it
/// lazily.
///
/// - Throws: _ANTLRError.unsupportedOperation_ if the current parser does not
/// implement the _#getSerializedATN()_ method.
///
///
public func getATNWithBypassAlts() -> ATN {
let serializedAtn = getSerializedATN()

var result = bypassAltsAtnCache[serializedAtn]
bypassAltsAtnCacheMutex.synchronized { [unowned self] in
if result == nil {
let deserializationOptions = ATNDeserializationOptions()
try! deserializationOptions.setGenerateRuleBypassTransitions(true)
result = try! ATNDeserializer(deserializationOptions).deserialize(Array(serializedAtn))
self.bypassAltsAtnCache[serializedAtn] = result!
return bypassAltsAtnCacheMutex.synchronized {
if let cachedResult = bypassAltsAtnCache[serializedAtn] {
return cachedResult
}

var opts = ATNDeserializationOptions()
opts.generateRuleBypassTransitions = true
let result = try! ATNDeserializer(opts).deserialize(Array(serializedAtn))
bypassAltsAtnCache[serializedAtn] = result
return result
}
return result!
}

///
Expand Down Expand Up @@ -965,38 +958,30 @@ open class Parser: Recognizer<ParserATNSimulator> {

/// For debugging and other purposes.
public func getDFAStrings() -> [String] {
var s = [String]()
guard let _interp = _interp else {
return s
guard let _interp = _interp else {
return []
}
decisionToDFAMutex.synchronized { [unowned self] in
for d in 0..<_interp.decisionToDFA.count {
let dfa = _interp.decisionToDFA[d]
s.append(dfa.toString(self.getVocabulary()))
}

let vocab = getVocabulary()
return _interp.decisionToDFA.map {
$0.toString(vocab)
}
return s
}

/// For debugging and other purposes.
public func dumpDFA() {
guard let _interp = _interp else {
return
}
decisionToDFAMutex.synchronized { [unowned self] in
var seenOne = false

for dfa in _interp.decisionToDFA {
if !dfa.states.isEmpty {
if seenOne {
print("")
}
print("Decision \(dfa.decision):")

print(dfa.toString(self.getVocabulary()), terminator: "")
seenOne = true
var seenOne = false
let vocab = getVocabulary()
for dfa in _interp.decisionToDFA {
if !dfa.states.isEmpty {
if seenOne {
print("")
}
print("Decision \(dfa.decision):")
print(dfa.toString(vocab), terminator: "")
seenOne = true
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions runtime/Swift/Sources/Antlr4/atn/ATN.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ public class ATN {
///
/// For lexer ATNs, this maps the rule index to the resulting token type.
/// For parser ATNs, this maps the rule index to the generated bypass token
/// type if the
/// _org.antlr.v4.runtime.atn.ATNDeserializationOptions#isGenerateRuleBypassTransitions_
/// type if the `ATNDeserializationOptions.generateRuleBypassTransitions`
/// deserialization option was specified; otherwise, this is `null`.
///
public final var ruleToTokenType: [Int]!
Expand Down
10 changes: 5 additions & 5 deletions runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ public class ATNConfigSet: Hashable, CustomStringConvertible {

public final func getConflictingAltSubsets() -> [BitSet] {
let length = configs.count
let configToAlts = HashMap<Int, BitSet>(count: length)
var configToAlts = [Int: BitSet]()

for i in 0..<length {
let hash = configHash(configs[i].state.stateNumber, configs[i].context)
Expand All @@ -318,12 +318,12 @@ public class ATNConfigSet: Hashable, CustomStringConvertible {
try! alts.set(configs[i].alt)
}

return configToAlts.values
return Array(configToAlts.values)
}

public final func getStateToAltMap() -> HashMap<ATNState, BitSet> {
public final func getStateToAltMap() -> [ATNState: BitSet] {
let length = configs.count
let m = HashMap<ATNState, BitSet>(count: length)
var m = [ATNState: BitSet]()

for i in 0..<length {
var alts: BitSet
Expand Down Expand Up @@ -412,7 +412,7 @@ public class ATNConfigSet: Hashable, CustomStringConvertible {
public final func applyPrecedenceFilter(_ mergeCache: inout DoubleKeyMap<PredictionContext, PredictionContext, PredictionContext>?,_ parser: Parser,_ _outerContext: ParserRuleContext!) throws -> ATNConfigSet {

let configSet = ATNConfigSet(fullCtx)
let statesFromAlt1 = HashMap<Int, PredictionContext>(count: configs.count)
var statesFromAlt1 = [Int: PredictionContext]()
for config in configs {
// handle alt 1 first
if config.alt != 1 {
Expand Down
72 changes: 3 additions & 69 deletions runtime/Swift/Sources/Antlr4/atn/ATNDeserializationOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,7 @@
/// can be found in the LICENSE.txt file in the project root.
///



///
///
/// - Sam Harwell
///

public class ATNDeserializationOptions {

static let defaultOptions: ATNDeserializationOptions = {

let defaultOptions = ATNDeserializationOptions()
defaultOptions.makeReadOnly()
return defaultOptions

}()


private var readOnly: Bool = false
private var verifyATN: Bool
private var generateRuleBypassTransitions: Bool

public init() {
self.verifyATN = true
self.generateRuleBypassTransitions = false
}

public init(_ options: ATNDeserializationOptions) {
self.verifyATN = options.verifyATN
self.generateRuleBypassTransitions = options.generateRuleBypassTransitions
}


public static func getDefaultOptions() -> ATNDeserializationOptions {
return defaultOptions
}

public final func isReadOnly() -> Bool {
return readOnly
}

public final func makeReadOnly() {
readOnly = true
}

public final func isVerifyATN() -> Bool {
return verifyATN
}

public final func setVerifyATN(_ verifyATN: Bool) throws {
try throwIfReadOnly()
self.verifyATN = verifyATN
}

public final func isGenerateRuleBypassTransitions() -> Bool {
return generateRuleBypassTransitions
}

public final func setGenerateRuleBypassTransitions(_ generateRuleBypassTransitions: Bool) throws {
try throwIfReadOnly()
self.generateRuleBypassTransitions = generateRuleBypassTransitions
}

internal func throwIfReadOnly() throws {
if isReadOnly() {
throw ANTLRError.illegalState(msg: "This object is readonly")

}
}
public struct ATNDeserializationOptions {
public var verifyATN = true
public var generateRuleBypassTransitions = false
}
8 changes: 4 additions & 4 deletions runtime/Swift/Sources/Antlr4/atn/ATNDeserializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class ATNDeserializer {
private let deserializationOptions: ATNDeserializationOptions

public init(_ deserializationOptions: ATNDeserializationOptions? = nil) {
self.deserializationOptions = deserializationOptions ?? ATNDeserializationOptions.getDefaultOptions()
self.deserializationOptions = deserializationOptions ?? ATNDeserializationOptions()
}

///
Expand Down Expand Up @@ -667,13 +667,13 @@ public class ATNDeserializer {

private func finalizeATN(_ atn: ATN) throws {
markPrecedenceDecisions(atn)
if deserializationOptions.isVerifyATN() {
if deserializationOptions.verifyATN {
try verifyATN(atn)
}
if deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType.parser {
if deserializationOptions.generateRuleBypassTransitions && atn.grammarType == ATNType.parser {
try generateRuleBypassTransitions(atn)

if deserializationOptions.isVerifyATN() {
if deserializationOptions.verifyATN {
// reverify after modification
try verifyATN(atn)
}
Expand Down
5 changes: 2 additions & 3 deletions runtime/Swift/Sources/Antlr4/atn/ATNSimulator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,10 @@ open class ATNSimulator {
open func getCachedContext(_ context: PredictionContext) -> PredictionContext {
//TODO: synced (sharedContextCache!)
//synced (sharedContextCache!) {
let visited = HashMap<PredictionContext, PredictionContext>()

var visited = [PredictionContext: PredictionContext]()
return PredictionContext.getCachedContext(context,
sharedContextCache,
visited)
&visited)
}

public static func edgeFactory(_ atn: ATN,
Expand Down
2 changes: 1 addition & 1 deletion runtime/Swift/Sources/Antlr4/atn/LexerATNSimulator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ open class LexerATNSimulator: ATNSimulator {

return dfaStatesMutex.synchronized {
if let existing = dfa.states[proposed] {
return existing!
return existing
}

let newState = proposed
Expand Down
Loading