antlr4 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +27 -0
  3. data/README.md +46 -0
  4. data/lib/antlr4.rb +262 -0
  5. data/lib/antlr4/BufferedTokenStream.rb +306 -0
  6. data/lib/antlr4/CommonTokenFactory.rb +53 -0
  7. data/lib/antlr4/CommonTokenStream.rb +56 -0
  8. data/lib/antlr4/FileStream.rb +14 -0
  9. data/lib/antlr4/InputStream.rb +82 -0
  10. data/lib/antlr4/IntervalSet.rb +341 -0
  11. data/lib/antlr4/LL1Analyzer.rb +177 -0
  12. data/lib/antlr4/Lexer.rb +335 -0
  13. data/lib/antlr4/ListTokenSource.rb +140 -0
  14. data/lib/antlr4/Parser.rb +562 -0
  15. data/lib/antlr4/ParserInterpreter.rb +149 -0
  16. data/lib/antlr4/ParserRuleContext.rb +162 -0
  17. data/lib/antlr4/PredictionContext.rb +690 -0
  18. data/lib/antlr4/Recognizer.rb +162 -0
  19. data/lib/antlr4/RuleContext.rb +226 -0
  20. data/lib/antlr4/Token.rb +124 -0
  21. data/lib/antlr4/TokenFactory.rb +3 -0
  22. data/lib/antlr4/TokenSource.rb +4 -0
  23. data/lib/antlr4/TokenStream.rb +3 -0
  24. data/lib/antlr4/TraceListener.rb +23 -0
  25. data/lib/antlr4/atn/ATN.rb +133 -0
  26. data/lib/antlr4/atn/ATNConfig.rb +146 -0
  27. data/lib/antlr4/atn/ATNConfigSet.rb +215 -0
  28. data/lib/antlr4/atn/ATNDeserializationOptions.rb +62 -0
  29. data/lib/antlr4/atn/ATNDeserializer.rb +604 -0
  30. data/lib/antlr4/atn/ATNSimulator.rb +43 -0
  31. data/lib/antlr4/atn/ATNState.rb +253 -0
  32. data/lib/antlr4/atn/ATNType.rb +22 -0
  33. data/lib/antlr4/atn/LexerATNSimulator.rb +612 -0
  34. data/lib/antlr4/atn/LexerAction.rb +311 -0
  35. data/lib/antlr4/atn/LexerActionExecutor.rb +134 -0
  36. data/lib/antlr4/atn/ParserATNSimulator.rb +1622 -0
  37. data/lib/antlr4/atn/PredictionMode.rb +525 -0
  38. data/lib/antlr4/atn/SemanticContext.rb +355 -0
  39. data/lib/antlr4/atn/Transition.rb +297 -0
  40. data/lib/antlr4/base.rb +60 -0
  41. data/lib/antlr4/dfa/DFA.rb +128 -0
  42. data/lib/antlr4/dfa/DFASerializer.rb +77 -0
  43. data/lib/antlr4/dfa/DFAState.rb +133 -0
  44. data/lib/antlr4/error.rb +151 -0
  45. data/lib/antlr4/error/DiagnosticErrorListener.rb +136 -0
  46. data/lib/antlr4/error/ErrorListener.rb +109 -0
  47. data/lib/antlr4/error/ErrorStrategy.rb +742 -0
  48. data/lib/antlr4/tree/Chunk.rb +31 -0
  49. data/lib/antlr4/tree/ParseTreeMatch.rb +105 -0
  50. data/lib/antlr4/tree/ParseTreePattern.rb +70 -0
  51. data/lib/antlr4/tree/ParseTreePatternMatcher.rb +334 -0
  52. data/lib/antlr4/tree/RuleTagToken.rb +39 -0
  53. data/lib/antlr4/tree/TokenTagToken.rb +38 -0
  54. data/lib/antlr4/tree/Tree.rb +204 -0
  55. data/lib/antlr4/tree/Trees.rb +111 -0
  56. data/lib/antlr4/version.rb +5 -0
  57. data/lib/antlr4/xpath/XPath.rb +354 -0
  58. data/lib/double_key_map.rb +78 -0
  59. data/lib/java_symbols.rb +24 -0
  60. data/lib/uuid.rb +87 -0
  61. data/test/test_intervalset.rb +664 -0
  62. data/test/test_tree.rb +140 -0
  63. data/test/test_uuid.rb +122 -0
  64. metadata +109 -0
