calabash-android 0.4.0.pre1 → 0.4.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/bin/calabash-android-build.rb +6 -0
  2. data/bin/calabash-android-setup.rb +2 -3
  3. data/lib/calabash-android/canned_steps.md +1 -1
  4. data/lib/calabash-android/helpers.rb +35 -2
  5. data/lib/calabash-android/lib/TestServer.apk +0 -0
  6. data/lib/calabash-android/operations.rb +13 -6
  7. data/lib/calabash-android/version.rb +1 -1
  8. data/test-server/instrumentation-backend/.classpath +2 -1
  9. data/test-server/instrumentation-backend/antlr.sh +2 -0
  10. data/test-server/instrumentation-backend/antlr/UIQuery.g +70 -0
  11. data/test-server/instrumentation-backend/antlr/UIQuery.tokens +12 -0
  12. data/test-server/instrumentation-backend/build-libs/antlr-3.4-complete.jar +0 -0
  13. data/test-server/instrumentation-backend/build-libs/junit.jar +0 -0
  14. data/test-server/instrumentation-backend/build.xml +56 -0
  15. data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRFileStream.java +78 -0
  16. data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRInputStream.java +70 -0
  17. data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRReaderStream.java +95 -0
  18. data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRStringStream.java +230 -0
  19. data/test-server/instrumentation-backend/src/org/antlr/runtime/BaseRecognizer.java +894 -0
  20. data/test-server/instrumentation-backend/src/org/antlr/runtime/BitSet.java +325 -0
  21. data/test-server/instrumentation-backend/src/org/antlr/runtime/BufferedTokenStream.java +272 -0
  22. data/test-server/instrumentation-backend/src/org/antlr/runtime/CharStream.java +57 -0
  23. data/test-server/instrumentation-backend/src/org/antlr/runtime/CharStreamState.java +45 -0
  24. data/test-server/instrumentation-backend/src/org/antlr/runtime/ClassicToken.java +141 -0
  25. data/test-server/instrumentation-backend/src/org/antlr/runtime/CommonToken.java +191 -0
  26. data/test-server/instrumentation-backend/src/org/antlr/runtime/CommonTokenStream.java +153 -0
  27. data/test-server/instrumentation-backend/src/org/antlr/runtime/DFA.java +250 -0
  28. data/test-server/instrumentation-backend/src/org/antlr/runtime/EarlyExitException.java +41 -0
  29. data/test-server/instrumentation-backend/src/org/antlr/runtime/FailedPredicateException.java +54 -0
  30. data/test-server/instrumentation-backend/src/org/antlr/runtime/IntStream.java +122 -0
  31. data/test-server/instrumentation-backend/src/org/antlr/runtime/LegacyCommonTokenStream.java +394 -0
  32. data/test-server/instrumentation-backend/src/org/antlr/runtime/Lexer.java +340 -0
  33. data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedNotSetException.java +41 -0
  34. data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedRangeException.java +45 -0
  35. data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedSetException.java +44 -0
  36. data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedTokenException.java +45 -0
  37. data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedTreeNodeException.java +49 -0
  38. data/test-server/instrumentation-backend/src/org/antlr/runtime/MissingTokenException.java +56 -0
  39. data/test-server/instrumentation-backend/src/org/antlr/runtime/NoViableAltException.java +57 -0
  40. data/test-server/instrumentation-backend/src/org/antlr/runtime/Parser.java +98 -0
  41. data/test-server/instrumentation-backend/src/org/antlr/runtime/ParserRuleReturnScope.java +52 -0
  42. data/test-server/instrumentation-backend/src/org/antlr/runtime/RecognitionException.java +180 -0
  43. data/test-server/instrumentation-backend/src/org/antlr/runtime/RecognizerSharedState.java +144 -0
  44. data/test-server/instrumentation-backend/src/org/antlr/runtime/RuleReturnScope.java +42 -0
  45. data/test-server/instrumentation-backend/src/org/antlr/runtime/SerializedGrammar.java +204 -0
  46. data/test-server/instrumentation-backend/src/org/antlr/runtime/Token.java +92 -0
  47. data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenRewriteStream.java +569 -0
  48. data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenSource.java +54 -0
  49. data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenStream.java +75 -0
  50. data/test-server/instrumentation-backend/src/org/antlr/runtime/UnbufferedTokenStream.java +82 -0
  51. data/test-server/instrumentation-backend/src/org/antlr/runtime/UnwantedTokenException.java +53 -0
  52. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/BlankDebugEventListener.java +77 -0
  53. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventHub.java +292 -0
  54. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventListener.java +323 -0
  55. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventRepeater.java +88 -0
  56. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventSocketProxy.java +358 -0
  57. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugParser.java +101 -0
  58. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTokenStream.java +156 -0
  59. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeAdaptor.java +250 -0
  60. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeNodeStream.java +155 -0
  61. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeParser.java +112 -0
  62. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/ParseTreeBuilder.java +109 -0
  63. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/Profiler.java +772 -0
  64. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/RemoteDebugEventSocketListener.java +541 -0
  65. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/TraceDebugEventListener.java +108 -0
  66. data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/Tracer.java +69 -0
  67. data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/DoubleKeyMap.java +62 -0
  68. data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/FastQueue.java +100 -0
  69. data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/IntArray.java +87 -0
  70. data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/LookaheadStream.java +161 -0
  71. data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/Stats.java +189 -0
  72. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BaseTree.java +349 -0
  73. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BaseTreeAdaptor.java +279 -0
  74. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BufferedTreeNodeStream.java +489 -0
  75. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonErrorNode.java +108 -0
  76. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTree.java +185 -0
  77. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTreeAdaptor.java +168 -0
  78. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTreeNodeStream.java +171 -0
  79. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/ParseTree.java +119 -0
  80. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteCardinalityException.java +47 -0
  81. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteEarlyExitException.java +39 -0
  82. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteEmptyStreamException.java +35 -0
  83. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleElementStream.java +210 -0
  84. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleNodeStream.java +70 -0
  85. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleSubtreeStream.java +86 -0
  86. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleTokenStream.java +76 -0
  87. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/Tree.java +127 -0
  88. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeAdaptor.java +263 -0
  89. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeFilter.java +135 -0
  90. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeIterator.java +132 -0
  91. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeNodeStream.java +106 -0
  92. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeParser.java +169 -0
  93. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreePatternLexer.java +135 -0
  94. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreePatternParser.java +154 -0
  95. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeRewriter.java +124 -0
  96. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeRuleReturnScope.java +41 -0
  97. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeVisitor.java +69 -0
  98. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeVisitorAction.java +47 -0
  99. data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeWizard.java +531 -0
  100. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearAppData.java +22 -7
  101. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java +4 -4
  102. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java +0 -1
  103. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java +161 -129
  104. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetActivityOrientation.java +5 -7
  105. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/GetViewProperty.java +1 -7
  106. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/Query.java +70 -61
  107. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/UIQuery.tokens +12 -0
  108. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ViewMapper.java +63 -0
  109. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQuery.tokens +10 -0
  110. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryLexer.java +945 -0
  111. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryParser.java +463 -0
  112. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/InvalidUIQueryException.java +10 -0
  113. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryAST.java +8 -0
  114. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTClassName.java +115 -0
  115. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTWith.java +157 -0
  116. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryDirection.java +5 -0
  117. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryEvaluator.java +205 -0
  118. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryUtils.java +135 -0
  119. data/test-server/instrumentation-backend/tests/sh/calaba/instrumentationbackend/query/tests/UIQueryTest.java +134 -0
  120. metadata +106 -3
  121. data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetOrientation.java +0 -39
