1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 2 * Use of this file is governed by the BSD 3-clause license that 3 * can be found in the LICENSE.txt file in the project root. 4 */ 5 6 7 /// A rule context is a record of a single rule invocation. 8 /// 9 /// We form a stack of these context objects using the parent 10 /// pointer. A parent pointer of null indicates that the current 11 /// context is the bottom of the stack. The ParserRuleContext subclass 12 /// as a children list so that we can turn this data structure into a 13 /// tree. 14 /// 15 /// The root node always has a null pointer and invokingState of -1. 16 /// 17 /// Upon entry to parsing, the first invoked rule function creates a 18 /// context object (asubclass specialized for that rule such as 19 /// SContext) and makes it the root of a parse tree, recorded by field 20 /// Parser._ctx. 21 /// 22 /// public final SContext s() throws RecognitionException { 23 /// SContext _localctx = new SContext(_ctx, getState()); <-- create new node 24 /// enterRule(_localctx, 0, RULE_s); <-- push it 25 /// ... 26 /// exitRule(); <-- pop back to _localctx 27 /// return _localctx; 28 /// } 29 /// 30 /// A subsequent rule invocation of r from the start rule s pushes a 31 /// new context object for r whose parent points at s and use invoking 32 /// state is the state with r emanating as edge label. 33 /// 34 /// The invokingState fields from a context object to the root 35 /// together form a stack of rule indication states where the root 36 /// (bottom of the stack) has a -1 sentinel value. If we invoke start 37 /// symbol s then call r1, which calls r2, the would look like 38 /// this: 39 /// 40 /// SContext[-1] <- root node (bottom of the stack) 41 /// R1Context[p] <- p in rule s called r1 42 /// R2Context[q] <- q in rule r1 called r2 43 /// 44 /// So the top of the stack, _ctx, represents a call to the current 45 /// rule and it holds the return address from another rule that invoke 46 /// to this rule. To invoke a rule, we must always have a current context. 47 /// 48 /// The parent contexts are useful for computing lookahead sets and 49 /// getting error information. 50 /// 51 /// These objects are used during parsing and prediction. 52 /// For the special case of parsers, we use the subclass 53 /// ParserRuleContext. 54 /// 55 /// - SeeAlso: org.antlr.v4.runtime.ParserRuleContext 56 /// 57 58 open class RuleContext: RuleNode { 59 public static let EMPTY = ParserRuleContext() 60 61 /// What context invoked this rule? 62 public weak var parent: RuleContext? 63 64 /// What state invoked the rule associated with this context? 65 /// The "return address" is the followState of invokingState 66 /// If parent is null, this should be -1 this context object represents 67 /// the start rule. 68 /// 69 public var invokingState = -1 70 71 public init() { 72 } 73 74 public init(_ parent: RuleContext?, _ invokingState: Int) { 75 self.parent = parent 76 //if ( parent!=null ) { print("invoke "+stateNumber+" from "+parent)} 77 self.invokingState = invokingState 78 } 79 depthnull80 open func depth() -> Int { 81 var n = 0 82 var p: RuleContext? = self 83 while let pWrap = p { 84 p = pWrap.parent 85 n += 1 86 } 87 return n 88 } 89 90 /// A context is empty if there is no invoking state; meaning nobody called 91 /// current context. 92 /// isEmptynull93 open func isEmpty() -> Bool { 94 return invokingState == -1 95 } 96 97 // satisfy the ParseTree / SyntaxTree interface 98 getSourceIntervalnull99 open func getSourceInterval() -> Interval { 100 return Interval.INVALID 101 } 102 getRuleContextnull103 open func getRuleContext() -> RuleContext { 104 return self 105 } 106 getParentnull107 open func getParent() -> Tree? { 108 return parent 109 } 110 setParentnull111 open func setParent(_ parent: RuleContext) { 112 self.parent = parent 113 } 114 getPayloadnull115 open func getPayload() -> AnyObject { 116 return self 117 } 118 119 /// Return the combined text of all child nodes. This method only considers 120 /// tokens which have been added to the parse tree. 121 /// 122 /// Since tokens on hidden channels (e.g. whitespace or comments) are not 123 /// added to the parse trees, they will not appear in the output of this 124 /// method. 125 /// 126 getTextnull127 open func getText() -> String { 128 let length = getChildCount() 129 if length == 0 { 130 return "" 131 } 132 133 var builder = "" 134 for i in 0..<length { 135 builder += self[i].getText() 136 } 137 138 return builder 139 } 140 getRuleIndexnull141 open func getRuleIndex() -> Int { 142 return -1 143 } 144 getAltNumbernull145 open func getAltNumber() -> Int { return ATN.INVALID_ALT_NUMBER } setAltNumbernull146 open func setAltNumber(_ altNumber: Int) { } 147 getChildnull148 open func getChild(_ i: Int) -> Tree? { 149 return nil 150 } 151 152 getChildCountnull153 open func getChildCount() -> Int { 154 return 0 155 } 156 157 158 open subscript(index: Int) -> ParseTree { 159 preconditionFailure("Index out of range (RuleContext never has children, though its subclasses may).") 160 } 161 162 accept<T>null163 open func accept<T>(_ visitor: ParseTreeVisitor<T>) -> T? { 164 return visitor.visitChildren(self) 165 } 166 167 /// Print out a whole tree, not just a node, in LISP format 168 /// (root child1 .. childN). Print just a node if this is a leaf. 169 /// We have to know the recognizer so we can get rule names. 170 /// toStringTreenull171 open func toStringTree(_ recog: Parser) -> String { 172 return Trees.toStringTree(self, recog) 173 } 174 175 /// Print out a whole tree, not just a node, in LISP format 176 /// (root child1 .. childN). Print just a node if this is a leaf. 177 /// toStringTreenull178 public func toStringTree(_ ruleNames: [String]?) -> String { 179 return Trees.toStringTree(self, ruleNames) 180 } 181 toStringTreenull182 open func toStringTree() -> String { 183 return toStringTree(nil) 184 } 185 186 open var description: String { 187 return toString(nil, nil) 188 } 189 190 open var debugDescription: String { 191 return description 192 } 193 toString<T>null194 public final func toString<T>(_ recog: Recognizer<T>) -> String { 195 return toString(recog, ParserRuleContext.EMPTY) 196 } 197 toStringnull198 public final func toString(_ ruleNames: [String]) -> String { 199 return toString(ruleNames, nil) 200 } 201 202 // recog null unless ParserRuleContext, in which case we use subclass toString(...) toString<T>null203 open func toString<T>(_ recog: Recognizer<T>?, _ stop: RuleContext) -> String { 204 let ruleNames = recog?.getRuleNames() 205 return toString(ruleNames, stop) 206 } 207 toStringnull208 open func toString(_ ruleNames: [String]?, _ stop: RuleContext?) -> String { 209 var buf = "" 210 var p: RuleContext? = self 211 buf += "[" 212 while let pWrap = p, pWrap !== stop { 213 if let ruleNames = ruleNames { 214 let ruleIndex = pWrap.getRuleIndex() 215 let ruleIndexInRange = (ruleIndex >= 0 && ruleIndex < ruleNames.count) 216 let ruleName = (ruleIndexInRange ? ruleNames[ruleIndex] : String(ruleIndex)) 217 buf += ruleName 218 } 219 else { 220 if !pWrap.isEmpty() { 221 buf += String(pWrap.invokingState) 222 } 223 } 224 225 if pWrap.parent != nil && (ruleNames != nil || !pWrap.parent!.isEmpty()) { 226 buf += " " 227 } 228 229 p = pWrap.parent 230 } 231 232 buf += "]" 233 return buf 234 } 235 castdown<T>null236 open func castdown<T>(_ subType: T.Type) -> T { 237 return self as! T 238 } 239 240 } 241