From c9508b74a4e661fd07c96cc8e29dca8f1abfae24 Mon Sep 17 00:00:00 2001
From: janyou
Date: Wed, 14 Dec 2016 09:09:40 +0800
Subject: [PATCH] Fixes #1238, Fixes #994
---
.../v4/runtime/BufferedTokenStream.swift | 4 +-
.../v4/runtime/atn/ParserATNSimulator.swift | 176 +++++++++++++++++-
2 files changed, 175 insertions(+), 5 deletions(-)
diff --git a/runtime/Swift/Antlr4/org/antlr/v4/runtime/BufferedTokenStream.swift b/runtime/Swift/Antlr4/org/antlr/v4/runtime/BufferedTokenStream.swift
index 1c1122812..1f0ed2c44 100644
--- a/runtime/Swift/Antlr4/org/antlr/v4/runtime/BufferedTokenStream.swift
+++ b/runtime/Swift/Antlr4/org/antlr/v4/runtime/BufferedTokenStream.swift
@@ -473,8 +473,6 @@ public class BufferedTokenStream: TokenStream {
public func getText() throws -> String {
- try lazyInit()
- try fill()
return try getText(Interval.of(0, size() - 1))
}
@@ -485,7 +483,7 @@ public class BufferedTokenStream: TokenStream {
if start < 0 || stop < 0 {
return ""
}
- try lazyInit()
+ try fill()
if stop >= tokens.count {
stop = tokens.count - 1
}
diff --git a/runtime/Swift/Antlr4/org/antlr/v4/runtime/atn/ParserATNSimulator.swift b/runtime/Swift/Antlr4/org/antlr/v4/runtime/atn/ParserATNSimulator.swift
index 4e7ff246c..3488bff0a 100644
--- a/runtime/Swift/Antlr4/org/antlr/v4/runtime/atn/ParserATNSimulator.swift
+++ b/runtime/Swift/Antlr4/org/antlr/v4/runtime/atn/ParserATNSimulator.swift
@@ -232,13 +232,20 @@
* both SLL and LL parsing. Erroneous input will therefore require 2 passes over
* the input.
*/
+import Foundation
open class ParserATNSimulator: ATNSimulator {
public let debug: Bool = false
public let debug_list_atn_decisions: Bool = false
public let dfa_debug: Bool = false
public let retry_debug: Bool = false
-
+ /** Just in case this optimization is bad, add an ENV variable to turn it off */
+ public static let TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT: Bool = {
+ if let value = ProcessInfo.processInfo.environment["TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT"] {
+ return NSString(string: value).boolValue
+ }
+ return false
+ }()
internal final var parser: Parser
public final var decisionToDFA: [DFA]
@@ -1441,6 +1448,10 @@ open class ParserATNSimulator: ATNSimulator {
}
let length = p.getNumberOfTransitions()
for i in 0.. Bool {
+ if ParserATNSimulator.TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT {
+ return false
+ }
+ let p: ATNState = config.state
+ guard let configContext = config.context else {
+ return false
+ }
+ // First check to see if we are in StarLoopEntryState generated during
+ // left-recursion elimination. For efficiency, also check if
+ // the context has an empty stack case. If so, it would mean
+ // global FOLLOW so we can't perform optimization
+ if p.getStateType() != ATNState.STAR_LOOP_ENTRY ||
+ !( (p as! StarLoopEntryState)).precedenceRuleDecision || // Are we the special loop entry/exit state?
+ configContext.isEmpty() || // If SLL wildcard
+ configContext.hasEmptyPath(){
+ return false
+ }
+
+ // Require all return states to return back to the same rule
+ // that p is in.
+ let numCtxs: Int = configContext.size()
+ for i in 0 ..< numCtxs { // for each stack context
+ let returnState: ATNState = atn.states[configContext.getReturnState(i)]!
+ if returnState.ruleIndex != p.ruleIndex
+ {return false}
+ }
+
+ let decisionStartState: BlockStartState = (p.transition(0).target as! BlockStartState)
+ let blockEndStateNum: Int = decisionStartState.endState!.stateNumber
+ let blockEndState: BlockEndState = (atn.states[blockEndStateNum] as! BlockEndState)
+
+ // Verify that the top of each stack context leads to loop entry/exit
+ // state through epsilon edges and w/o leaving rule.
+ for i in 0 ..< numCtxs { // for each stack context
+ let returnStateNumber: Int = configContext.getReturnState(i)
+ let returnState: ATNState = atn.states[returnStateNumber]!
+ // all states must have single outgoing epsilon edge
+ if returnState.getNumberOfTransitions() != 1 || !returnState.transition(0).isEpsilon(){
+ return false
+ }
+ // Look for prefix op case like 'not expr', (' type ')' expr
+ let returnStateTarget: ATNState = returnState.transition(0).target
+ if returnState.getStateType() == ATNState.BLOCK_END &&
+ returnStateTarget == p {
+ continue
+ }
+ // Look for 'expr op expr' or case where expr's return state is block end
+ // of (...)* internal block; the block end points to loop back
+ // which points to p but we don't need to check that
+ if returnState == blockEndState{
+ continue
+ }
+ // Look for ternary expr ? expr : expr. The return state points at block end,
+ // which points at loop entry state
+ if returnStateTarget == blockEndState{
+ continue
+ }
+ // Look for complex prefix 'between expr and expr' case where 2nd expr's
+ // return state points at block end state of (...)* internal block
+ if returnStateTarget.getStateType() == ATNState.BLOCK_END &&
+ returnStateTarget.getNumberOfTransitions() == 1 &&
+ returnStateTarget.transition(0).isEpsilon() &&
+ returnStateTarget.transition(0).target == p{
+ continue
+ }
+
+ // anything else ain't conforming
+ return false
+ }
+
+ return true
+ }
+
open func getRuleName(_ index: Int) -> String {
if index >= 0 {
return parser.getRuleNames()[index]