@@ -0,0 +1,140 @@
1
+ #
2
+ # Provides an implementation of {@link TokenSource} as a wrapper around a list
3
+ # of {@link Token} objects.
4
+ #
5
+ # <p>If the final token in the list is an {@link Token#EOF} token, it will be used
6
+ # as the EOF token for every call to {@link #nextToken} after the end of the
7
+ # list is reached. Otherwise, an EOF token will be created.</p>
8
+
9
+ class ListTokenSource < TokenSource
10
+
11
+ # Constructs a new {@link ListTokenSource} instance from the specified
12
+ # collection of {@link Token} objects and source name.
13
+ #
14
+ # @param tokens The collection of {@link Token} objects to provide as a
15
+ # {@link TokenSource}.
16
+ # @param sourceName The name of the {@link TokenSource}. If this value is
17
+ # {@code null}, {@link #getSourceName} will attempt to infer the name from
18
+ # the next {@link Token} (or the previous token if the end of the input has
19
+ # been reached).
20
+ #
21
+ # @exception NullPointerException if {@code tokens} is {@code null}
22
+ attr_accessor :tokens, :sourceName, :pos, :eofToken, :factory
23
+ def initialize(_tokens, source_name=nil)
24
+ raise ReferenceError.new("tokens cannot be null") if tokens.nil?
25
+ @tokens = _tokens
26
+ @sourceName = source_name
27
+ # The index into {@link #tokens} of token to return by the next call to
28
+ # {@link #nextToken}. The end of the input is indicated by this value
29
+ # being greater than or equal to the number of items in {@link #tokens}.
30
+ @pos = 0
31
+ # This field caches the EOF token for the token source.
32
+ @eofToken = nil
33
+ # This is the backing field for {@link #getTokenFactory} and
34
+ @factory = CommonTokenFactory.DEFAULT
35
+ end
36
+
37
+
38
+ #
39
+ # {@inheritDoc}
40
+ #
41
+ def column
42
+ if self.pos < self.tokens.length
43
+ return self.tokens[self.pos].column
44
+ elsif not self.eofToken.nil?
45
+ return self.eofToken.column
46
+ elsif self.tokens.length > 0
47
+ # have to calculate the result from the line/column of the previous
48
+ # token, along with the text of the token.
49
+ lastToken = self.tokens[-1]
50
+ tokenText = lastToken.getText()
51
+ if not tokenText.nil? then
52
+ lastNewLine = tokenText.rfind('\n')
53
+ if lastNewLine >= 0
54
+ return tokenText.length - lastNewLine - 1
55
+ end
56
+ end
57
+ return lastToken.column + lastToken.stopIndex - lastToken.startIndex + 1
58
+ end
59
+ # only reach this if tokens is empty, meaning EOF occurs at the first
60
+ # position in the input
61
+ return 0
62
+ end
63
+ #
64
+ # {@inheritDoc}
65
+ #
66
+ def nextToken
67
+ if self.pos >= self.tokens.length then
68
+ if self.eofToken.nil? then
69
+ start = -1
70
+ if self.tokens.length > 0 then
71
+ previousStop = self.tokens[-1].stopIndex
72
+ if previousStop != -1 then
73
+ start = previousStop + 1
74
+ end
75
+ end
76
+ stop = [-1, start - 1].max
77
+ self.eofToken = self.factory.create([self, self.getInputStream()],
78
+ Token::EOF, "EOF", Token::DEFAULT_CHANNEL, start, stop, self.line, self.column)
79
+ stop = [-1, start - 1].max
80
+ end
81
+ return self.eofToken
82
+ end
83
+ t = self.tokens[self.pos]
84
+ if self.pos == self.tokens.length - 1 and t.type == Token::EOF
85
+ eofToken = t
86
+ end
87
+ self.pos = self.pos + 1
88
+ return t
89
+ end
90
+ def line
91
+ if self.pos < self.tokens.length
92
+ return self.tokens[self.pos].line
93
+ elsif not self.eofToken.nil?
94
+ return self.eofToken.line
95
+ elsif self.tokens.length > 0
96
+ # have to calculate the result from the line/column of the previous
97
+ # token, along with the text of the token.
98
+ lastToken = self.tokens[-1]
99
+ line = lastToken.line
100
+ tokenText = lastToken.text
101
+ if not tokenText.nil? then
102
+ for c in tokenText do
103
+ if c == '\n'
104
+ line = line + 1
105
+ end
106
+ end
107
+ end
108
+ # if no text is available, assume the token did not contain any newline characters.
109
+ return line
110
+ end
111
+ # only reach this if tokens is empty, meaning EOF occurs at the first
112
+ # position in the input
113
+ return 1
114
+ end
115
+ #
116
+ # {@inheritDoc}
117
+ #
118
+ def getInputStream
119
+ if self.pos < self.tokens.length
120
+ return self.tokens[self.pos].getInputStream()
121
+ elsif not self.eofToken.nil?
122
+ return self.eofToken.getInputStream()
123
+ elsif self.tokens.length > 0
124
+ return self.tokens[-1].getInputStream()
125
+ else
126
+ # no input stream information is available
127
+ return nil
128
+ end
129
+ end
130
+
131
+ def getSourceName
132
+ return self.sourceName unless self.sourceName.nil?
133
+ inputStream = self.getInputStream()
134
+ if not inputStream.nil?
135
+ return inputStream.getSourceName()
136
+ else
137
+ return "List"
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,562 @@
1
+ # self is all the parsing support code essentially; most of it is error recovery stuff.#
2
+ class Parser < Recognizer
3
+
4
+ # self field maps from the serialized ATN string to the deserialized {@link ATN} with
5
+ # bypass alternatives.
6
+ #
7
+ # @see ATNDeserializationOptions#isGenerateRuleBypassTransitions()
8
+ #
9
+ @@bypassAltsAtnCache = Hash.new
10
+
11
+ attr_accessor :input,:errHandler,:precedenceStack ,:ctx, :buildParseTrees
12
+ attr_accessor :tracer, :parseListeners, :syntaxErrors
13
+ attr_accessor :tokenNames
14
+ def initialize(input)
15
+ super()
16
+ # The input stream.
17
+ self.input = nil
18
+ # The error handling strategy for the parser. The default value is a new
19
+ # instance of {@link DefaultErrorStrategy}.
20
+ self.errHandler = DefaultErrorStrategy.new()
21
+ @precedenceStack = Array.new()
22
+ @precedenceStack.push(0)
23
+ # The {@link ParserRuleContext} object for the currently executing rule.
24
+ # self is always non-null during the parsing process.
25
+ @ctx = nil
26
+ # Specifies whether or not the parser should construct a parse tree during
27
+ # the parsing process. The default value is {@code true}.
28
+ @buildParseTrees = true
29
+ # When {@link #setTrace}{@code (true)} is called, a reference to the
30
+ # {@link TraceListener} is stored here so it can be easily removed in a
31
+ # later call to {@link #setTrace}{@code (false)}. The listener itself is
32
+ # implemented as a parser listener so self field is not directly used by
33
+ # other parser methods.
34
+ @tracer = nil
35
+ # The list of {@link ParseTreeListener} listeners registered to receive
36
+ # events during the parse.
37
+ @parseListeners = Array.new()
38
+ # The number of syntax errors reported during parsing. self value is
39
+ # incremented each time {@link #notifyErrorListeners} is called.
40
+ @syntaxErrors = 0
41
+ self.setInputStream(input)
42
+ end
43
+
44
+ # reset the parser's state#
45
+ def reset()
46
+ self.input.seek(0) unless @input.nil?
47
+ @errHandler.reset(self)
48
+ @ctx = nil
49
+ @syntaxErrors = 0
50
+ self.setTrace(false)
51
+ @precedenceStack = Array.new
52
+ @precedenceStack.push(0)
53
+ @interp.reset() unless @interp.nil?
54
+ end
55
+
56
+ # Match current input symbol against {@code ttype}. If the symbol type
57
+ # matches, {@link ANTLRErrorStrategy#reportMatch} and {@link #consume} are
58
+ # called to complete the match process.
59
+ #
60
+ # <p>If the symbol type does not match,
61
+ # {@link ANTLRErrorStrategy#recoverInline} is called on the current error
62
+ # strategy to attempt recovery. If {@link #getBuildParseTree} is
63
+ # {@code true} and the token index of the symbol returned by
64
+ # {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to
65
+ # the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p>
66
+ #
67
+ # @param ttype the token type to match
68
+ # @return the matched symbol
69
+ # @throws RecognitionException if the current input symbol did not match
70
+ # {@code ttype} and the error strategy could not recover from the
71
+ # mismatched symbol
72
+
73
+ def match(ttype)
74
+ t = self.getCurrentToken()
75
+ if t.type==ttype
76
+ self.errHandler.reportMatch(self)
77
+ self.consume()
78
+ else
79
+ t = self.errHandler.recoverInline(self)
80
+ if self.buildParseTrees and t.tokenIndex==-1
81
+ # we must have conjured up a new token during single token insertion
82
+ # if it's not the current symbol
83
+ self.ctx.addErrorNode(t)
84
+ end
85
+ end
86
+ return t
87
+ end
88
+
89
+ # Match current input symbol as a wildcard. If the symbol type matches
90
+ # (i.e. has a value greater than 0), {@link ANTLRErrorStrategy#reportMatch}
91
+ # and {@link #consume} are called to complete the match process.
92
+ #
93
+ # <p>If the symbol type does not match,
94
+ # {@link ANTLRErrorStrategy#recoverInline} is called on the current error
95
+ # strategy to attempt recovery. If {@link #getBuildParseTree} is
96
+ # {@code true} and the token index of the symbol returned by
97
+ # {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to
98
+ # the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p>
99
+ #
100
+ # @return the matched symbol
101
+ # @throws RecognitionException if the current input symbol did not match
102
+ # a wildcard and the error strategy could not recover from the mismatched
103
+ # symbol
104
+
105
+ def matchWildcard()
106
+ t = self.getCurrentToken()
107
+ if t.type > 0 then
108
+ self.errHandler.reportMatch(self)
109
+ self.consume()
110
+ else
111
+ t = self.errHandler.recoverInline(self)
112
+ if self.buildParseTrees and t.tokenIndex == -1 then
113
+ # we must have conjured up a new token during single token insertion
114
+ # if it's not the current symbol
115
+ self.ctx.addErrorNode(t)
116
+ end
117
+ end
118
+ return t
119
+ end
120
+
121
+ def getParseListeners
122
+ self.parseListeners
123
+ end
124
+
125
+ # Registers {@code listener} to receive events during the parsing process.
126
+ #
127
+ # <p>To support output-preserving grammar transformations (including but not
128
+ # limited to left-recursion removal, automated left-factoring, and
129
+ # optimized code generation), calls to listener methods during the parse
130
+ # may differ substantially from calls made by
131
+ # {@link ParseTreeWalker#DEFAULT} used after the parse is complete. In
132
+ # particular, rule entry and exit events may occur in a different order
133
+ # during the parse than after the parser. In addition, calls to certain
134
+ # rule entry methods may be omitted.</p>
135
+ #
136
+ # <p>With the following specific exceptions, calls to listener events are
137
+ # <em>deterministic</em>, i.e. for identical input the calls to listener
138
+ # methods will be the same.</p>
139
+ #
140
+ # <ul>
141
+ # <li>Alterations to the grammar used to generate code may change the
142
+ # behavior of the listener calls.</li>
143
+ # <li>Alterations to the command line options passed to ANTLR 4 when
144
+ # generating the parser may change the behavior of the listener calls.</li>
145
+ # <li>Changing the version of the ANTLR Tool used to generate the parser
146
+ # may change the behavior of the listener calls.</li>
147
+ # </ul>
148
+ #
149
+ # @param listener the listener to add
150
+ #
151
+ # @throws NullPointerException if {@code} listener is {@code null}
152
+ #
153
+ def addParseListener(listener)
154
+ raise ReferenceError.new("listener is nil") if listener.nil?
155
+ # @parseListeners = Array.new if @parseListeners.nil?
156
+ self.parseListeners.push(listener)
157
+ end
158
+
159
+ #
160
+ # Remove {@code listener} from the list of parse listeners.
161
+ #
162
+ # <p>If {@code listener} is {@code null} or has not been added as a parse
163
+ # listener, self method does nothing.</p>
164
+ # @param listener the listener to remove
165
+ #
166
+ def removeParseListener(listener)
167
+ # return if self.parseListeners.nil?
168
+ self.parseListeners.delete(listener)
169
+ end
170
+
171
+ # Remove all parse listeners.
172
+ def removeParseListeners
173
+ @parseListeners = Array.new
174
+ end
175
+
176
+ # Notify any parse listeners of an enter rule event.
177
+ def triggerEnterRuleEvent
178
+ self.parseListeners do |listener|
179
+ listener.enterEveryRule(self.ctx)
180
+ self.ctx.enterRule(listener)
181
+ end
182
+ end
183
+
184
+ #
185
+ # Notify any parse listeners of an exit rule event.
186
+ #
187
+ # @see #addParseListener
188
+ #
189
+ def triggerExitRuleEvent
190
+ # reverse order walk of listeners
191
+ self.parseListeners.reverse do |listener|
192
+ self.ctx.exitRule(listener)
193
+ listener.exitEveryRule(self.ctx)
194
+ end
195
+ end
196
+
197
+
198
+ def getTokenFactory
199
+ return self.input.tokenSource.factory
200
+ end
201
+
202
+ # Tell our token source and error strategy about a new way to create tokens.#
203
+ def setTokenFactory(factory)
204
+ self.input.tokenSource.factory = factory
205
+ end
206
+
207
+ # The ATN with bypass alternatives is expensive to create so we create it
208
+ # lazily.
209
+ #
210
+ # @throws UnsupportedOperationException if the current parser does not
211
+ # implement the {@link #getSerializedATN()} method.
212
+ #
213
+ def getATNWithBypassAlts()
214
+ serializedAtn = self.getSerializedATN()
215
+ if serializedAtn.nil?
216
+ raise UnsupportedOperationException.new("The current parser does not support an ATN with bypass alternatives.")
217
+ end
218
+ result = self.bypassAltsAtnCache.get(serializedAtn)
219
+ if result.nil? then
220
+ deserializationOptions = ATNDeserializationOptions.new()
221
+ deserializationOptions.generateRuleBypassTransitions = true
222
+ result = ATNDeserializer(deserializationOptions).deserialize(serializedAtn)
223
+ self.bypassAltsAtnCache[serializedAtn] = result
224
+ end
225
+ return result
226
+ end
227
+
228
+ # The preferred method of getting a tree pattern. For example, here's a
229
+ # sample use:
230
+ #
231
+ # <pre>
232
+ # ParseTree t = parser.expr();
233
+ # ParseTreePattern p = parser.compileParseTreePattern("&lt;ID&gt;+0", MyParser.RULE_expr);
234
+ # ParseTreeMatch m = p.match(t);
235
+ # String id = m.get("ID");
236
+ # </pre>
237
+ #
238
+ def compileParseTreePattern(pattern, patternRuleIndex, lexer=nil)
239
+ if lexer.nil? then
240
+ if not self.getTokenStream().nil? then
241
+ tokenSource = self.getTokenStream().getTokenSource()
242
+ end
243
+ lexer = tokenSource if tokenSource.kind_of? Lexer
244
+ end
245
+ if lexer.nil?
246
+ raise UnsupportedOperationException.new("Parser can't discover a lexer to use")
247
+ end
248
+ m = ParseTreePatternMatcher.new(lexer, self)
249
+ return m.compile(pattern, patternRuleIndex)
250
+ end
251
+
252
+ def getInputStream()
253
+ return self.getTokenStream()
254
+ end
255
+
256
+ def setInputStream(input)
257
+ self.setTokenStream(input)
258
+ end
259
+
260
+ def getTokenStream()
261
+ return self.input
262
+ end
263
+
264
+ # Set the token stream and reset the parser.#
265
+ def setTokenStream(input)
266
+ self.input = nil
267
+ self.reset()
268
+ self.input = input
269
+ end
270
+ # Match needs to return the current input symbol, which gets put
271
+ # into the label for the associated token ref; e.g., x=ID.
272
+ #
273
+ def getCurrentToken()
274
+ return self.input.LT(1)
275
+ end
276
+
277
+ def notifyErrorListeners(msg, offendingToken=nil ,e=nil) #RecognitionException
278
+ if offendingToken.nil?
279
+ offendingToken = self.getCurrentToken()
280
+ end
281
+ @syntaxErrors = @syntaxErrors + 1
282
+ line = offendingToken.line
283
+ column = offendingToken.column
284
+ listener = self.getErrorListenerDispatch()
285
+ listener.syntaxError(self, offendingToken, line, column, msg, e)
286
+ end
287
+ #
288
+ # Consume and return the {@linkplain #getCurrentToken current symbol}.
289
+ #
290
+ # <p>E.g., given the following input with {@code A} being the current
291
+ # lookahead symbol, self function moves the cursor to {@code B} and returns
292
+ # {@code A}.</p>
293
+ #
294
+ # <pre>
295
+ # A B
296
+ # ^
297
+ # </pre>
298
+ #
299
+ # If the parser is not in error recovery mode, the consumed symbol is added
300
+ # to the parse tree using {@link ParserRuleContext#addChild(Token)}, and
301
+ # {@link ParseTreeListener#visitTerminal} is called on any parse listeners.
302
+ # If the parser <em>is</em> in error recovery mode, the consumed symbol is
303
+ # added to the parse tree using
304
+ # {@link ParserRuleContext#addErrorNode(Token)}, and
305
+ # {@link ParseTreeListener#visitErrorNode} is called on any parse
306
+ # listeners.
307
+ #
308
+ def consume()
309
+ o = self.getCurrentToken()
310
+ if o.type != Token::EOF then
311
+ self.getInputStream().consume()
312
+ end
313
+ hasListener = ! self.parseListeners.empty?
314
+ if self.buildParseTrees or hasListener then
315
+ if self.errHandler.inErrorRecoveryMode(self) then
316
+ node = self.ctx.addErrorNode(o)
317
+ else
318
+ node = self.ctx.addTokenNode(o)
319
+ end
320
+ self.parseListeners.each {|listener| listener.visitTerminal(node) }
321
+ end
322
+ return o
323
+ end
324
+
325
+ def addContextToParseTree()
326
+ # add current context to parent if we have a parent
327
+ if self.ctx.parentCtx then
328
+ self.ctx.parentCtx.addChild(self.ctx)
329
+ end
330
+ end
331
+ # Always called by generated parsers upon entry to a rule. Access field
332
+ # {@link #ctx} get the current context.
333
+ #
334
+ def enterRule(localctx, state, ruleIndex)
335
+ self.state = state
336
+ self.ctx = localctx
337
+ self.ctx.start = self.input.LT(1)
338
+ self.addContextToParseTree() if self.buildParseTrees
339
+ self.triggerEnterRuleEvent()
340
+ end
341
+
342
+ def exitRule()
343
+ self.ctx.stop = self.input.LT(-1)
344
+ # trigger event on ctx, before it reverts to parent
345
+ self.triggerExitRuleEvent()
346
+ self.state = self.ctx.invokingState
347
+ self.ctx = self.ctx.parentCtx
348
+ end
349
+
350
+ def enterOuterAlt(localctx, altNum)
351
+ # if we have new localctx, make sure we replace existing ctx
352
+ # that is previous child of parse tree
353
+ if self.buildParseTrees and self.ctx != localctx
354
+ if not self.ctx.parentCtx.nil? then
355
+ self.ctx.parentCtx.removeLastChild()
356
+ self.ctx.parentCtx.addChild(localctx)
357
+ end
358
+ end
359
+ self.ctx = localctx
360
+ end
361
+
362
+ # Get the precedence level for the top-most precedence rule.
363
+ #
364
+ # @return The precedence level for the top-most precedence rule, or -1 if
365
+ # the parser context is not nested within a precedence rule.
366
+ #
367
+ def getPrecedence()
368
+ if @precedenceStack.length==0
369
+ return -1
370
+ else
371
+ return @precedenceStack[-1]
372
+ end
373
+ end
374
+
375
+ def enterRecursionRule(localctx, state, ruleIndex, precedence)
376
+ self.state = state
377
+ self.precedenceStack.push(precedence)
378
+ self.ctx = localctx
379
+ self.ctx.start = self.input.LT(1)
380
+ self.triggerEnterRuleEvent() # simulates rule entry for left-recursive rules
381
+ end
382
+
383
+ #
384
+ # Like {@link #enterRule} but for recursive rules.
385
+ #
386
+ def pushNewRecursionContext(localctx, state, ruleIndex)
387
+ previous = self.ctx
388
+ previous.parentCtx = localctx
389
+ previous.invokingState = state
390
+ previous.stop = self.input.LT(-1)
391
+
392
+ self.ctx = localctx
393
+ self.ctx.start = previous.start
394
+ self.ctx.addChild(previous) if self.buildParseTrees
395
+ self.triggerEnterRuleEvent() # simulates rule entry for left-recursive rules
396
+ end
397
+
398
+ def unrollRecursionContexts(parentCtx)
399
+ self.precedenceStack.pop()
400
+ self.ctx.stop = self.input.LT(-1)
401
+ retCtx = self.ctx # save current ctx (return value)
402
+ # unroll so ctx is as it was before call to recursive method
403
+ if not self.parseListeners.empty? then
404
+ while self.ctx != parentCtx do
405
+ self.triggerExitRuleEvent()
406
+ self.ctx = self.ctx.parentCtx
407
+ end
408
+ else
409
+ self.ctx = parentCtx
410
+ end
411
+ # hook into tree
412
+ retCtx.parentCtx = parentCtx
413
+
414
+ if self.buildParseTrees and parentCtx then
415
+ # add return ctx into invoking rule's tree
416
+ parentCtx.addChild(retCtx)
417
+ end
418
+ end
419
+ def getInvokingContext(ruleIndex)
420
+ ctx = self.ctx
421
+ while not ctx.nil? do
422
+ if ctx.ruleIndex == ruleIndex
423
+ return ctx
424
+ end
425
+ ctx = ctx.parentCtx
426
+ end
427
+ return nil
428
+ end
429
+
430
+
431
+ def precpred(localctx, precedence)
432
+ return precedence >= self.precedenceStack[-1]
433
+ end
434
+
435
+ def inContext(context)
436
+ # TODO: useful in parser?
437
+ return false
438
+ end
439
+
440
+ #
441
+ # Checks whether or not {@code symbol} can follow the current state in the
442
+ # ATN. The behavior of self method is equivalent to the following, but is
443
+ # implemented such that the complete context-sensitive follow set does not
444
+ # need to be explicitly constructed.
445
+ #
446
+ # <pre>
447
+ # return getExpectedTokens().contains(symbol);
448
+ # </pre>
449
+ #
450
+ # @param symbol the symbol type to check
451
+ # @return {@code true} if {@code symbol} can follow the current state in
452
+ # the ATN, otherwise {@code false}.
453
+ #
454
+ def isExpectedToken(symbol)
455
+ atn = self.interp.atn
456
+ ctx = self.ctx
457
+ s = atn.states[self.state]
458
+ following = atn.nextTokens(s)
459
+ # print "\nisExpectedToken: #{following.toString(tokenNames)}: #{s}"
460
+ if following.member?(symbol) then
461
+ # puts " true "
462
+ return true
463
+ end
464
+ if not following.member? Token::EPSILON then
465
+ # puts " FAIL "
466
+ return false
467
+ end
468
+ while ctx and ctx.invokingState >= 0 and following.member?(Token::EPSILON) do
469
+ invokingState = atn.states[ctx.invokingState]
470
+ rt = invokingState.transitions[0]
471
+ following = atn.nextTokens(rt.followState)
472
+ return true if following.member?(symbol)
473
+ ctx = ctx.parentCtx
474
+ end
475
+ if following.member?( Token::EPSILON) and symbol == Token::EOF
476
+ return true
477
+ else
478
+ return false
479
+ end
480
+ end
481
+ # Computes the set of input symbols which could follow the current parser
482
+ # state and context, as given by {@link #getState} and {@link #getContext},
483
+ # respectively.
484
+ #
485
+ # @see ATN#getExpectedTokens(int, RuleContext)
486
+ #
487
+ def getExpectedTokens()
488
+ return self.interp.atn.getExpectedTokens(self.state, self.ctx)
489
+ end
490
+
491
+ def getExpectedTokensWithinCurrentRule()
492
+ atn = self.interp.atn
493
+ s = atn.states[self.state]
494
+ return atn.nextTokens(s)
495
+ end
496
+
497
+ # Get a rule's index (i.e., {@code RULE_ruleName} field) or -1 if not found.#
498
+ def getRuleIndex(ruleName)
499
+ ruleIndex = self.getRuleIndexMap().get(ruleName)
500
+ if ruleIndex then
501
+ return ruleIndex
502
+ else
503
+ return -1
504
+ end
505
+ end
506
+
507
+ # Return List&lt;String&gt; of the rule names in your parser instance
508
+ # leading up to a call to the current rule. You could override if
509
+ # you want more details such as the file/line info of where
510
+ # in the ATN a rule is invoked.
511
+ #
512
+ # this is very useful for error messages.
513
+ #
514
+ def getRuleInvocationStack(p=nil)
515
+ p = self.ctx if p.nil?
516
+ stack = Array.new
517
+ while p do
518
+ # compute what follows who invoked us
519
+ ruleIndex = p.getRuleIndex()
520
+ if ruleIndex<0
521
+ stack.push("n/a")
522
+ else
523
+ stack.push(self.ruleNames[ruleIndex])
524
+ end
525
+ p = p.parentCtx
526
+ end
527
+ return stack
528
+ end
529
+ # For debugging and other purposes.#
530
+ def getDFAStrings
531
+ self.interp.decisionToDFA.map {|dfa| dfa.to_s }
532
+ end
533
+ # For debugging and other purposes.#
534
+ def dumpDFA()
535
+ seenOne = false
536
+ self.interp.decisionToDFA.each {|dfa|
537
+ if dfa.states.length > 0
538
+ puts "Decision #{dfa.decision}:"
539
+ puts dfa.toString(self.tokenNames)
540
+ end
541
+ }
542
+ end
543
+ def getSourceName
544
+ return self.input.sourceName
545
+ end
546
+
547
+ # During a parse is sometimes useful to listen in on the rule entry and exit
548
+ # events as well as token matches. self is for quick and dirty debugging.
549
+ #
550
+ def setTrace(trace)
551
+ if not trace then
552
+ self.removeParseListener(self.tracer)
553
+ self.tracer = nil
554
+ else
555
+ if self.tracer
556
+ self.removeParseListener(self.tracer)
557
+ end
558
+ self.tracer = TraceListener.new(self)
559
+ self.addParseListener(self.tracer)
560
+ end
561
+ end
562
+ end