antlr4 0.9.2

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