@@ -0,0 +1,95 @@
1
+ /*
2
+ [The "BSD license"]
3
+ Copyright (c) 2005-2009 Terence Parr
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions
8
+ are met:
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ 3. The name of the author may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ package org.antlr.runtime;
29
+
30
+ import java.io.*;
31
+
32
+ /** Vacuum all input from a Reader and then treat it like a StringStream.
33
+ * Manage the buffer manually to avoid unnecessary data copying.
34
+ *
35
+ * If you need encoding, use ANTLRInputStream.
36
+ */
37
+ public class ANTLRReaderStream extends ANTLRStringStream {
38
+ public static final int READ_BUFFER_SIZE = 1024;
39
+ public static final int INITIAL_BUFFER_SIZE = 1024;
40
+
41
+ public ANTLRReaderStream() {
42
+ }
43
+
44
+ public ANTLRReaderStream(Reader r) throws IOException {
45
+ this(r, INITIAL_BUFFER_SIZE, READ_BUFFER_SIZE);
46
+ }
47
+
48
+ public ANTLRReaderStream(Reader r, int size) throws IOException {
49
+ this(r, size, READ_BUFFER_SIZE);
50
+ }
51
+
52
+ public ANTLRReaderStream(Reader r, int size, int readChunkSize) throws IOException {
53
+ load(r, size, readChunkSize);
54
+ }
55
+
56
+ public void load(Reader r, int size, int readChunkSize)
57
+ throws IOException
58
+ {
59
+ if ( r==null ) {
60
+ return;
61
+ }
62
+ if ( size<=0 ) {
63
+ size = INITIAL_BUFFER_SIZE;
64
+ }
65
+ if ( readChunkSize<=0 ) {
66
+ readChunkSize = READ_BUFFER_SIZE;
67
+ }
68
+ // System.out.println("load "+size+" in chunks of "+readChunkSize);
69
+ try {
70
+ // alloc initial buffer size.
71
+ data = new char[size];
72
+ // read all the data in chunks of readChunkSize
73
+ int numRead=0;
74
+ int p = 0;
75
+ do {
76
+ if ( p+readChunkSize > data.length ) { // overflow?
77
+ // System.out.println("### overflow p="+p+", data.length="+data.length);
78
+ char[] newdata = new char[data.length*2]; // resize
79
+ System.arraycopy(data, 0, newdata, 0, data.length);
80
+ data = newdata;
81
+ }
82
+ numRead = r.read(data, p, readChunkSize);
83
+ // System.out.println("read "+numRead+" chars; p was "+p+" is now "+(p+numRead));
84
+ p += numRead;
85
+ } while (numRead!=-1); // while not EOF
86
+ // set the actual size of the data available;
87
+ // EOF subtracted one above in p+=numRead; add one back
88
+ super.n = p+1;
89
+ //System.out.println("n="+n);
90
+ }
91
+ finally {
92
+ r.close();
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,230 @@
1
+ /*
2
+ [The "BSD license"]
3
+ Copyright (c) 2005-2009 Terence Parr
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions
8
+ are met:
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ 3. The name of the author may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ package org.antlr.runtime;
29
+
30
+ import java.util.ArrayList;
31
+ import java.util.List;
32
+
33
+ /** A pretty quick CharStream that pulls all data from an array
34
+ * directly. Every method call counts in the lexer. Java's
35
+ * strings aren't very good so I'm avoiding.
36
+ */
37
+ public class ANTLRStringStream implements CharStream {
38
+ /** The data being scanned */
39
+ protected char[] data;
40
+
41
+ /** How many characters are actually in the buffer */
42
+ protected int n;
43
+
44
+ /** 0..n-1 index into string of next char */
45
+ protected int p=0;
46
+
47
+ /** line number 1..n within the input */
48
+ protected int line = 1;
49
+
50
+ /** The index of the character relative to the beginning of the line 0..n-1 */
51
+ protected int charPositionInLine = 0;
52
+
53
+ /** tracks how deep mark() calls are nested */
54
+ protected int markDepth = 0;
55
+
56
+ /** A list of CharStreamState objects that tracks the stream state
57
+ * values line, charPositionInLine, and p that can change as you
58
+ * move through the input stream. Indexed from 1..markDepth.
59
+ * A null is kept @ index 0. Create upon first call to mark().
60
+ */
61
+ protected List markers;
62
+
63
+ /** Track the last mark() call result value for use in rewind(). */
64
+ protected int lastMarker;
65
+
66
+ /** What is name or source of this char stream? */
67
+ public String name;
68
+
69
+ public ANTLRStringStream() {
70
+ }
71
+
72
+ /** Copy data in string to a local char array */
73
+ public ANTLRStringStream(String input) {
74
+ this();
75
+ this.data = input.toCharArray();
76
+ this.n = input.length();
77
+ }
78
+
79
+ /** This is the preferred constructor as no data is copied */
80
+ public ANTLRStringStream(char[] data, int numberOfActualCharsInArray) {
81
+ this();
82
+ this.data = data;
83
+ this.n = numberOfActualCharsInArray;
84
+ }
85
+
86
+ /** Reset the stream so that it's in the same state it was
87
+ * when the object was created *except* the data array is not
88
+ * touched.
89
+ */
90
+ public void reset() {
91
+ p = 0;
92
+ line = 1;
93
+ charPositionInLine = 0;
94
+ markDepth = 0;
95
+ }
96
+
97
+ public void consume() {
98
+ //System.out.println("prev p="+p+", c="+(char)data[p]);
99
+ if ( p < n ) {
100
+ charPositionInLine++;
101
+ if ( data[p]=='\n' ) {
102
+ /*
103
+ System.out.println("newline char found on line: "+line+
104
+ "@ pos="+charPositionInLine);
105
+ */
106
+ line++;
107
+ charPositionInLine=0;
108
+ }
109
+ p++;
110
+ //System.out.println("p moves to "+p+" (c='"+(char)data[p]+"')");
111
+ }
112
+ }
113
+
114
+ public int LA(int i) {
115
+ if ( i==0 ) {
116
+ return 0; // undefined
117
+ }
118
+ if ( i<0 ) {
119
+ i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1]
120
+ if ( (p+i-1) < 0 ) {
121
+ return CharStream.EOF; // invalid; no char before first char
122
+ }
123
+ }
124
+
125
+ if ( (p+i-1) >= n ) {
126
+ //System.out.println("char LA("+i+")=EOF; p="+p);
127
+ return CharStream.EOF;
128
+ }
129
+ //System.out.println("char LA("+i+")="+(char)data[p+i-1]+"; p="+p);
130
+ //System.out.println("LA("+i+"); p="+p+" n="+n+" data.length="+data.length);
131
+ return data[p+i-1];
132
+ }
133
+
134
+ public int LT(int i) {
135
+ return LA(i);
136
+ }
137
+
138
+ /** Return the current input symbol index 0..n where n indicates the
139
+ * last symbol has been read. The index is the index of char to
140
+ * be returned from LA(1).
141
+ */
142
+ public int index() {
143
+ return p;
144
+ }
145
+
146
+ public int size() {
147
+ return n;
148
+ }
149
+
150
+ public int mark() {
151
+ if ( markers==null ) {
152
+ markers = new ArrayList();
153
+ markers.add(null); // depth 0 means no backtracking, leave blank
154
+ }
155
+ markDepth++;
156
+ CharStreamState state = null;
157
+ if ( markDepth>=markers.size() ) {
158
+ state = new CharStreamState();
159
+ markers.add(state);
160
+ }
161
+ else {
162
+ state = (CharStreamState)markers.get(markDepth);
163
+ }
164
+ state.p = p;
165
+ state.line = line;
166
+ state.charPositionInLine = charPositionInLine;
167
+ lastMarker = markDepth;
168
+ return markDepth;
169
+ }
170
+
171
+ public void rewind(int m) {
172
+ CharStreamState state = (CharStreamState)markers.get(m);
173
+ // restore stream state
174
+ seek(state.p);
175
+ line = state.line;
176
+ charPositionInLine = state.charPositionInLine;
177
+ release(m);
178
+ }
179
+
180
+ public void rewind() {
181
+ rewind(lastMarker);
182
+ }
183
+
184
+ public void release(int marker) {
185
+ // unwind any other markers made after m and release m
186
+ markDepth = marker;
187
+ // release this marker
188
+ markDepth--;
189
+ }
190
+
191
+ /** consume() ahead until p==index; can't just set p=index as we must
192
+ * update line and charPositionInLine.
193
+ */
194
+ public void seek(int index) {
195
+ if ( index<=p ) {
196
+ p = index; // just jump; don't update stream state (line, ...)
197
+ return;
198
+ }
199
+ // seek forward, consume until p hits index
200
+ while ( p<index ) {
201
+ consume();
202
+ }
203
+ }
204
+
205
+ public String substring(int start, int stop) {
206
+ return new String(data,start,stop-start+1);
207
+ }
208
+
209
+ public int getLine() {
210
+ return line;
211
+ }
212
+
213
+ public int getCharPositionInLine() {
214
+ return charPositionInLine;
215
+ }
216
+
217
+ public void setLine(int line) {
218
+ this.line = line;
219
+ }
220
+
221
+ public void setCharPositionInLine(int pos) {
222
+ this.charPositionInLine = pos;
223
+ }
224
+
225
+ public String getSourceName() {
226
+ return name;
227
+ }
228
+
229
+ public String toString() { return new String(data); }
230
+ }
@@ -0,0 +1,894 @@
1
+ /*
2
+ [The "BSD license"]
3
+ Copyright (c) 2005-2009 Terence Parr
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions
8
+ are met:
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ 3. The name of the author may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ package org.antlr.runtime;
29
+
30
+ import java.util.ArrayList;
31
+ import java.util.HashMap;
32
+ import java.util.List;
33
+ import java.util.Map;
34
+
35
+ /** A generic recognizer that can handle recognizers generated from
36
+ * lexer, parser, and tree grammars. This is all the parsing
37
+ * support code essentially; most of it is error recovery stuff and
38
+ * backtracking.
39
+ */
40
+ public abstract class BaseRecognizer {
41
+ public static final int MEMO_RULE_FAILED = -2;
42
+ public static final int MEMO_RULE_UNKNOWN = -1;
43
+ public static final int INITIAL_FOLLOW_STACK_SIZE = 100;
44
+
45
+ private static final String TAG = "ANTLR:BaseRecognizer";
46
+
47
+ // copies from Token object for convenience in actions
48
+ public static final int DEFAULT_TOKEN_CHANNEL = Token.DEFAULT_CHANNEL;
49
+ public static final int HIDDEN = Token.HIDDEN_CHANNEL;
50
+
51
+ public static final String NEXT_TOKEN_RULE_NAME = "nextToken";
52
+
53
+ /** State of a lexer, parser, or tree parser are collected into a state
54
+ * object so the state can be shared. This sharing is needed to
55
+ * have one grammar import others and share same error variables
56
+ * and other state variables. It's a kind of explicit multiple
57
+ * inheritance via delegation of methods and shared state.
58
+ */
59
+ protected RecognizerSharedState state;
60
+
61
+ public BaseRecognizer() {
62
+ state = new RecognizerSharedState();
63
+ }
64
+
65
+ public BaseRecognizer(RecognizerSharedState state) {
66
+ if ( state==null ) {
67
+ state = new RecognizerSharedState();
68
+ }
69
+ this.state = state;
70
+ }
71
+
72
+ /** reset the parser's state; subclasses must rewinds the input stream */
73
+ public void reset() {
74
+ // wack everything related to error recovery
75
+ if ( state==null ) {
76
+ return; // no shared state work to do
77
+ }
78
+ state._fsp = -1;
79
+ state.errorRecovery = false;
80
+ state.lastErrorIndex = -1;
81
+ state.failed = false;
82
+ state.syntaxErrors = 0;
83
+ // wack everything related to backtracking and memoization
84
+ state.backtracking = 0;
85
+ for (int i = 0; state.ruleMemo!=null && i < state.ruleMemo.length; i++) { // wipe cache
86
+ state.ruleMemo[i] = null;
87
+ }
88
+ }
89
+
90
+
91
+ /** Match current input symbol against ttype. Attempt
92
+ * single token insertion or deletion error recovery. If
93
+ * that fails, throw MismatchedTokenException.
94
+ *
95
+ * To turn off single token insertion or deletion error
96
+ * recovery, override recoverFromMismatchedToken() and have it
97
+ * throw an exception. See TreeParser.recoverFromMismatchedToken().
98
+ * This way any error in a rule will cause an exception and
99
+ * immediate exit from rule. Rule would recover by resynchronizing
100
+ * to the set of symbols that can follow rule ref.
101
+ */
102
+ public Object match(IntStream input, int ttype, BitSet follow)
103
+ throws RecognitionException
104
+ {
105
+ //System.out.println("match "+((TokenStream)input).LT(1));
106
+ Object matchedSymbol = getCurrentInputSymbol(input);
107
+ if ( input.LA(1)==ttype ) {
108
+ input.consume();
109
+ state.errorRecovery = false;
110
+ state.failed = false;
111
+ return matchedSymbol;
112
+ }
113
+ if ( state.backtracking>0 ) {
114
+ state.failed = true;
115
+ return matchedSymbol;
116
+ }
117
+ matchedSymbol = recoverFromMismatchedToken(input, ttype, follow);
118
+ return matchedSymbol;
119
+ }
120
+
121
+ /** Match the wildcard: in a symbol */
122
+ public void matchAny(IntStream input) {
123
+ state.errorRecovery = false;
124
+ state.failed = false;
125
+ input.consume();
126
+ }
127
+
128
+ public boolean mismatchIsUnwantedToken(IntStream input, int ttype) {
129
+ return input.LA(2)==ttype;
130
+ }
131
+
132
+ public boolean mismatchIsMissingToken(IntStream input, BitSet follow) {
133
+ if ( follow==null ) {
134
+ // we have no information about the follow; we can only consume
135
+ // a single token and hope for the best
136
+ return false;
137
+ }
138
+ // compute what can follow this grammar element reference
139
+ if ( follow.member(Token.EOR_TOKEN_TYPE) ) {
140
+ BitSet viableTokensFollowingThisRule = computeContextSensitiveRuleFOLLOW();
141
+ follow = follow.or(viableTokensFollowingThisRule);
142
+ if ( state._fsp>=0 ) { // remove EOR if we're not the start symbol
143
+ follow.remove(Token.EOR_TOKEN_TYPE);
144
+ }
145
+ }
146
+ // if current token is consistent with what could come after set
147
+ // then we know we're missing a token; error recovery is free to
148
+ // "insert" the missing token
149
+
150
+ //System.out.println("viable tokens="+follow.toString(getTokenNames()));
151
+ //System.out.println("LT(1)="+((TokenStream)input).LT(1));
152
+
153
+ // BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR
154
+ // in follow set to indicate that the fall of the start symbol is
155
+ // in the set (EOF can follow).
156
+ if ( follow.member(input.LA(1)) || follow.member(Token.EOR_TOKEN_TYPE) ) {
157
+ //System.out.println("LT(1)=="+((TokenStream)input).LT(1)+" is consistent with what follows; inserting...");
158
+ return true;
159
+ }
160
+ return false;
161
+ }
162
+
163
+ /** Report a recognition problem.
164
+ *
165
+ * This method sets errorRecovery to indicate the parser is recovering
166
+ * not parsing. Once in recovery mode, no errors are generated.
167
+ * To get out of recovery mode, the parser must successfully match
168
+ * a token (after a resync). So it will go:
169
+ *
170
+ * 1. error occurs
171
+ * 2. enter recovery mode, report error
172
+ * 3. consume until token found in resynch set
173
+ * 4. try to resume parsing
174
+ * 5. next match() will reset errorRecovery mode
175
+ *
176
+ * If you override, make sure to update syntaxErrors if you care about that.
177
+ */
178
+ public void reportError(RecognitionException e) {
179
+ // if we've already reported an error and have not matched a token
180
+ // yet successfully, don't report any errors.
181
+ if ( state.errorRecovery ) {
182
+ //System.err.print("[SPURIOUS] ");
183
+ return;
184
+ }
185
+ state.syntaxErrors++; // don't count spurious
186
+ state.errorRecovery = true;
187
+
188
+ displayRecognitionError(this.getTokenNames(), e);
189
+ }
190
+
191
+ public void displayRecognitionError(String[] tokenNames,
192
+ RecognitionException e)
193
+ {
194
+ String hdr = getErrorHeader(e);
195
+ String msg = getErrorMessage(e, tokenNames);
196
+ emitErrorMessage(hdr+" "+msg);
197
+ }
198
+
199
+ /** What error message should be generated for the various
200
+ * exception types?
201
+ *
202
+ * Not very object-oriented code, but I like having all error message
203
+ * generation within one method rather than spread among all of the
204
+ * exception classes. This also makes it much easier for the exception
205
+ * handling because the exception classes do not have to have pointers back
206
+ * to this object to access utility routines and so on. Also, changing
207
+ * the message for an exception type would be difficult because you
208
+ * would have to subclassing exception, but then somehow get ANTLR
209
+ * to make those kinds of exception objects instead of the default.
210
+ * This looks weird, but trust me--it makes the most sense in terms
211
+ * of flexibility.
212
+ *
213
+ * For grammar debugging, you will want to override this to add
214
+ * more information such as the stack frame with
215
+ * getRuleInvocationStack(e, this.getClass().getName()) and,
216
+ * for no viable alts, the decision description and state etc...
217
+ *
218
+ * Override this to change the message generated for one or more
219
+ * exception types.
220
+ */
221
+ public String getErrorMessage(RecognitionException e, String[] tokenNames) {
222
+ String msg = e.getMessage();
223
+ if ( e instanceof UnwantedTokenException ) {
224
+ UnwantedTokenException ute = (UnwantedTokenException)e;
225
+ String tokenName="<unknown>";
226
+ if ( ute.expecting== Token.EOF ) {
227
+ tokenName = "EOF";
228
+ }
229
+ else {
230
+ tokenName = tokenNames[ute.expecting];
231
+ }
232
+ msg = "extraneous input "+getTokenErrorDisplay(ute.getUnexpectedToken())+
233
+ " expecting "+tokenName;
234
+ }
235
+ else if ( e instanceof MissingTokenException ) {
236
+ MissingTokenException mte = (MissingTokenException)e;
237
+ String tokenName="<unknown>";
238
+ if ( mte.expecting== Token.EOF ) {
239
+ tokenName = "EOF";
240
+ }
241
+ else {
242
+ tokenName = tokenNames[mte.expecting];
243
+ }
244
+ msg = "missing "+tokenName+" at "+getTokenErrorDisplay(e.token);
245
+ }
246
+ else if ( e instanceof MismatchedTokenException ) {
247
+ MismatchedTokenException mte = (MismatchedTokenException)e;
248
+ String tokenName="<unknown>";
249
+ if ( mte.expecting== Token.EOF ) {
250
+ tokenName = "EOF";
251
+ }
252
+ else {
253
+ tokenName = tokenNames[mte.expecting];
254
+ }
255
+ msg = "mismatched input "+getTokenErrorDisplay(e.token)+
256
+ " expecting "+tokenName;
257
+ }
258
+ else if ( e instanceof MismatchedTreeNodeException ) {
259
+ MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e;
260
+ String tokenName="<unknown>";
261
+ if ( mtne.expecting==Token.EOF ) {
262
+ tokenName = "EOF";
263
+ }
264
+ else {
265
+ tokenName = tokenNames[mtne.expecting];
266
+ }
267
+ msg = "mismatched tree node: "+mtne.node+
268
+ " expecting "+tokenName;
269
+ }
270
+ else if ( e instanceof NoViableAltException ) {
271
+ //NoViableAltException nvae = (NoViableAltException)e;
272
+ // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
273
+ // and "(decision="+nvae.decisionNumber+") and
274
+ // "state "+nvae.stateNumber
275
+ msg = "no viable alternative at input "+getTokenErrorDisplay(e.token);
276
+ }
277
+ else if ( e instanceof EarlyExitException ) {
278
+ //EarlyExitException eee = (EarlyExitException)e;
279
+ // for development, can add "(decision="+eee.decisionNumber+")"
280
+ msg = "required (...)+ loop did not match anything at input "+
281
+ getTokenErrorDisplay(e.token);
282
+ }
283
+ else if ( e instanceof MismatchedSetException ) {
284
+ MismatchedSetException mse = (MismatchedSetException)e;
285
+ msg = "mismatched input "+getTokenErrorDisplay(e.token)+
286
+ " expecting set "+mse.expecting;
287
+ }
288
+ else if ( e instanceof MismatchedNotSetException ) {
289
+ MismatchedNotSetException mse = (MismatchedNotSetException)e;
290
+ msg = "mismatched input "+getTokenErrorDisplay(e.token)+
291
+ " expecting set "+mse.expecting;
292
+ }
293
+ else if ( e instanceof FailedPredicateException ) {
294
+ FailedPredicateException fpe = (FailedPredicateException)e;
295
+ msg = "rule "+fpe.ruleName+" failed predicate: {"+
296
+ fpe.predicateText+"}?";
297
+ }
298
+ return msg;
299
+ }
300
+
301
+ /** Get number of recognition errors (lexer, parser, tree parser). Each
302
+ * recognizer tracks its own number. So parser and lexer each have
303
+ * separate count. Does not count the spurious errors found between
304
+ * an error and next valid token match
305
+ *
306
+ * See also reportError()
307
+ */
308
+ public int getNumberOfSyntaxErrors() {
309
+ return state.syntaxErrors;
310
+ }
311
+
312
+ /** What is the error header, normally line/character position information? */
313
+ public String getErrorHeader(RecognitionException e) {
314
+ if ( getSourceName()!=null )
315
+ return getSourceName()+" line "+e.line+":"+e.charPositionInLine;
316
+
317
+ return "line "+e.line+":"+e.charPositionInLine;
318
+ }
319
+
320
+ /** How should a token be displayed in an error message? The default
321
+ * is to display just the text, but during development you might
322
+ * want to have a lot of information spit out. Override in that case
323
+ * to use t.toString() (which, for CommonToken, dumps everything about
324
+ * the token). This is better than forcing you to override a method in
325
+ * your token objects because you don't have to go modify your lexer
326
+ * so that it creates a new Java type.
327
+ */
328
+ public String getTokenErrorDisplay(Token t) {
329
+ String s = t.getText();
330
+ if ( s==null ) {
331
+ if ( t.getType()==Token.EOF ) {
332
+ s = "<EOF>";
333
+ }
334
+ else {
335
+ s = "<"+t.getType()+">";
336
+ }
337
+ }
338
+ s = s.replaceAll("\n","\\\\n");
339
+ s = s.replaceAll("\r","\\\\r");
340
+ s = s.replaceAll("\t","\\\\t");
341
+ return "'"+s+"'";
342
+ }
343
+
344
+ /** Override this method to change where error messages go */
345
+ public void emitErrorMessage(String msg) {
346
+ //System.err.println(msg);
347
+ android.util.Log.e(TAG, msg);
348
+ }
349
+
350
+ /** Recover from an error found on the input stream. This is
351
+ * for NoViableAlt and mismatched symbol exceptions. If you enable
352
+ * single token insertion and deletion, this will usually not
353
+ * handle mismatched symbol exceptions but there could be a mismatched
354
+ * token that the match() routine could not recover from.
355
+ */
356
+ public void recover(IntStream input, RecognitionException re) {
357
+ if ( state.lastErrorIndex==input.index() ) {
358
+ // uh oh, another error at same token index; must be a case
359
+ // where LT(1) is in the recovery token set so nothing is
360
+ // consumed; consume a single token so at least to prevent
361
+ // an infinite loop; this is a failsafe.
362
+ input.consume();
363
+ }
364
+ state.lastErrorIndex = input.index();
365
+ BitSet followSet = computeErrorRecoverySet();
366
+ beginResync();
367
+ consumeUntil(input, followSet);
368
+ endResync();
369
+ }
370
+
371
+ /** A hook to listen in on the token consumption during error recovery.
372
+ * The DebugParser subclasses this to fire events to the listenter.
373
+ */
374
+ public void beginResync() {
375
+ }
376
+
377
+ public void endResync() {
378
+ }
379
+
380
+ /* Compute the error recovery set for the current rule. During
381
+ * rule invocation, the parser pushes the set of tokens that can
382
+ * follow that rule reference on the stack; this amounts to
383
+ * computing FIRST of what follows the rule reference in the
384
+ * enclosing rule. This local follow set only includes tokens
385
+ * from within the rule; i.e., the FIRST computation done by
386
+ * ANTLR stops at the end of a rule.
387
+ *
388
+ * EXAMPLE
389
+ *
390
+ * When you find a "no viable alt exception", the input is not
391
+ * consistent with any of the alternatives for rule r. The best
392
+ * thing to do is to consume tokens until you see something that
393
+ * can legally follow a call to r *or* any rule that called r.
394
+ * You don't want the exact set of viable next tokens because the
395
+ * input might just be missing a token--you might consume the
396
+ * rest of the input looking for one of the missing tokens.
397
+ *
398
+ * Consider grammar:
399
+ *
400
+ * a : '[' b ']'
401
+ * | '(' b ')'
402
+ * ;
403
+ * b : c '^' INT ;
404
+ * c : ID
405
+ * | INT
406
+ * ;
407
+ *
408
+ * At each rule invocation, the set of tokens that could follow
409
+ * that rule is pushed on a stack. Here are the various "local"
410
+ * follow sets:
411
+ *
412
+ * FOLLOW(b1_in_a) = FIRST(']') = ']'
413
+ * FOLLOW(b2_in_a) = FIRST(')') = ')'
414
+ * FOLLOW(c_in_b) = FIRST('^') = '^'
415
+ *
416
+ * Upon erroneous input "[]", the call chain is
417
+ *
418
+ * a -> b -> c
419
+ *
420
+ * and, hence, the follow context stack is:
421
+ *
422
+ * depth local follow set after call to rule
423
+ * 0 <EOF> a (from main())
424
+ * 1 ']' b
425
+ * 3 '^' c
426
+ *
427
+ * Notice that ')' is not included, because b would have to have
428
+ * been called from a different context in rule a for ')' to be
429
+ * included.
430
+ *
431
+ * For error recovery, we cannot consider FOLLOW(c)
432
+ * (context-sensitive or otherwise). We need the combined set of
433
+ * all context-sensitive FOLLOW sets--the set of all tokens that
434
+ * could follow any reference in the call chain. We need to
435
+ * resync to one of those tokens. Note that FOLLOW(c)='^' and if
436
+ * we resync'd to that token, we'd consume until EOF. We need to
437
+ * sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
438
+ * In this case, for input "[]", LA(1) is in this set so we would
439
+ * not consume anything and after printing an error rule c would
440
+ * return normally. It would not find the required '^' though.
441
+ * At this point, it gets a mismatched token error and throws an
442
+ * exception (since LA(1) is not in the viable following token
443
+ * set). The rule exception handler tries to recover, but finds
444
+ * the same recovery set and doesn't consume anything. Rule b
445
+ * exits normally returning to rule a. Now it finds the ']' (and
446
+ * with the successful match exits errorRecovery mode).
447
+ *
448
+ * So, you cna see that the parser walks up call chain looking
449
+ * for the token that was a member of the recovery set.
450
+ *
451
+ * Errors are not generated in errorRecovery mode.
452
+ *
453
+ * ANTLR's error recovery mechanism is based upon original ideas:
454
+ *
455
+ * "Algorithms + Data Structures = Programs" by Niklaus Wirth
456
+ *
457
+ * and
458
+ *
459
+ * "A note on error recovery in recursive descent parsers":
460
+ * http://portal.acm.org/citation.cfm?id=947902.947905
461
+ *
462
+ * Later, Josef Grosch had some good ideas:
463
+ *
464
+ * "Efficient and Comfortable Error Recovery in Recursive Descent
465
+ * Parsers":
466
+ * ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
467
+ *
468
+ * Like Grosch I implemented local FOLLOW sets that are combined
469
+ * at run-time upon error to avoid overhead during parsing.
470
+ */
471
+ protected BitSet computeErrorRecoverySet() {
472
+ return combineFollows(false);
473
+ }
474
+
475
+ /** Compute the context-sensitive FOLLOW set for current rule.
476
+ * This is set of token types that can follow a specific rule
477
+ * reference given a specific call chain. You get the set of
478
+ * viable tokens that can possibly come next (lookahead depth 1)
479
+ * given the current call chain. Contrast this with the
480
+ * definition of plain FOLLOW for rule r:
481
+ *
482
+ * FOLLOW(r)={x | S=>*alpha r beta in G and x in FIRST(beta)}
483
+ *
484
+ * where x in T* and alpha, beta in V*; T is set of terminals and
485
+ * V is the set of terminals and nonterminals. In other words,
486
+ * FOLLOW(r) is the set of all tokens that can possibly follow
487
+ * references to r in *any* sentential form (context). At
488
+ * runtime, however, we know precisely which context applies as
489
+ * we have the call chain. We may compute the exact (rather
490
+ * than covering superset) set of following tokens.
491
+ *
492
+ * For example, consider grammar:
493
+ *
494
+ * stat : ID '=' expr ';' // FOLLOW(stat)=={EOF}
495
+ * | "return" expr '.'
496
+ * ;
497
+ * expr : atom ('+' atom)* ; // FOLLOW(expr)=={';','.',')'}
498
+ * atom : INT // FOLLOW(atom)=={'+',')',';','.'}
499
+ * | '(' expr ')'
500
+ * ;
501
+ *
502
+ * The FOLLOW sets are all inclusive whereas context-sensitive
503
+ * FOLLOW sets are precisely what could follow a rule reference.
504
+ * For input input "i=(3);", here is the derivation:
505
+ *
506
+ * stat => ID '=' expr ';'
507
+ * => ID '=' atom ('+' atom)* ';'
508
+ * => ID '=' '(' expr ')' ('+' atom)* ';'
509
+ * => ID '=' '(' atom ')' ('+' atom)* ';'
510
+ * => ID '=' '(' INT ')' ('+' atom)* ';'
511
+ * => ID '=' '(' INT ')' ';'
512
+ *
513
+ * At the "3" token, you'd have a call chain of
514
+ *
515
+ * stat -> expr -> atom -> expr -> atom
516
+ *
517
+ * What can follow that specific nested ref to atom? Exactly ')'
518
+ * as you can see by looking at the derivation of this specific
519
+ * input. Contrast this with the FOLLOW(atom)={'+',')',';','.'}.
520
+ *
521
+ * You want the exact viable token set when recovering from a
522
+ * token mismatch. Upon token mismatch, if LA(1) is member of
523
+ * the viable next token set, then you know there is most likely
524
+ * a missing token in the input stream. "Insert" one by just not
525
+ * throwing an exception.
526
+ */
527
+ protected BitSet computeContextSensitiveRuleFOLLOW() {
528
+ return combineFollows(true);
529
+ }
530
+
531
+ // what is exact? it seems to only add sets from above on stack
532
+ // if EOR is in set i. When it sees a set w/o EOR, it stops adding.
533
+ // Why would we ever want them all? Maybe no viable alt instead of
534
+ // mismatched token?
535
+ protected BitSet combineFollows(boolean exact) {
536
+ int top = state._fsp;
537
+ BitSet followSet = new BitSet();
538
+ for (int i=top; i>=0; i--) {
539
+ BitSet localFollowSet = (BitSet)state.following[i];
540
+ /*
541
+ System.out.println("local follow depth "+i+"="+
542
+ localFollowSet.toString(getTokenNames())+")");
543
+ */
544
+ followSet.orInPlace(localFollowSet);
545
+ if ( exact ) {
546
+ // can we see end of rule?
547
+ if ( localFollowSet.member(Token.EOR_TOKEN_TYPE) ) {
548
+ // Only leave EOR in set if at top (start rule); this lets
549
+ // us know if have to include follow(start rule); i.e., EOF
550
+ if ( i>0 ) {
551
+ followSet.remove(Token.EOR_TOKEN_TYPE);
552
+ }
553
+ }
554
+ else { // can't see end of rule, quit
555
+ break;
556
+ }
557
+ }
558
+ }
559
+ return followSet;
560
+ }
561
+
562
+ /** Attempt to recover from a single missing or extra token.
563
+ *
564
+ * EXTRA TOKEN
565
+ *
566
+ * LA(1) is not what we are looking for. If LA(2) has the right token,
567
+ * however, then assume LA(1) is some extra spurious token. Delete it
568
+ * and LA(2) as if we were doing a normal match(), which advances the
569
+ * input.
570
+ *
571
+ * MISSING TOKEN
572
+ *
573
+ * If current token is consistent with what could come after
574
+ * ttype then it is ok to "insert" the missing token, else throw
575
+ * exception For example, Input "i=(3;" is clearly missing the
576
+ * ')'. When the parser returns from the nested call to expr, it
577
+ * will have call chain:
578
+ *
579
+ * stat -> expr -> atom
580
+ *
581
+ * and it will be trying to match the ')' at this point in the
582
+ * derivation:
583
+ *
584
+ * => ID '=' '(' INT ')' ('+' atom)* ';'
585
+ * ^
586
+ * match() will see that ';' doesn't match ')' and report a
587
+ * mismatched token error. To recover, it sees that LA(1)==';'
588
+ * is in the set of tokens that can follow the ')' token
589
+ * reference in rule atom. It can assume that you forgot the ')'.
590
+ */
591
+ protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow)
592
+ throws RecognitionException
593
+ {
594
+ RecognitionException e = null;
595
+ // if next token is what we are looking for then "delete" this token
596
+ if ( mismatchIsUnwantedToken(input, ttype) ) {
597
+ e = new UnwantedTokenException(ttype, input);
598
+ /*
599
+ System.err.println("recoverFromMismatchedToken deleting "+
600
+ ((TokenStream)input).LT(1)+
601
+ " since "+((TokenStream)input).LT(2)+" is what we want");
602
+ */
603
+ beginResync();
604
+ input.consume(); // simply delete extra token
605
+ endResync();
606
+ reportError(e); // report after consuming so AW sees the token in the exception
607
+ // we want to return the token we're actually matching
608
+ Object matchedSymbol = getCurrentInputSymbol(input);
609
+ input.consume(); // move past ttype token as if all were ok
610
+ return matchedSymbol;
611
+ }
612
+ // can't recover with single token deletion, try insertion
613
+ if ( mismatchIsMissingToken(input, follow) ) {
614
+ Object inserted = getMissingSymbol(input, e, ttype, follow);
615
+ e = new MissingTokenException(ttype, input, inserted);
616
+ reportError(e); // report after inserting so AW sees the token in the exception
617
+ return inserted;
618
+ }
619
+ // even that didn't work; must throw the exception
620
+ e = new MismatchedTokenException(ttype, input);
621
+ throw e;
622
+ }
623
+
624
+ /** Not currently used */
625
+ public Object recoverFromMismatchedSet(IntStream input,
626
+ RecognitionException e,
627
+ BitSet follow)
628
+ throws RecognitionException
629
+ {
630
+ if ( mismatchIsMissingToken(input, follow) ) {
631
+ // System.out.println("missing token");
632
+ reportError(e);
633
+ // we don't know how to conjure up a token for sets yet
634
+ return getMissingSymbol(input, e, Token.INVALID_TOKEN_TYPE, follow);
635
+ }
636
+ // TODO do single token deletion like above for Token mismatch
637
+ throw e;
638
+ }
639
+
640
+ /** Match needs to return the current input symbol, which gets put
641
+ * into the label for the associated token ref; e.g., x=ID. Token
642
+ * and tree parsers need to return different objects. Rather than test
643
+ * for input stream type or change the IntStream interface, I use
644
+ * a simple method to ask the recognizer to tell me what the current
645
+ * input symbol is.
646
+ *
647
+ * This is ignored for lexers.
648
+ */
649
+ protected Object getCurrentInputSymbol(IntStream input) { return null; }
650
+
651
+ /** Conjure up a missing token during error recovery.
652
+ *
653
+ * The recognizer attempts to recover from single missing
654
+ * symbols. But, actions might refer to that missing symbol.
655
+ * For example, x=ID {f($x);}. The action clearly assumes
656
+ * that there has been an identifier matched previously and that
657
+ * $x points at that token. If that token is missing, but
658
+ * the next token in the stream is what we want we assume that
659
+ * this token is missing and we keep going. Because we
660
+ * have to return some token to replace the missing token,
661
+ * we have to conjure one up. This method gives the user control
662
+ * over the tokens returned for missing tokens. Mostly,
663
+ * you will want to create something special for identifier
664
+ * tokens. For literals such as '{' and ',', the default
665
+ * action in the parser or tree parser works. It simply creates
666
+ * a CommonToken of the appropriate type. The text will be the token.
667
+ * If you change what tokens must be created by the lexer,
668
+ * override this method to create the appropriate tokens.
669
+ */
670
+ protected Object getMissingSymbol(IntStream input,
671
+ RecognitionException e,
672
+ int expectedTokenType,
673
+ BitSet follow)
674
+ {
675
+ return null;
676
+ }
677
+
678
+ public void consumeUntil(IntStream input, int tokenType) {
679
+ //System.out.println("consumeUntil "+tokenType);
680
+ int ttype = input.LA(1);
681
+ while (ttype != Token.EOF && ttype != tokenType) {
682
+ input.consume();
683
+ ttype = input.LA(1);
684
+ }
685
+ }
686
+
687
+ /** Consume tokens until one matches the given token set */
688
+ public void consumeUntil(IntStream input, BitSet set) {
689
+ //System.out.println("consumeUntil("+set.toString(getTokenNames())+")");
690
+ int ttype = input.LA(1);
691
+ while (ttype != Token.EOF && !set.member(ttype) ) {
692
+ //System.out.println("consume during recover LA(1)="+getTokenNames()[input.LA(1)]);
693
+ input.consume();
694
+ ttype = input.LA(1);
695
+ }
696
+ }
697
+
698
+ /** Push a rule's follow set using our own hardcoded stack */
699
+ protected void pushFollow(BitSet fset) {
700
+ if ( (state._fsp +1)>=state.following.length ) {
701
+ BitSet[] f = new BitSet[state.following.length*2];
702
+ System.arraycopy(state.following, 0, f, 0, state.following.length);
703
+ state.following = f;
704
+ }
705
+ state.following[++state._fsp] = fset;
706
+ }
707
+
708
+ /** Return List<String> of the rules in your parser instance
709
+ * leading up to a call to this method. You could override if
710
+ * you want more details such as the file/line info of where
711
+ * in the parser java code a rule is invoked.
712
+ *
713
+ * This is very useful for error messages and for context-sensitive
714
+ * error recovery.
715
+ */
716
+ public List getRuleInvocationStack() {
717
+ String parserClassName = getClass().getName();
718
+ return getRuleInvocationStack(new Throwable(), parserClassName);
719
+ }
720
+
721
+ /** A more general version of getRuleInvocationStack where you can
722
+ * pass in, for example, a RecognitionException to get it's rule
723
+ * stack trace. This routine is shared with all recognizers, hence,
724
+ * static.
725
+ *
726
+ * TODO: move to a utility class or something; weird having lexer call this
727
+ */
728
+ public static List getRuleInvocationStack(Throwable e,
729
+ String recognizerClassName)
730
+ {
731
+ List rules = new ArrayList();
732
+ StackTraceElement[] stack = e.getStackTrace();
733
+ int i = 0;
734
+ for (i=stack.length-1; i>=0; i--) {
735
+ StackTraceElement t = stack[i];
736
+ if ( t.getClassName().startsWith("org.antlr.runtime.") ) {
737
+ continue; // skip support code such as this method
738
+ }
739
+ if ( t.getMethodName().equals(NEXT_TOKEN_RULE_NAME) ) {
740
+ continue;
741
+ }
742
+ if ( !t.getClassName().equals(recognizerClassName) ) {
743
+ continue; // must not be part of this parser
744
+ }
745
+ rules.add(t.getMethodName());
746
+ }
747
+ return rules;
748
+ }
749
+
750
+ public int getBacktrackingLevel() { return state.backtracking; }
751
+
752
+ public void setBacktrackingLevel(int n) { state.backtracking = n; }
753
+
754
+ /** Return whether or not a backtracking attempt failed. */
755
+ public boolean failed() { return state.failed; }
756
+
757
+ /** Used to print out token names like ID during debugging and
758
+ * error reporting. The generated parsers implement a method
759
+ * that overrides this to point to their String[] tokenNames.
760
+ */
761
+ public String[] getTokenNames() {
762
+ return null;
763
+ }
764
+
765
+ /** For debugging and other purposes, might want the grammar name.
766
+ * Have ANTLR generate an implementation for this method.
767
+ */
768
+ public String getGrammarFileName() {
769
+ return null;
770
+ }
771
+
772
+ public abstract String getSourceName();
773
+
774
+ /** A convenience method for use most often with template rewrites.
775
+ * Convert a List<Token> to List<String>
776
+ */
777
+ public List toStrings(List tokens) {
778
+ if ( tokens==null ) return null;
779
+ List strings = new ArrayList(tokens.size());
780
+ for (int i=0; i<tokens.size(); i++) {
781
+ strings.add(((Token)tokens.get(i)).getText());
782
+ }
783
+ return strings;
784
+ }
785
+
786
+ /** Given a rule number and a start token index number, return
787
+ * MEMO_RULE_UNKNOWN if the rule has not parsed input starting from
788
+ * start index. If this rule has parsed input starting from the
789
+ * start index before, then return where the rule stopped parsing.
790
+ * It returns the index of the last token matched by the rule.
791
+ *
792
+ * For now we use a hashtable and just the slow Object-based one.
793
+ * Later, we can make a special one for ints and also one that
794
+ * tosses out data after we commit past input position i.
795
+ */
796
+ public int getRuleMemoization(int ruleIndex, int ruleStartIndex) {
797
+ if ( state.ruleMemo[ruleIndex]==null ) {
798
+ state.ruleMemo[ruleIndex] = new HashMap();
799
+ }
800
+ Integer stopIndexI =
801
+ (Integer)state.ruleMemo[ruleIndex].get(new Integer(ruleStartIndex));
802
+ if ( stopIndexI==null ) {
803
+ return MEMO_RULE_UNKNOWN;
804
+ }
805
+ return stopIndexI.intValue();
806
+ }
807
+
808
+ /** Has this rule already parsed input at the current index in the
809
+ * input stream? Return the stop token index or MEMO_RULE_UNKNOWN.
810
+ * If we attempted but failed to parse properly before, return
811
+ * MEMO_RULE_FAILED.
812
+ *
813
+ * This method has a side-effect: if we have seen this input for
814
+ * this rule and successfully parsed before, then seek ahead to
815
+ * 1 past the stop token matched for this rule last time.
816
+ */
817
+ public boolean alreadyParsedRule(IntStream input, int ruleIndex) {
818
+ int stopIndex = getRuleMemoization(ruleIndex, input.index());
819
+ if ( stopIndex==MEMO_RULE_UNKNOWN ) {
820
+ return false;
821
+ }
822
+ if ( stopIndex==MEMO_RULE_FAILED ) {
823
+ //System.out.println("rule "+ruleIndex+" will never succeed");
824
+ state.failed=true;
825
+ }
826
+ else {
827
+ //System.out.println("seen rule "+ruleIndex+" before; skipping ahead to @"+(stopIndex+1)+" failed="+state.failed);
828
+ input.seek(stopIndex+1); // jump to one past stop token
829
+ }
830
+ return true;
831
+ }
832
+
833
+ /** Record whether or not this rule parsed the input at this position
834
+ * successfully. Use a standard java hashtable for now.
835
+ */
836
+ public void memoize(IntStream input,
837
+ int ruleIndex,
838
+ int ruleStartIndex)
839
+ {
840
+ int stopTokenIndex = state.failed?MEMO_RULE_FAILED:input.index()-1;
841
+ if ( state.ruleMemo==null ) {
842
+ //System.err.println("!!!!!!!!! memo array is null for "+ getGrammarFileName());
843
+ android.util.Log.e(TAG, "!!!!!!!!! memo array is null for "+ getGrammarFileName());
844
+ }
845
+ if ( ruleIndex >= state.ruleMemo.length ) {
846
+ //System.err.println("!!!!!!!!! memo size is "+state.ruleMemo.length+", but rule index is "+ruleIndex);
847
+ android.util.Log.e(TAG, "!!!!!!!!! memo size is "+state.ruleMemo.length+", but rule index is "+ruleIndex);
848
+ }
849
+ if ( state.ruleMemo[ruleIndex]!=null ) {
850
+ state.ruleMemo[ruleIndex].put(
851
+ new Integer(ruleStartIndex), new Integer(stopTokenIndex)
852
+ );
853
+ }
854
+ }
855
+
856
+ /** return how many rule/input-index pairs there are in total.
857
+ * TODO: this includes synpreds. :(
858
+ */
859
+ public int getRuleMemoizationCacheSize() {
860
+ int n = 0;
861
+ for (int i = 0; state.ruleMemo!=null && i < state.ruleMemo.length; i++) {
862
+ Map ruleMap = state.ruleMemo[i];
863
+ if ( ruleMap!=null ) {
864
+ n += ruleMap.size(); // how many input indexes are recorded?
865
+ }
866
+ }
867
+ return n;
868
+ }
869
+
870
+ public void traceIn(String ruleName, int ruleIndex, Object inputSymbol) {
871
+ //System.out.print("enter "+ruleName+" "+inputSymbol);
872
+ android.util.Log.i(TAG, "enter "+ruleName+" "+inputSymbol);
873
+ if ( state.backtracking>0 ) {
874
+ System.out.print(" backtracking="+state.backtracking);
875
+ }
876
+ //System.out.println();
877
+ }
878
+
879
+ public void traceOut(String ruleName,
880
+ int ruleIndex,
881
+ Object inputSymbol)
882
+ {
883
+ //System.out.print("exit "+ruleName+" "+inputSymbol);
884
+ android.util.Log.i(TAG, "exit "+ruleName+" "+inputSymbol);
885
+ if ( state.backtracking>0 ) {
886
+ //System.out.print(" backtracking="+state.backtracking);
887
+ android.util.Log.i(TAG, " backtracking="+state.backtracking);
888
+ if ( state.failed ) System.out.print(" failed");
889
+ else android.util.Log.i(TAG, " succeeded");
890
+ }
891
+ //System.out.println();
892
+ }
893
+
894
+ }