omlish 0.0.0.dev57__py3-none-any.whl → 0.0.0.dev59__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. omlish/__about__.py +2 -2
  2. omlish/antlr/__init__.py +0 -0
  3. omlish/antlr/_runtime/BufferedTokenStream.py +305 -0
  4. omlish/antlr/_runtime/CommonTokenFactory.py +64 -0
  5. omlish/antlr/_runtime/CommonTokenStream.py +90 -0
  6. omlish/antlr/_runtime/FileStream.py +30 -0
  7. omlish/antlr/_runtime/InputStream.py +90 -0
  8. omlish/antlr/_runtime/IntervalSet.py +183 -0
  9. omlish/antlr/_runtime/LL1Analyzer.py +176 -0
  10. omlish/antlr/_runtime/Lexer.py +332 -0
  11. omlish/antlr/_runtime/ListTokenSource.py +147 -0
  12. omlish/antlr/_runtime/Parser.py +583 -0
  13. omlish/antlr/_runtime/ParserInterpreter.py +173 -0
  14. omlish/antlr/_runtime/ParserRuleContext.py +189 -0
  15. omlish/antlr/_runtime/PredictionContext.py +632 -0
  16. omlish/antlr/_runtime/Recognizer.py +150 -0
  17. omlish/antlr/_runtime/RuleContext.py +230 -0
  18. omlish/antlr/_runtime/StdinStream.py +14 -0
  19. omlish/antlr/_runtime/Token.py +158 -0
  20. omlish/antlr/_runtime/TokenStreamRewriter.py +258 -0
  21. omlish/antlr/_runtime/Utils.py +36 -0
  22. omlish/antlr/_runtime/__init__.py +24 -0
  23. omlish/antlr/_runtime/_pygrun.py +174 -0
  24. omlish/antlr/_runtime/atn/ATN.py +135 -0
  25. omlish/antlr/_runtime/atn/ATNConfig.py +162 -0
  26. omlish/antlr/_runtime/atn/ATNConfigSet.py +215 -0
  27. omlish/antlr/_runtime/atn/ATNDeserializationOptions.py +27 -0
  28. omlish/antlr/_runtime/atn/ATNDeserializer.py +449 -0
  29. omlish/antlr/_runtime/atn/ATNSimulator.py +50 -0
  30. omlish/antlr/_runtime/atn/ATNState.py +267 -0
  31. omlish/antlr/_runtime/atn/ATNType.py +20 -0
  32. omlish/antlr/_runtime/atn/LexerATNSimulator.py +573 -0
  33. omlish/antlr/_runtime/atn/LexerAction.py +301 -0
  34. omlish/antlr/_runtime/atn/LexerActionExecutor.py +146 -0
  35. omlish/antlr/_runtime/atn/ParserATNSimulator.py +1664 -0
  36. omlish/antlr/_runtime/atn/PredictionMode.py +502 -0
  37. omlish/antlr/_runtime/atn/SemanticContext.py +333 -0
  38. omlish/antlr/_runtime/atn/Transition.py +271 -0
  39. omlish/antlr/_runtime/atn/__init__.py +4 -0
  40. omlish/antlr/_runtime/dfa/DFA.py +136 -0
  41. omlish/antlr/_runtime/dfa/DFASerializer.py +76 -0
  42. omlish/antlr/_runtime/dfa/DFAState.py +129 -0
  43. omlish/antlr/_runtime/dfa/__init__.py +4 -0
  44. omlish/antlr/_runtime/error/DiagnosticErrorListener.py +110 -0
  45. omlish/antlr/_runtime/error/ErrorListener.py +75 -0
  46. omlish/antlr/_runtime/error/ErrorStrategy.py +712 -0
  47. omlish/antlr/_runtime/error/Errors.py +176 -0
  48. omlish/antlr/_runtime/error/__init__.py +4 -0
  49. omlish/antlr/_runtime/tree/Chunk.py +33 -0
  50. omlish/antlr/_runtime/tree/ParseTreeMatch.py +121 -0
  51. omlish/antlr/_runtime/tree/ParseTreePattern.py +75 -0
  52. omlish/antlr/_runtime/tree/ParseTreePatternMatcher.py +377 -0
  53. omlish/antlr/_runtime/tree/RuleTagToken.py +53 -0
  54. omlish/antlr/_runtime/tree/TokenTagToken.py +50 -0
  55. omlish/antlr/_runtime/tree/Tree.py +194 -0
  56. omlish/antlr/_runtime/tree/Trees.py +114 -0
  57. omlish/antlr/_runtime/tree/__init__.py +2 -0
  58. omlish/antlr/_runtime/xpath/XPath.py +272 -0
  59. omlish/antlr/_runtime/xpath/XPathLexer.py +98 -0
  60. omlish/antlr/_runtime/xpath/__init__.py +4 -0
  61. omlish/marshal/__init__.py +10 -5
  62. omlish/marshal/nop.py +18 -0
  63. omlish/marshal/primitives.py +16 -6
  64. {omlish-0.0.0.dev57.dist-info → omlish-0.0.0.dev59.dist-info}/METADATA +1 -1
  65. {omlish-0.0.0.dev57.dist-info → omlish-0.0.0.dev59.dist-info}/RECORD +69 -9
  66. {omlish-0.0.0.dev57.dist-info → omlish-0.0.0.dev59.dist-info}/LICENSE +0 -0
  67. {omlish-0.0.0.dev57.dist-info → omlish-0.0.0.dev59.dist-info}/WHEEL +0 -0
  68. {omlish-0.0.0.dev57.dist-info → omlish-0.0.0.dev59.dist-info}/entry_points.txt +0 -0
  69. {omlish-0.0.0.dev57.dist-info → omlish-0.0.0.dev59.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,712 @@
1
+ # type: ignore
2
+ # ruff: noqa
3
+ # flake8: noqa
4
+ #
5
+ # Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
6
+ # Use of this file is governed by the BSD 3-clause license that
7
+ # can be found in the LICENSE.txt file in the project root.
8
+ #
9
+ import sys
10
+ from ..IntervalSet import IntervalSet
11
+
12
+ from ..Token import Token
13
+ from ..atn.ATNState import ATNState
14
+ from .Errors import RecognitionException, NoViableAltException, InputMismatchException, \
15
+ FailedPredicateException, ParseCancellationException
16
+
17
+ # need forward declaration
18
+ Parser = None
19
+
20
+ class ErrorStrategy(object):
21
+
22
+ def reset(self, recognizer:Parser):
23
+ pass
24
+
25
+ def recoverInline(self, recognizer:Parser):
26
+ pass
27
+
28
+ def recover(self, recognizer:Parser, e:RecognitionException):
29
+ pass
30
+
31
+ def sync(self, recognizer:Parser):
32
+ pass
33
+
34
+ def inErrorRecoveryMode(self, recognizer:Parser):
35
+ pass
36
+
37
+ def reportError(self, recognizer:Parser, e:RecognitionException):
38
+ pass
39
+
40
+
41
+ # This is the default implementation of {@link ANTLRErrorStrategy} used for
42
+ # error reporting and recovery in ANTLR parsers.
43
+ #
44
+ class DefaultErrorStrategy(ErrorStrategy):
45
+
46
+ def __init__(self):
47
+ super().__init__()
48
+ # Indicates whether the error strategy is currently "recovering from an
49
+ # error". This is used to suppress reporting multiple error messages while
50
+ # attempting to recover from a detected syntax error.
51
+ #
52
+ # @see #inErrorRecoveryMode
53
+ #
54
+ self.errorRecoveryMode = False
55
+
56
+ # The index into the input stream where the last error occurred.
57
+ # This is used to prevent infinite loops where an error is found
58
+ # but no token is consumed during recovery...another error is found,
59
+ # ad nauseum. This is a failsafe mechanism to guarantee that at least
60
+ # one token/tree node is consumed for two errors.
61
+ #
62
+ self.lastErrorIndex = -1
63
+ self.lastErrorStates = None
64
+ self.nextTokensContext = None
65
+ self.nextTokenState = 0
66
+
67
+ # <p>The default implementation simply calls {@link #endErrorCondition} to
68
+ # ensure that the handler is not in error recovery mode.</p>
69
+ def reset(self, recognizer:Parser):
70
+ self.endErrorCondition(recognizer)
71
+
72
+ #
73
+ # This method is called to enter error recovery mode when a recognition
74
+ # exception is reported.
75
+ #
76
+ # @param recognizer the parser instance
77
+ #
78
+ def beginErrorCondition(self, recognizer:Parser):
79
+ self.errorRecoveryMode = True
80
+
81
+ def inErrorRecoveryMode(self, recognizer:Parser):
82
+ return self.errorRecoveryMode
83
+
84
+ #
85
+ # This method is called to leave error recovery mode after recovering from
86
+ # a recognition exception.
87
+ #
88
+ # @param recognizer
89
+ #
90
+ def endErrorCondition(self, recognizer:Parser):
91
+ self.errorRecoveryMode = False
92
+ self.lastErrorStates = None
93
+ self.lastErrorIndex = -1
94
+
95
+ #
96
+ # {@inheritDoc}
97
+ #
98
+ # <p>The default implementation simply calls {@link #endErrorCondition}.</p>
99
+ #
100
+ def reportMatch(self, recognizer:Parser):
101
+ self.endErrorCondition(recognizer)
102
+
103
+ #
104
+ # {@inheritDoc}
105
+ #
106
+ # <p>The default implementation returns immediately if the handler is already
107
+ # in error recovery mode. Otherwise, it calls {@link #beginErrorCondition}
108
+ # and dispatches the reporting task based on the runtime type of {@code e}
109
+ # according to the following table.</p>
110
+ #
111
+ # <ul>
112
+ # <li>{@link NoViableAltException}: Dispatches the call to
113
+ # {@link #reportNoViableAlternative}</li>
114
+ # <li>{@link InputMismatchException}: Dispatches the call to
115
+ # {@link #reportInputMismatch}</li>
116
+ # <li>{@link FailedPredicateException}: Dispatches the call to
117
+ # {@link #reportFailedPredicate}</li>
118
+ # <li>All other types: calls {@link Parser#notifyErrorListeners} to report
119
+ # the exception</li>
120
+ # </ul>
121
+ #
122
+ def reportError(self, recognizer:Parser, e:RecognitionException):
123
+ # if we've already reported an error and have not matched a token
124
+ # yet successfully, don't report any errors.
125
+ if self.inErrorRecoveryMode(recognizer):
126
+ return # don't report spurious errors
127
+ self.beginErrorCondition(recognizer)
128
+ if isinstance( e, NoViableAltException ):
129
+ self.reportNoViableAlternative(recognizer, e)
130
+ elif isinstance( e, InputMismatchException ):
131
+ self.reportInputMismatch(recognizer, e)
132
+ elif isinstance( e, FailedPredicateException ):
133
+ self.reportFailedPredicate(recognizer, e)
134
+ else:
135
+ print("unknown recognition error type: " + type(e).__name__)
136
+ recognizer.notifyErrorListeners(e.message, e.offendingToken, e)
137
+
138
+ #
139
+ # {@inheritDoc}
140
+ #
141
+ # <p>The default implementation resynchronizes the parser by consuming tokens
142
+ # until we find one in the resynchronization set--loosely the set of tokens
143
+ # that can follow the current rule.</p>
144
+ #
145
+ def recover(self, recognizer:Parser, e:RecognitionException):
146
+ if self.lastErrorIndex==recognizer.getInputStream().index \
147
+ and self.lastErrorStates is not None \
148
+ and recognizer.state in self.lastErrorStates:
149
+ # uh oh, another error at same token index and previously-visited
150
+ # state in ATN; must be a case where LT(1) is in the recovery
151
+ # token set so nothing got consumed. Consume a single token
152
+ # at least to prevent an infinite loop; this is a failsafe.
153
+ recognizer.consume()
154
+
155
+ self.lastErrorIndex = recognizer._input.index
156
+ if self.lastErrorStates is None:
157
+ self.lastErrorStates = []
158
+ self.lastErrorStates.append(recognizer.state)
159
+ followSet = self.getErrorRecoverySet(recognizer)
160
+ self.consumeUntil(recognizer, followSet)
161
+
162
+ # The default implementation of {@link ANTLRErrorStrategy#sync} makes sure
163
+ # that the current lookahead symbol is consistent with what were expecting
164
+ # at this point in the ATN. You can call this anytime but ANTLR only
165
+ # generates code to check before subrules/loops and each iteration.
166
+ #
167
+ # <p>Implements Jim Idle's magic sync mechanism in closures and optional
168
+ # subrules. E.g.,</p>
169
+ #
170
+ # <pre>
171
+ # a : sync ( stuff sync )* ;
172
+ # sync : {consume to what can follow sync} ;
173
+ # </pre>
174
+ #
175
+ # At the start of a sub rule upon error, {@link #sync} performs single
176
+ # token deletion, if possible. If it can't do that, it bails on the current
177
+ # rule and uses the default error recovery, which consumes until the
178
+ # resynchronization set of the current rule.
179
+ #
180
+ # <p>If the sub rule is optional ({@code (...)?}, {@code (...)*}, or block
181
+ # with an empty alternative), then the expected set includes what follows
182
+ # the subrule.</p>
183
+ #
184
+ # <p>During loop iteration, it consumes until it sees a token that can start a
185
+ # sub rule or what follows loop. Yes, that is pretty aggressive. We opt to
186
+ # stay in the loop as long as possible.</p>
187
+ #
188
+ # <p><strong>ORIGINS</strong></p>
189
+ #
190
+ # <p>Previous versions of ANTLR did a poor job of their recovery within loops.
191
+ # A single mismatch token or missing token would force the parser to bail
192
+ # out of the entire rules surrounding the loop. So, for rule</p>
193
+ #
194
+ # <pre>
195
+ # classDef : 'class' ID '{' member* '}'
196
+ # </pre>
197
+ #
198
+ # input with an extra token between members would force the parser to
199
+ # consume until it found the next class definition rather than the next
200
+ # member definition of the current class.
201
+ #
202
+ # <p>This functionality cost a little bit of effort because the parser has to
203
+ # compare token set at the start of the loop and at each iteration. If for
204
+ # some reason speed is suffering for you, you can turn off this
205
+ # functionality by simply overriding this method as a blank { }.</p>
206
+ #
207
+ def sync(self, recognizer:Parser):
208
+ # If already recovering, don't try to sync
209
+ if self.inErrorRecoveryMode(recognizer):
210
+ return
211
+
212
+ s = recognizer._interp.atn.states[recognizer.state]
213
+ la = recognizer.getTokenStream().LA(1)
214
+ # try cheaper subset first; might get lucky. seems to shave a wee bit off
215
+ nextTokens = recognizer.atn.nextTokens(s)
216
+ if la in nextTokens:
217
+ self.nextTokensContext = None
218
+ self.nextTokenState = ATNState.INVALID_STATE_NUMBER
219
+ return
220
+ elif Token.EPSILON in nextTokens:
221
+ if self.nextTokensContext is None:
222
+ # It's possible the next token won't match information tracked
223
+ # by sync is restricted for performance.
224
+ self.nextTokensContext = recognizer._ctx
225
+ self.nextTokensState = recognizer._stateNumber
226
+ return
227
+
228
+ if s.stateType in [ATNState.BLOCK_START, ATNState.STAR_BLOCK_START,
229
+ ATNState.PLUS_BLOCK_START, ATNState.STAR_LOOP_ENTRY]:
230
+ # report error and recover if possible
231
+ if self.singleTokenDeletion(recognizer)is not None:
232
+ return
233
+ else:
234
+ raise InputMismatchException(recognizer)
235
+
236
+ elif s.stateType in [ATNState.PLUS_LOOP_BACK, ATNState.STAR_LOOP_BACK]:
237
+ self.reportUnwantedToken(recognizer)
238
+ expecting = recognizer.getExpectedTokens()
239
+ whatFollowsLoopIterationOrRule = expecting.addSet(self.getErrorRecoverySet(recognizer))
240
+ self.consumeUntil(recognizer, whatFollowsLoopIterationOrRule)
241
+
242
+ else:
243
+ # do nothing if we can't identify the exact kind of ATN state
244
+ pass
245
+
246
+ # This is called by {@link #reportError} when the exception is a
247
+ # {@link NoViableAltException}.
248
+ #
249
+ # @see #reportError
250
+ #
251
+ # @param recognizer the parser instance
252
+ # @param e the recognition exception
253
+ #
254
+ def reportNoViableAlternative(self, recognizer:Parser, e:NoViableAltException):
255
+ tokens = recognizer.getTokenStream()
256
+ if tokens is not None:
257
+ if e.startToken.type==Token.EOF:
258
+ input = "<EOF>"
259
+ else:
260
+ input = tokens.getText(e.startToken, e.offendingToken)
261
+ else:
262
+ input = "<unknown input>"
263
+ msg = "no viable alternative at input " + self.escapeWSAndQuote(input)
264
+ recognizer.notifyErrorListeners(msg, e.offendingToken, e)
265
+
266
+ #
267
+ # This is called by {@link #reportError} when the exception is an
268
+ # {@link InputMismatchException}.
269
+ #
270
+ # @see #reportError
271
+ #
272
+ # @param recognizer the parser instance
273
+ # @param e the recognition exception
274
+ #
275
+ def reportInputMismatch(self, recognizer:Parser, e:InputMismatchException):
276
+ msg = "mismatched input " + self.getTokenErrorDisplay(e.offendingToken) \
277
+ + " expecting " + e.getExpectedTokens().toString(recognizer.literalNames, recognizer.symbolicNames)
278
+ recognizer.notifyErrorListeners(msg, e.offendingToken, e)
279
+
280
+ #
281
+ # This is called by {@link #reportError} when the exception is a
282
+ # {@link FailedPredicateException}.
283
+ #
284
+ # @see #reportError
285
+ #
286
+ # @param recognizer the parser instance
287
+ # @param e the recognition exception
288
+ #
289
+ def reportFailedPredicate(self, recognizer, e):
290
+ ruleName = recognizer.ruleNames[recognizer._ctx.getRuleIndex()]
291
+ msg = "rule " + ruleName + " " + e.message
292
+ recognizer.notifyErrorListeners(msg, e.offendingToken, e)
293
+
294
+ # This method is called to report a syntax error which requires the removal
295
+ # of a token from the input stream. At the time this method is called, the
296
+ # erroneous symbol is current {@code LT(1)} symbol and has not yet been
297
+ # removed from the input stream. When this method returns,
298
+ # {@code recognizer} is in error recovery mode.
299
+ #
300
+ # <p>This method is called when {@link #singleTokenDeletion} identifies
301
+ # single-token deletion as a viable recovery strategy for a mismatched
302
+ # input error.</p>
303
+ #
304
+ # <p>The default implementation simply returns if the handler is already in
305
+ # error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
306
+ # enter error recovery mode, followed by calling
307
+ # {@link Parser#notifyErrorListeners}.</p>
308
+ #
309
+ # @param recognizer the parser instance
310
+ #
311
+ def reportUnwantedToken(self, recognizer:Parser):
312
+ if self.inErrorRecoveryMode(recognizer):
313
+ return
314
+
315
+ self.beginErrorCondition(recognizer)
316
+ t = recognizer.getCurrentToken()
317
+ tokenName = self.getTokenErrorDisplay(t)
318
+ expecting = self.getExpectedTokens(recognizer)
319
+ msg = "extraneous input " + tokenName + " expecting " \
320
+ + expecting.toString(recognizer.literalNames, recognizer.symbolicNames)
321
+ recognizer.notifyErrorListeners(msg, t, None)
322
+
323
+ # This method is called to report a syntax error which requires the
324
+ # insertion of a missing token into the input stream. At the time this
325
+ # method is called, the missing token has not yet been inserted. When this
326
+ # method returns, {@code recognizer} is in error recovery mode.
327
+ #
328
+ # <p>This method is called when {@link #singleTokenInsertion} identifies
329
+ # single-token insertion as a viable recovery strategy for a mismatched
330
+ # input error.</p>
331
+ #
332
+ # <p>The default implementation simply returns if the handler is already in
333
+ # error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
334
+ # enter error recovery mode, followed by calling
335
+ # {@link Parser#notifyErrorListeners}.</p>
336
+ #
337
+ # @param recognizer the parser instance
338
+ #
339
+ def reportMissingToken(self, recognizer:Parser):
340
+ if self.inErrorRecoveryMode(recognizer):
341
+ return
342
+ self.beginErrorCondition(recognizer)
343
+ t = recognizer.getCurrentToken()
344
+ expecting = self.getExpectedTokens(recognizer)
345
+ msg = "missing " + expecting.toString(recognizer.literalNames, recognizer.symbolicNames) \
346
+ + " at " + self.getTokenErrorDisplay(t)
347
+ recognizer.notifyErrorListeners(msg, t, None)
348
+
349
+ # <p>The default implementation attempts to recover from the mismatched input
350
+ # by using single token insertion and deletion as described below. If the
351
+ # recovery attempt fails, this method throws an
352
+ # {@link InputMismatchException}.</p>
353
+ #
354
+ # <p><strong>EXTRA TOKEN</strong> (single token deletion)</p>
355
+ #
356
+ # <p>{@code LA(1)} is not what we are looking for. If {@code LA(2)} has the
357
+ # right token, however, then assume {@code LA(1)} is some extra spurious
358
+ # token and delete it. Then consume and return the next token (which was
359
+ # the {@code LA(2)} token) as the successful result of the match operation.</p>
360
+ #
361
+ # <p>This recovery strategy is implemented by {@link #singleTokenDeletion}.</p>
362
+ #
363
+ # <p><strong>MISSING TOKEN</strong> (single token insertion)</p>
364
+ #
365
+ # <p>If current token (at {@code LA(1)}) is consistent with what could come
366
+ # after the expected {@code LA(1)} token, then assume the token is missing
367
+ # and use the parser's {@link TokenFactory} to create it on the fly. The
368
+ # "insertion" is performed by returning the created token as the successful
369
+ # result of the match operation.</p>
370
+ #
371
+ # <p>This recovery strategy is implemented by {@link #singleTokenInsertion}.</p>
372
+ #
373
+ # <p><strong>EXAMPLE</strong></p>
374
+ #
375
+ # <p>For example, Input {@code i=(3;} is clearly missing the {@code ')'}. When
376
+ # the parser returns from the nested call to {@code expr}, it will have
377
+ # call chain:</p>
378
+ #
379
+ # <pre>
380
+ # stat &rarr; expr &rarr; atom
381
+ # </pre>
382
+ #
383
+ # and it will be trying to match the {@code ')'} at this point in the
384
+ # derivation:
385
+ #
386
+ # <pre>
387
+ # =&gt; ID '=' '(' INT ')' ('+' atom)* ';'
388
+ # ^
389
+ # </pre>
390
+ #
391
+ # The attempt to match {@code ')'} will fail when it sees {@code ';'} and
392
+ # call {@link #recoverInline}. To recover, it sees that {@code LA(1)==';'}
393
+ # is in the set of tokens that can follow the {@code ')'} token reference
394
+ # in rule {@code atom}. It can assume that you forgot the {@code ')'}.
395
+ #
396
+ def recoverInline(self, recognizer:Parser):
397
+ # SINGLE TOKEN DELETION
398
+ matchedSymbol = self.singleTokenDeletion(recognizer)
399
+ if matchedSymbol is not None:
400
+ # we have deleted the extra token.
401
+ # now, move past ttype token as if all were ok
402
+ recognizer.consume()
403
+ return matchedSymbol
404
+
405
+ # SINGLE TOKEN INSERTION
406
+ if self.singleTokenInsertion(recognizer):
407
+ return self.getMissingSymbol(recognizer)
408
+
409
+ # even that didn't work; must throw the exception
410
+ raise InputMismatchException(recognizer)
411
+
412
+ #
413
+ # This method implements the single-token insertion inline error recovery
414
+ # strategy. It is called by {@link #recoverInline} if the single-token
415
+ # deletion strategy fails to recover from the mismatched input. If this
416
+ # method returns {@code true}, {@code recognizer} will be in error recovery
417
+ # mode.
418
+ #
419
+ # <p>This method determines whether or not single-token insertion is viable by
420
+ # checking if the {@code LA(1)} input symbol could be successfully matched
421
+ # if it were instead the {@code LA(2)} symbol. If this method returns
422
+ # {@code true}, the caller is responsible for creating and inserting a
423
+ # token with the correct type to produce this behavior.</p>
424
+ #
425
+ # @param recognizer the parser instance
426
+ # @return {@code true} if single-token insertion is a viable recovery
427
+ # strategy for the current mismatched input, otherwise {@code false}
428
+ #
429
+ def singleTokenInsertion(self, recognizer:Parser):
430
+ currentSymbolType = recognizer.getTokenStream().LA(1)
431
+ # if current token is consistent with what could come after current
432
+ # ATN state, then we know we're missing a token; error recovery
433
+ # is free to conjure up and insert the missing token
434
+ atn = recognizer._interp.atn
435
+ currentState = atn.states[recognizer.state]
436
+ next = currentState.transitions[0].target
437
+ expectingAtLL2 = atn.nextTokens(next, recognizer._ctx)
438
+ if currentSymbolType in expectingAtLL2:
439
+ self.reportMissingToken(recognizer)
440
+ return True
441
+ else:
442
+ return False
443
+
444
+ # This method implements the single-token deletion inline error recovery
445
+ # strategy. It is called by {@link #recoverInline} to attempt to recover
446
+ # from mismatched input. If this method returns null, the parser and error
447
+ # handler state will not have changed. If this method returns non-null,
448
+ # {@code recognizer} will <em>not</em> be in error recovery mode since the
449
+ # returned token was a successful match.
450
+ #
451
+ # <p>If the single-token deletion is successful, this method calls
452
+ # {@link #reportUnwantedToken} to report the error, followed by
453
+ # {@link Parser#consume} to actually "delete" the extraneous token. Then,
454
+ # before returning {@link #reportMatch} is called to signal a successful
455
+ # match.</p>
456
+ #
457
+ # @param recognizer the parser instance
458
+ # @return the successfully matched {@link Token} instance if single-token
459
+ # deletion successfully recovers from the mismatched input, otherwise
460
+ # {@code null}
461
+ #
462
+ def singleTokenDeletion(self, recognizer:Parser):
463
+ nextTokenType = recognizer.getTokenStream().LA(2)
464
+ expecting = self.getExpectedTokens(recognizer)
465
+ if nextTokenType in expecting:
466
+ self.reportUnwantedToken(recognizer)
467
+ # print("recoverFromMismatchedToken deleting " \
468
+ # + str(recognizer.getTokenStream().LT(1)) \
469
+ # + " since " + str(recognizer.getTokenStream().LT(2)) \
470
+ # + " is what we want", file=sys.stderr)
471
+ recognizer.consume() # simply delete extra token
472
+ # we want to return the token we're actually matching
473
+ matchedSymbol = recognizer.getCurrentToken()
474
+ self.reportMatch(recognizer) # we know current token is correct
475
+ return matchedSymbol
476
+ else:
477
+ return None
478
+
479
+ # Conjure up a missing token during error recovery.
480
+ #
481
+ # The recognizer attempts to recover from single missing
482
+ # symbols. But, actions might refer to that missing symbol.
483
+ # For example, x=ID {f($x);}. The action clearly assumes
484
+ # that there has been an identifier matched previously and that
485
+ # $x points at that token. If that token is missing, but
486
+ # the next token in the stream is what we want we assume that
487
+ # this token is missing and we keep going. Because we
488
+ # have to return some token to replace the missing token,
489
+ # we have to conjure one up. This method gives the user control
490
+ # over the tokens returned for missing tokens. Mostly,
491
+ # you will want to create something special for identifier
492
+ # tokens. For literals such as '{' and ',', the default
493
+ # action in the parser or tree parser works. It simply creates
494
+ # a CommonToken of the appropriate type. The text will be the token.
495
+ # If you change what tokens must be created by the lexer,
496
+ # override this method to create the appropriate tokens.
497
+ #
498
+ def getMissingSymbol(self, recognizer:Parser):
499
+ currentSymbol = recognizer.getCurrentToken()
500
+ expecting = self.getExpectedTokens(recognizer)
501
+ expectedTokenType = expecting[0] # get any element
502
+ if expectedTokenType==Token.EOF:
503
+ tokenText = "<missing EOF>"
504
+ else:
505
+ name = None
506
+ if expectedTokenType < len(recognizer.literalNames):
507
+ name = recognizer.literalNames[expectedTokenType]
508
+ if name is None and expectedTokenType < len(recognizer.symbolicNames):
509
+ name = recognizer.symbolicNames[expectedTokenType]
510
+ tokenText = "<missing " + str(name) + ">"
511
+ current = currentSymbol
512
+ lookback = recognizer.getTokenStream().LT(-1)
513
+ if current.type==Token.EOF and lookback is not None:
514
+ current = lookback
515
+ return recognizer.getTokenFactory().create(current.source,
516
+ expectedTokenType, tokenText, Token.DEFAULT_CHANNEL,
517
+ -1, -1, current.line, current.column)
518
+
519
+ def getExpectedTokens(self, recognizer:Parser):
520
+ return recognizer.getExpectedTokens()
521
+
522
+ # How should a token be displayed in an error message? The default
523
+ # is to display just the text, but during development you might
524
+ # want to have a lot of information spit out. Override in that case
525
+ # to use t.toString() (which, for CommonToken, dumps everything about
526
+ # the token). This is better than forcing you to override a method in
527
+ # your token objects because you don't have to go modify your lexer
528
+ # so that it creates a new Java type.
529
+ #
530
+ def getTokenErrorDisplay(self, t:Token):
531
+ if t is None:
532
+ return "<no token>"
533
+ s = t.text
534
+ if s is None:
535
+ if t.type==Token.EOF:
536
+ s = "<EOF>"
537
+ else:
538
+ s = "<" + str(t.type) + ">"
539
+ return self.escapeWSAndQuote(s)
540
+
541
+ def escapeWSAndQuote(self, s:str):
542
+ s = s.replace("\n","\\n")
543
+ s = s.replace("\r","\\r")
544
+ s = s.replace("\t","\\t")
545
+ return "'" + s + "'"
546
+
547
+ # Compute the error recovery set for the current rule. During
548
+ # rule invocation, the parser pushes the set of tokens that can
549
+ # follow that rule reference on the stack; this amounts to
550
+ # computing FIRST of what follows the rule reference in the
551
+ # enclosing rule. See LinearApproximator.FIRST().
552
+ # This local follow set only includes tokens
553
+ # from within the rule; i.e., the FIRST computation done by
554
+ # ANTLR stops at the end of a rule.
555
+ #
556
+ # EXAMPLE
557
+ #
558
+ # When you find a "no viable alt exception", the input is not
559
+ # consistent with any of the alternatives for rule r. The best
560
+ # thing to do is to consume tokens until you see something that
561
+ # can legally follow a call to r#or* any rule that called r.
562
+ # You don't want the exact set of viable next tokens because the
563
+ # input might just be missing a token--you might consume the
564
+ # rest of the input looking for one of the missing tokens.
565
+ #
566
+ # Consider grammar:
567
+ #
568
+ # a : '[' b ']'
569
+ # | '(' b ')'
570
+ # ;
571
+ # b : c '^' INT ;
572
+ # c : ID
573
+ # | INT
574
+ # ;
575
+ #
576
+ # At each rule invocation, the set of tokens that could follow
577
+ # that rule is pushed on a stack. Here are the various
578
+ # context-sensitive follow sets:
579
+ #
580
+ # FOLLOW(b1_in_a) = FIRST(']') = ']'
581
+ # FOLLOW(b2_in_a) = FIRST(')') = ')'
582
+ # FOLLOW(c_in_b) = FIRST('^') = '^'
583
+ #
584
+ # Upon erroneous input "[]", the call chain is
585
+ #
586
+ # a -> b -> c
587
+ #
588
+ # and, hence, the follow context stack is:
589
+ #
590
+ # depth follow set start of rule execution
591
+ # 0 <EOF> a (from main())
592
+ # 1 ']' b
593
+ # 2 '^' c
594
+ #
595
+ # Notice that ')' is not included, because b would have to have
596
+ # been called from a different context in rule a for ')' to be
597
+ # included.
598
+ #
599
+ # For error recovery, we cannot consider FOLLOW(c)
600
+ # (context-sensitive or otherwise). We need the combined set of
601
+ # all context-sensitive FOLLOW sets--the set of all tokens that
602
+ # could follow any reference in the call chain. We need to
603
+ # resync to one of those tokens. Note that FOLLOW(c)='^' and if
604
+ # we resync'd to that token, we'd consume until EOF. We need to
605
+ # sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
606
+ # In this case, for input "[]", LA(1) is ']' and in the set, so we would
607
+ # not consume anything. After printing an error, rule c would
608
+ # return normally. Rule b would not find the required '^' though.
609
+ # At this point, it gets a mismatched token error and throws an
610
+ # exception (since LA(1) is not in the viable following token
611
+ # set). The rule exception handler tries to recover, but finds
612
+ # the same recovery set and doesn't consume anything. Rule b
613
+ # exits normally returning to rule a. Now it finds the ']' (and
614
+ # with the successful match exits errorRecovery mode).
615
+ #
616
+ # So, you can see that the parser walks up the call chain looking
617
+ # for the token that was a member of the recovery set.
618
+ #
619
+ # Errors are not generated in errorRecovery mode.
620
+ #
621
+ # ANTLR's error recovery mechanism is based upon original ideas:
622
+ #
623
+ # "Algorithms + Data Structures = Programs" by Niklaus Wirth
624
+ #
625
+ # and
626
+ #
627
+ # "A note on error recovery in recursive descent parsers":
628
+ # http:#portal.acm.org/citation.cfm?id=947902.947905
629
+ #
630
+ # Later, Josef Grosch had some good ideas:
631
+ #
632
+ # "Efficient and Comfortable Error Recovery in Recursive Descent
633
+ # Parsers":
634
+ # ftp:#www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
635
+ #
636
+ # Like Grosch I implement context-sensitive FOLLOW sets that are combined
637
+ # at run-time upon error to avoid overhead during parsing.
638
+ #
639
+ def getErrorRecoverySet(self, recognizer:Parser):
640
+ atn = recognizer._interp.atn
641
+ ctx = recognizer._ctx
642
+ recoverSet = IntervalSet()
643
+ while ctx is not None and ctx.invokingState>=0:
644
+ # compute what follows who invoked us
645
+ invokingState = atn.states[ctx.invokingState]
646
+ rt = invokingState.transitions[0]
647
+ follow = atn.nextTokens(rt.followState)
648
+ recoverSet.addSet(follow)
649
+ ctx = ctx.parentCtx
650
+ recoverSet.removeOne(Token.EPSILON)
651
+ return recoverSet
652
+
653
+ # Consume tokens until one matches the given token set.#
654
+ def consumeUntil(self, recognizer:Parser, set_:set):
655
+ ttype = recognizer.getTokenStream().LA(1)
656
+ while ttype != Token.EOF and not ttype in set_:
657
+ recognizer.consume()
658
+ ttype = recognizer.getTokenStream().LA(1)
659
+
660
+
661
+ #
662
+ # This implementation of {@link ANTLRErrorStrategy} responds to syntax errors
663
+ # by immediately canceling the parse operation with a
664
+ # {@link ParseCancellationException}. The implementation ensures that the
665
+ # {@link ParserRuleContext#exception} field is set for all parse tree nodes
666
+ # that were not completed prior to encountering the error.
667
+ #
668
+ # <p>
669
+ # This error strategy is useful in the following scenarios.</p>
670
+ #
671
+ # <ul>
672
+ # <li><strong>Two-stage parsing:</strong> This error strategy allows the first
673
+ # stage of two-stage parsing to immediately terminate if an error is
674
+ # encountered, and immediately fall back to the second stage. In addition to
675
+ # avoiding wasted work by attempting to recover from errors here, the empty
676
+ # implementation of {@link BailErrorStrategy#sync} improves the performance of
677
+ # the first stage.</li>
678
+ # <li><strong>Silent validation:</strong> When syntax errors are not being
679
+ # reported or logged, and the parse result is simply ignored if errors occur,
680
+ # the {@link BailErrorStrategy} avoids wasting work on recovering from errors
681
+ # when the result will be ignored either way.</li>
682
+ # </ul>
683
+ #
684
+ # <p>
685
+ # {@code myparser.setErrorHandler(new BailErrorStrategy());}</p>
686
+ #
687
+ # @see Parser#setErrorHandler(ANTLRErrorStrategy)
688
+ #
689
+ class BailErrorStrategy(DefaultErrorStrategy):
690
+ # Instead of recovering from exception {@code e}, re-throw it wrapped
691
+ # in a {@link ParseCancellationException} so it is not caught by the
692
+ # rule function catches. Use {@link Exception#getCause()} to get the
693
+ # original {@link RecognitionException}.
694
+ #
695
+ def recover(self, recognizer:Parser, e:RecognitionException):
696
+ context = recognizer._ctx
697
+ while context is not None:
698
+ context.exception = e
699
+ context = context.parentCtx
700
+ raise ParseCancellationException(e)
701
+
702
+ # Make sure we don't attempt to recover inline; if the parser
703
+ # successfully recovers, it won't throw an exception.
704
+ #
705
+ def recoverInline(self, recognizer:Parser):
706
+ self.recover(recognizer, InputMismatchException(recognizer))
707
+
708
+ # Make sure we don't attempt to recover from problems in subrules.#
709
+ def sync(self, recognizer:Parser):
710
+ pass
711
+
712
+ del Parser