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.
- data/bin/calabash-android-build.rb +6 -0
- data/bin/calabash-android-setup.rb +2 -3
- data/lib/calabash-android/canned_steps.md +1 -1
- data/lib/calabash-android/helpers.rb +35 -2
- data/lib/calabash-android/lib/TestServer.apk +0 -0
- data/lib/calabash-android/operations.rb +13 -6
- data/lib/calabash-android/version.rb +1 -1
- data/test-server/instrumentation-backend/.classpath +2 -1
- data/test-server/instrumentation-backend/antlr.sh +2 -0
- data/test-server/instrumentation-backend/antlr/UIQuery.g +70 -0
- data/test-server/instrumentation-backend/antlr/UIQuery.tokens +12 -0
- data/test-server/instrumentation-backend/build-libs/antlr-3.4-complete.jar +0 -0
- data/test-server/instrumentation-backend/build-libs/junit.jar +0 -0
- data/test-server/instrumentation-backend/build.xml +56 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRFileStream.java +78 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRInputStream.java +70 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRReaderStream.java +95 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRStringStream.java +230 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/BaseRecognizer.java +894 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/BitSet.java +325 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/BufferedTokenStream.java +272 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CharStream.java +57 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CharStreamState.java +45 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ClassicToken.java +141 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CommonToken.java +191 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CommonTokenStream.java +153 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/DFA.java +250 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/EarlyExitException.java +41 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/FailedPredicateException.java +54 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/IntStream.java +122 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/LegacyCommonTokenStream.java +394 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/Lexer.java +340 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedNotSetException.java +41 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedRangeException.java +45 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedSetException.java +44 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedTokenException.java +45 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedTreeNodeException.java +49 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MissingTokenException.java +56 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/NoViableAltException.java +57 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/Parser.java +98 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ParserRuleReturnScope.java +52 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/RecognitionException.java +180 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/RecognizerSharedState.java +144 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/RuleReturnScope.java +42 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/SerializedGrammar.java +204 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/Token.java +92 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenRewriteStream.java +569 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenSource.java +54 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenStream.java +75 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/UnbufferedTokenStream.java +82 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/UnwantedTokenException.java +53 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/BlankDebugEventListener.java +77 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventHub.java +292 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventListener.java +323 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventRepeater.java +88 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventSocketProxy.java +358 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugParser.java +101 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTokenStream.java +156 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeAdaptor.java +250 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeNodeStream.java +155 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeParser.java +112 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/ParseTreeBuilder.java +109 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/Profiler.java +772 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/RemoteDebugEventSocketListener.java +541 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/TraceDebugEventListener.java +108 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/Tracer.java +69 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/DoubleKeyMap.java +62 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/FastQueue.java +100 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/IntArray.java +87 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/LookaheadStream.java +161 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/Stats.java +189 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BaseTree.java +349 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BaseTreeAdaptor.java +279 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BufferedTreeNodeStream.java +489 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonErrorNode.java +108 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTree.java +185 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTreeAdaptor.java +168 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTreeNodeStream.java +171 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/ParseTree.java +119 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteCardinalityException.java +47 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteEarlyExitException.java +39 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteEmptyStreamException.java +35 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleElementStream.java +210 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleNodeStream.java +70 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleSubtreeStream.java +86 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleTokenStream.java +76 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/Tree.java +127 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeAdaptor.java +263 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeFilter.java +135 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeIterator.java +132 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeNodeStream.java +106 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeParser.java +169 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreePatternLexer.java +135 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreePatternParser.java +154 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeRewriter.java +124 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeRuleReturnScope.java +41 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeVisitor.java +69 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeVisitorAction.java +47 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeWizard.java +531 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearAppData.java +22 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java +4 -4
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java +0 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java +161 -129
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetActivityOrientation.java +5 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/GetViewProperty.java +1 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/Query.java +70 -61
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/UIQuery.tokens +12 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ViewMapper.java +63 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQuery.tokens +10 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryLexer.java +945 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryParser.java +463 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/InvalidUIQueryException.java +10 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryAST.java +8 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTClassName.java +115 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTWith.java +157 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryDirection.java +5 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryEvaluator.java +205 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryUtils.java +135 -0
- data/test-server/instrumentation-backend/tests/sh/calaba/instrumentationbackend/query/tests/UIQueryTest.java +134 -0
- metadata +106 -3
- 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
|
+
}
|