TestTokenRewriteStream.java revision 324c4644fee44b9898524c09511bd33c3f12e2df
1/*
2 * [The "BSD license"]
3 *  Copyright (c) 2010 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 */
28package org.antlr.test;
29
30import org.antlr.runtime.ANTLRStringStream;
31import org.antlr.runtime.CharStream;
32import org.antlr.runtime.TokenRewriteStream;
33import org.antlr.tool.Grammar;
34import org.antlr.tool.Interpreter;
35import org.junit.Test;
36
37public class TestTokenRewriteStream extends BaseTest {
38
39    /** Public default constructor used by TestRig */
40    public TestTokenRewriteStream() {
41    }
42
43	@Test public void testInsertBeforeIndex0() throws Exception {
44		Grammar g = new Grammar(
45			"lexer grammar t;\n"+
46			"A : 'a';\n" +
47			"B : 'b';\n" +
48			"C : 'c';\n");
49		CharStream input = new ANTLRStringStream("abc");
50		Interpreter lexEngine = new Interpreter(g, input);
51		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
52		tokens.insertBefore(0, "0");
53		String result = tokens.toString();
54		String expecting = "0abc";
55		assertEquals(expecting, result);
56	}
57
58	@Test public void testInsertAfterLastIndex() throws Exception {
59		Grammar g = new Grammar(
60			"lexer grammar t;\n"+
61			"A : 'a';\n" +
62			"B : 'b';\n" +
63			"C : 'c';\n");
64		CharStream input = new ANTLRStringStream("abc");
65		Interpreter lexEngine = new Interpreter(g, input);
66		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
67		tokens.insertAfter(2, "x");
68		String result = tokens.toString();
69		String expecting = "abcx";
70		assertEquals(expecting, result);
71	}
72
73	@Test public void test2InsertBeforeAfterMiddleIndex() throws Exception {
74		Grammar g = new Grammar(
75			"lexer grammar t;\n"+
76			"A : 'a';\n" +
77			"B : 'b';\n" +
78			"C : 'c';\n");
79		CharStream input = new ANTLRStringStream("abc");
80		Interpreter lexEngine = new Interpreter(g, input);
81		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
82		tokens.fill();
83		tokens.insertBefore(1, "x");
84		tokens.insertAfter(1, "x");
85		String result = tokens.toString();
86		String expecting = "axbxc";
87		assertEquals(expecting, result);
88	}
89
90	@Test public void testReplaceIndex0() throws Exception {
91		Grammar g = new Grammar(
92			"lexer grammar t;\n"+
93			"A : 'a';\n" +
94			"B : 'b';\n" +
95			"C : 'c';\n");
96		CharStream input = new ANTLRStringStream("abc");
97		Interpreter lexEngine = new Interpreter(g, input);
98		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
99		tokens.fill();
100		tokens.replace(0, "x");
101		String result = tokens.toString();
102		String expecting = "xbc";
103		assertEquals(expecting, result);
104	}
105
106	@Test public void testReplaceLastIndex() throws Exception {
107		Grammar g = new Grammar(
108			"lexer grammar t;\n"+
109			"A : 'a';\n" +
110			"B : 'b';\n" +
111			"C : 'c';\n");
112		CharStream input = new ANTLRStringStream("abc");
113		Interpreter lexEngine = new Interpreter(g, input);
114		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
115		tokens.fill();
116		tokens.replace(2, "x");
117		String result = tokens.toString();
118		String expecting = "abx";
119		assertEquals(expecting, result);
120	}
121
122	@Test public void testReplaceMiddleIndex() throws Exception {
123		Grammar g = new Grammar(
124			"lexer grammar t;\n"+
125			"A : 'a';\n" +
126			"B : 'b';\n" +
127			"C : 'c';\n");
128		CharStream input = new ANTLRStringStream("abc");
129		Interpreter lexEngine = new Interpreter(g, input);
130		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
131		tokens.fill();
132		tokens.replace(1, "x");
133		String result = tokens.toString();
134		String expecting = "axc";
135		assertEquals(expecting, result);
136	}
137
138    @Test public void testToStringStartStop() throws Exception {
139        Grammar g = new Grammar(
140            "lexer grammar t;\n"+
141            "ID : 'a'..'z'+;\n" +
142            "INT : '0'..'9'+;\n" +
143            "SEMI : ';';\n" +
144            "MUL : '*';\n" +
145            "ASSIGN : '=';\n" +
146            "WS : ' '+;\n");
147        // Tokens: 0123456789
148        // Input:  x = 3 * 0;
149        CharStream input = new ANTLRStringStream("x = 3 * 0;");
150        Interpreter lexEngine = new Interpreter(g, input);
151        TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
152        tokens.fill();
153        tokens.replace(4, 8, "0"); // replace 3 * 0 with 0
154
155        String result = tokens.toOriginalString();
156        String expecting = "x = 3 * 0;";
157        assertEquals(expecting, result);
158
159        result = tokens.toString();
160        expecting = "x = 0;";
161        assertEquals(expecting, result);
162
163        result = tokens.toString(0,9);
164        expecting = "x = 0;";
165        assertEquals(expecting, result);
166
167        result = tokens.toString(4,8);
168        expecting = "0";
169        assertEquals(expecting, result);
170    }
171
172    @Test public void testToStringStartStop2() throws Exception {
173        Grammar g = new Grammar(
174            "lexer grammar t;\n"+
175            "ID : 'a'..'z'+;\n" +
176            "INT : '0'..'9'+;\n" +
177            "SEMI : ';';\n" +
178            "ASSIGN : '=';\n" +
179            "PLUS : '+';\n" +
180            "MULT : '*';\n" +
181            "WS : ' '+;\n");
182        // Tokens: 012345678901234567
183        // Input:  x = 3 * 0 + 2 * 0;
184        CharStream input = new ANTLRStringStream("x = 3 * 0 + 2 * 0;");
185        Interpreter lexEngine = new Interpreter(g, input);
186        TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
187        tokens.fill();
188
189        String result = tokens.toOriginalString();
190        String expecting = "x = 3 * 0 + 2 * 0;";
191        assertEquals(expecting, result);
192
193        tokens.replace(4, 8, "0"); // replace 3 * 0 with 0
194        result = tokens.toString();
195        expecting = "x = 0 + 2 * 0;";
196        assertEquals(expecting, result);
197
198        result = tokens.toString(0,17);
199        expecting = "x = 0 + 2 * 0;";
200        assertEquals(expecting, result);
201
202        result = tokens.toString(4,8);
203        expecting = "0";
204        assertEquals(expecting, result);
205
206        result = tokens.toString(0,8);
207        expecting = "x = 0";
208        assertEquals(expecting, result);
209
210        result = tokens.toString(12,16);
211        expecting = "2 * 0";
212        assertEquals(expecting, result);
213
214        tokens.insertAfter(17, "// comment");
215        result = tokens.toString(12,18);
216        expecting = "2 * 0;// comment";
217        assertEquals(expecting, result);
218
219        result = tokens.toString(0,8); // try again after insert at end
220        expecting = "x = 0";
221        assertEquals(expecting, result);
222    }
223
224
225    @Test public void test2ReplaceMiddleIndex() throws Exception {
226		Grammar g = new Grammar(
227			"lexer grammar t;\n"+
228			"A : 'a';\n" +
229			"B : 'b';\n" +
230			"C : 'c';\n");
231		CharStream input = new ANTLRStringStream("abc");
232		Interpreter lexEngine = new Interpreter(g, input);
233		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
234		tokens.fill();
235		tokens.replace(1, "x");
236		tokens.replace(1, "y");
237		String result = tokens.toString();
238		String expecting = "ayc";
239		assertEquals(expecting, result);
240	}
241
242    @Test public void test2ReplaceMiddleIndex1InsertBefore() throws Exception {
243		Grammar g = new Grammar(
244			"lexer grammar t;\n"+
245			"A : 'a';\n" +
246			"B : 'b';\n" +
247			"C : 'c';\n");
248		CharStream input = new ANTLRStringStream("abc");
249		Interpreter lexEngine = new Interpreter(g, input);
250		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
251		tokens.fill();
252        tokens.insertBefore(0, "_");
253        tokens.replace(1, "x");
254		tokens.replace(1, "y");
255		String result = tokens.toString();
256		String expecting = "_ayc";
257		assertEquals(expecting, result);
258	}
259
260	@Test public void testReplaceThenDeleteMiddleIndex() throws Exception {
261		Grammar g = new Grammar(
262			"lexer grammar t;\n"+
263			"A : 'a';\n" +
264			"B : 'b';\n" +
265			"C : 'c';\n");
266		CharStream input = new ANTLRStringStream("abc");
267		Interpreter lexEngine = new Interpreter(g, input);
268		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
269		tokens.fill();
270		tokens.replace(1, "x");
271		tokens.delete(1);
272		String result = tokens.toString();
273		String expecting = "ac";
274		assertEquals(expecting, result);
275	}
276
277	@Test public void testInsertInPriorReplace() throws Exception {
278		Grammar g = new Grammar(
279			"lexer grammar t;\n"+
280			"A : 'a';\n" +
281			"B : 'b';\n" +
282			"C : 'c';\n");
283		CharStream input = new ANTLRStringStream("abc");
284		Interpreter lexEngine = new Interpreter(g, input);
285		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
286		tokens.fill();
287		tokens.replace(0, 2, "x");
288		tokens.insertBefore(1, "0");
289		Exception exc = null;
290		try {
291			tokens.toString();
292		}
293		catch (IllegalArgumentException iae) {
294			exc = iae;
295		}
296		String expecting = "insert op <InsertBeforeOp@[@1,1:1='b',<5>,1:1]:\"0\"> within boundaries of previous <ReplaceOp@[@0,0:0='a',<4>,1:0]..[@2,2:2='c',<6>,1:2]:\"x\">";
297		assertNotNull(exc);
298		assertEquals(expecting, exc.getMessage());
299	}
300
301	@Test public void testInsertThenReplaceSameIndex() throws Exception {
302		Grammar g = new Grammar(
303			"lexer grammar t;\n"+
304			"A : 'a';\n" +
305			"B : 'b';\n" +
306			"C : 'c';\n");
307		CharStream input = new ANTLRStringStream("abc");
308		Interpreter lexEngine = new Interpreter(g, input);
309		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
310		tokens.fill();
311		tokens.insertBefore(0, "0");
312		tokens.replace(0, "x"); // supercedes insert at 0
313		String result = tokens.toString();
314		String expecting = "0xbc";
315		assertEquals(expecting, result);
316	}
317
318	@Test public void test2InsertMiddleIndex() throws Exception {
319		Grammar g = new Grammar(
320			"lexer grammar t;\n"+
321			"A : 'a';\n" +
322			"B : 'b';\n" +
323			"C : 'c';\n");
324		CharStream input = new ANTLRStringStream("abc");
325		Interpreter lexEngine = new Interpreter(g, input);
326		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
327		tokens.fill();
328		tokens.insertBefore(1, "x");
329		tokens.insertBefore(1, "y");
330		String result = tokens.toString();
331		String expecting = "ayxbc";
332		assertEquals(expecting, result);
333	}
334
335	@Test public void test2InsertThenReplaceIndex0() throws Exception {
336		Grammar g = new Grammar(
337			"lexer grammar t;\n"+
338			"A : 'a';\n" +
339			"B : 'b';\n" +
340			"C : 'c';\n");
341		CharStream input = new ANTLRStringStream("abc");
342		Interpreter lexEngine = new Interpreter(g, input);
343		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
344		tokens.fill();
345		tokens.insertBefore(0, "x");
346		tokens.insertBefore(0, "y");
347		tokens.replace(0, "z");
348		String result = tokens.toString();
349		String expecting = "yxzbc";
350		assertEquals(expecting, result);
351	}
352
353	@Test public void testReplaceThenInsertBeforeLastIndex() throws Exception {
354		Grammar g = new Grammar(
355			"lexer grammar t;\n"+
356			"A : 'a';\n" +
357			"B : 'b';\n" +
358			"C : 'c';\n");
359		CharStream input = new ANTLRStringStream("abc");
360		Interpreter lexEngine = new Interpreter(g, input);
361		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
362		tokens.fill();
363		tokens.replace(2, "x");
364		tokens.insertBefore(2, "y");
365		String result = tokens.toString();
366		String expecting = "abyx";
367		assertEquals(expecting, result);
368	}
369
370	@Test public void testInsertThenReplaceLastIndex() throws Exception {
371		Grammar g = new Grammar(
372			"lexer grammar t;\n"+
373			"A : 'a';\n" +
374			"B : 'b';\n" +
375			"C : 'c';\n");
376		CharStream input = new ANTLRStringStream("abc");
377		Interpreter lexEngine = new Interpreter(g, input);
378		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
379		tokens.fill();
380		tokens.insertBefore(2, "y");
381		tokens.replace(2, "x");
382		String result = tokens.toString();
383		String expecting = "abyx";
384		assertEquals(expecting, result);
385	}
386
387	@Test public void testReplaceThenInsertAfterLastIndex() throws Exception {
388		Grammar g = new Grammar(
389			"lexer grammar t;\n"+
390			"A : 'a';\n" +
391			"B : 'b';\n" +
392			"C : 'c';\n");
393		CharStream input = new ANTLRStringStream("abc");
394		Interpreter lexEngine = new Interpreter(g, input);
395		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
396		tokens.fill();
397		tokens.replace(2, "x");
398		tokens.insertAfter(2, "y");
399		String result = tokens.toString();
400		String expecting = "abxy";
401		assertEquals(expecting, result);
402	}
403
404	@Test public void testReplaceRangeThenInsertAtLeftEdge() throws Exception {
405		Grammar g = new Grammar(
406			"lexer grammar t;\n"+
407			"A : 'a';\n" +
408			"B : 'b';\n" +
409			"C : 'c';\n");
410		CharStream input = new ANTLRStringStream("abcccba");
411		Interpreter lexEngine = new Interpreter(g, input);
412		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
413		tokens.fill();
414		tokens.replace(2, 4, "x");
415		tokens.insertBefore(2, "y");
416		String result = tokens.toString();
417		String expecting = "abyxba";
418		assertEquals(expecting, result);
419	}
420
421	@Test public void testReplaceRangeThenInsertAtRightEdge() throws Exception {
422		Grammar g = new Grammar(
423			"lexer grammar t;\n"+
424			"A : 'a';\n" +
425			"B : 'b';\n" +
426			"C : 'c';\n");
427		CharStream input = new ANTLRStringStream("abcccba");
428		Interpreter lexEngine = new Interpreter(g, input);
429		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
430		tokens.fill();
431		tokens.replace(2, 4, "x");
432		tokens.insertBefore(4, "y"); // no effect; within range of a replace
433		Exception exc = null;
434		try {
435			tokens.toString();
436		}
437		catch (IllegalArgumentException iae) {
438			exc = iae;
439		}
440		String expecting = "insert op <InsertBeforeOp@[@4,4:4='c',<6>,1:4]:\"y\"> within boundaries of previous <ReplaceOp@[@2,2:2='c',<6>,1:2]..[@4,4:4='c',<6>,1:4]:\"x\">";
441		assertNotNull(exc);
442		assertEquals(expecting, exc.getMessage());
443	}
444
445	@Test public void testReplaceRangeThenInsertAfterRightEdge() throws Exception {
446		Grammar g = new Grammar(
447			"lexer grammar t;\n"+
448			"A : 'a';\n" +
449			"B : 'b';\n" +
450			"C : 'c';\n");
451		CharStream input = new ANTLRStringStream("abcccba");
452		Interpreter lexEngine = new Interpreter(g, input);
453		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
454		tokens.fill();
455		tokens.replace(2, 4, "x");
456		tokens.insertAfter(4, "y");
457		String result = tokens.toString();
458		String expecting = "abxyba";
459		assertEquals(expecting, result);
460	}
461
462	@Test public void testReplaceAll() throws Exception {
463		Grammar g = new Grammar(
464			"lexer grammar t;\n"+
465			"A : 'a';\n" +
466			"B : 'b';\n" +
467			"C : 'c';\n");
468		CharStream input = new ANTLRStringStream("abcccba");
469		Interpreter lexEngine = new Interpreter(g, input);
470		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
471		tokens.fill();
472		tokens.replace(0, 6, "x");
473		String result = tokens.toString();
474		String expecting = "x";
475		assertEquals(expecting, result);
476	}
477
478	@Test public void testReplaceSubsetThenFetch() throws Exception {
479		Grammar g = new Grammar(
480			"lexer grammar t;\n"+
481			"A : 'a';\n" +
482			"B : 'b';\n" +
483			"C : 'c';\n");
484		CharStream input = new ANTLRStringStream("abcccba");
485		Interpreter lexEngine = new Interpreter(g, input);
486		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
487		tokens.fill();
488		tokens.replace(2, 4, "xyz");
489		String result = tokens.toString(0,6);
490		String expecting = "abxyzba";
491		assertEquals(expecting, result);
492	}
493
494	@Test public void testReplaceThenReplaceSuperset() throws Exception {
495		Grammar g = new Grammar(
496			"lexer grammar t;\n"+
497			"A : 'a';\n" +
498			"B : 'b';\n" +
499			"C : 'c';\n");
500		CharStream input = new ANTLRStringStream("abcccba");
501		Interpreter lexEngine = new Interpreter(g, input);
502		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
503		tokens.fill();
504		tokens.replace(2, 4, "xyz");
505		tokens.replace(3, 5, "foo"); // overlaps, error
506		Exception exc = null;
507		try {
508			tokens.toString();
509		}
510		catch (IllegalArgumentException iae) {
511			exc = iae;
512		}
513		String expecting = "replace op boundaries of <ReplaceOp@[@3,3:3='c',<6>,1:3]..[@5,5:5='b',<5>,1:5]:\"foo\"> overlap with previous <ReplaceOp@[@2,2:2='c',<6>,1:2]..[@4,4:4='c',<6>,1:4]:\"xyz\">";
514		assertNotNull(exc);
515		assertEquals(expecting, exc.getMessage());
516	}
517
518	@Test public void testReplaceThenReplaceLowerIndexedSuperset() throws Exception {
519		Grammar g = new Grammar(
520			"lexer grammar t;\n"+
521			"A : 'a';\n" +
522			"B : 'b';\n" +
523			"C : 'c';\n");
524		CharStream input = new ANTLRStringStream("abcccba");
525		Interpreter lexEngine = new Interpreter(g, input);
526		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
527		tokens.fill();
528		tokens.replace(2, 4, "xyz");
529		tokens.replace(1, 3, "foo"); // overlap, error
530		Exception exc = null;
531		try {
532			tokens.toString();
533		}
534		catch (IllegalArgumentException iae) {
535			exc = iae;
536		}
537		String expecting = "replace op boundaries of <ReplaceOp@[@1,1:1='b',<5>,1:1]..[@3,3:3='c',<6>,1:3]:\"foo\"> overlap with previous <ReplaceOp@[@2,2:2='c',<6>,1:2]..[@4,4:4='c',<6>,1:4]:\"xyz\">";
538		assertNotNull(exc);
539		assertEquals(expecting, exc.getMessage());
540	}
541
542	@Test public void testReplaceSingleMiddleThenOverlappingSuperset() throws Exception {
543		Grammar g = new Grammar(
544			"lexer grammar t;\n"+
545			"A : 'a';\n" +
546			"B : 'b';\n" +
547			"C : 'c';\n");
548		CharStream input = new ANTLRStringStream("abcba");
549		Interpreter lexEngine = new Interpreter(g, input);
550		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
551		tokens.fill();
552		tokens.replace(2, 2, "xyz");
553		tokens.replace(0, 3, "foo");
554		String result = tokens.toString();
555		String expecting = "fooa";
556		assertEquals(expecting, result);
557	}
558
559	// June 2, 2008 I rewrote core of rewrite engine; just adding lots more tests here
560
561	@Test public void testCombineInserts() throws Exception {
562		Grammar g = new Grammar(
563			"lexer grammar t;\n"+
564			"A : 'a';\n" +
565			"B : 'b';\n" +
566			"C : 'c';\n");
567		CharStream input = new ANTLRStringStream("abc");
568		Interpreter lexEngine = new Interpreter(g, input);
569		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
570		tokens.fill();
571		tokens.insertBefore(0, "x");
572		tokens.insertBefore(0, "y");
573		String result = tokens.toString();
574		String expecting = "yxabc";
575		assertEquals(expecting, result);
576	}
577
578	@Test public void testCombine3Inserts() throws Exception {
579		Grammar g = new Grammar(
580			"lexer grammar t;\n"+
581			"A : 'a';\n" +
582			"B : 'b';\n" +
583			"C : 'c';\n");
584		CharStream input = new ANTLRStringStream("abc");
585		Interpreter lexEngine = new Interpreter(g, input);
586		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
587		tokens.fill();
588		tokens.insertBefore(1, "x");
589		tokens.insertBefore(0, "y");
590		tokens.insertBefore(1, "z");
591		String result = tokens.toString();
592		String expecting = "yazxbc";
593		assertEquals(expecting, result);
594	}
595
596	@Test public void testCombineInsertOnLeftWithReplace() throws Exception {
597		Grammar g = new Grammar(
598			"lexer grammar t;\n"+
599			"A : 'a';\n" +
600			"B : 'b';\n" +
601			"C : 'c';\n");
602		CharStream input = new ANTLRStringStream("abc");
603		Interpreter lexEngine = new Interpreter(g, input);
604		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
605		tokens.fill();
606		tokens.replace(0, 2, "foo");
607		tokens.insertBefore(0, "z"); // combine with left edge of rewrite
608		String result = tokens.toString();
609		String expecting = "zfoo";
610		assertEquals(expecting, result);
611	}
612
613	@Test public void testCombineInsertOnLeftWithDelete() throws Exception {
614		Grammar g = new Grammar(
615			"lexer grammar t;\n"+
616			"A : 'a';\n" +
617			"B : 'b';\n" +
618			"C : 'c';\n");
619		CharStream input = new ANTLRStringStream("abc");
620		Interpreter lexEngine = new Interpreter(g, input);
621		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
622		tokens.fill();
623		tokens.delete(0, 2);
624		tokens.insertBefore(0, "z"); // combine with left edge of rewrite
625		String result = tokens.toString();
626		String expecting = "z"; // make sure combo is not znull
627		assertEquals(expecting, result);
628	}
629
630	@Test public void testDisjointInserts() throws Exception {
631		Grammar g = new Grammar(
632			"lexer grammar t;\n"+
633			"A : 'a';\n" +
634			"B : 'b';\n" +
635			"C : 'c';\n");
636		CharStream input = new ANTLRStringStream("abc");
637		Interpreter lexEngine = new Interpreter(g, input);
638		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
639		tokens.fill();
640		tokens.insertBefore(1, "x");
641		tokens.insertBefore(2, "y");
642		tokens.insertBefore(0, "z");
643		String result = tokens.toString();
644		String expecting = "zaxbyc";
645		assertEquals(expecting, result);
646	}
647
648	@Test public void testOverlappingReplace() throws Exception {
649		Grammar g = new Grammar(
650			"lexer grammar t;\n"+
651			"A : 'a';\n" +
652			"B : 'b';\n" +
653			"C : 'c';\n");
654		CharStream input = new ANTLRStringStream("abcc");
655		Interpreter lexEngine = new Interpreter(g, input);
656		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
657		tokens.fill();
658		tokens.replace(1, 2, "foo");
659		tokens.replace(0, 3, "bar"); // wipes prior nested replace
660		String result = tokens.toString();
661		String expecting = "bar";
662		assertEquals(expecting, result);
663	}
664
665	@Test public void testOverlappingReplace2() throws Exception {
666		Grammar g = new Grammar(
667			"lexer grammar t;\n"+
668			"A : 'a';\n" +
669			"B : 'b';\n" +
670			"C : 'c';\n");
671		CharStream input = new ANTLRStringStream("abcc");
672		Interpreter lexEngine = new Interpreter(g, input);
673		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
674		tokens.fill();
675		tokens.replace(0, 3, "bar");
676		tokens.replace(1, 2, "foo"); // cannot split earlier replace
677		Exception exc = null;
678		try {
679			tokens.toString();
680		}
681		catch (IllegalArgumentException iae) {
682			exc = iae;
683		}
684		String expecting = "replace op boundaries of <ReplaceOp@[@1,1:1='b',<5>,1:1]..[@2,2:2='c',<6>,1:2]:\"foo\"> overlap with previous <ReplaceOp@[@0,0:0='a',<4>,1:0]..[@3,3:3='c',<6>,1:3]:\"bar\">";
685		assertNotNull(exc);
686		assertEquals(expecting, exc.getMessage());
687	}
688
689	@Test public void testOverlappingReplace3() throws Exception {
690		Grammar g = new Grammar(
691			"lexer grammar t;\n"+
692			"A : 'a';\n" +
693			"B : 'b';\n" +
694			"C : 'c';\n");
695		CharStream input = new ANTLRStringStream("abcc");
696		Interpreter lexEngine = new Interpreter(g, input);
697		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
698		tokens.fill();
699		tokens.replace(1, 2, "foo");
700		tokens.replace(0, 2, "bar"); // wipes prior nested replace
701		String result = tokens.toString();
702		String expecting = "barc";
703		assertEquals(expecting, result);
704	}
705
706	@Test public void testOverlappingReplace4() throws Exception {
707		Grammar g = new Grammar(
708			"lexer grammar t;\n"+
709			"A : 'a';\n" +
710			"B : 'b';\n" +
711			"C : 'c';\n");
712		CharStream input = new ANTLRStringStream("abcc");
713		Interpreter lexEngine = new Interpreter(g, input);
714		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
715		tokens.fill();
716		tokens.replace(1, 2, "foo");
717		tokens.replace(1, 3, "bar"); // wipes prior nested replace
718		String result = tokens.toString();
719		String expecting = "abar";
720		assertEquals(expecting, result);
721	}
722
723	@Test public void testDropIdenticalReplace() throws Exception {
724		Grammar g = new Grammar(
725			"lexer grammar t;\n"+
726			"A : 'a';\n" +
727			"B : 'b';\n" +
728			"C : 'c';\n");
729		CharStream input = new ANTLRStringStream("abcc");
730		Interpreter lexEngine = new Interpreter(g, input);
731		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
732		tokens.fill();
733		tokens.replace(1, 2, "foo");
734		tokens.replace(1, 2, "foo"); // drop previous, identical
735		String result = tokens.toString();
736		String expecting = "afooc";
737		assertEquals(expecting, result);
738	}
739
740	@Test public void testDropPrevCoveredInsert() throws Exception {
741		Grammar g = new Grammar(
742			"lexer grammar t;\n"+
743			"A : 'a';\n" +
744			"B : 'b';\n" +
745			"C : 'c';\n");
746		CharStream input = new ANTLRStringStream("abc");
747		Interpreter lexEngine = new Interpreter(g, input);
748		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
749		tokens.fill();
750		tokens.insertBefore(1, "foo");
751		tokens.replace(1, 2, "foo"); // kill prev insert
752		String result = tokens.toString();
753		String expecting = "afoofoo";
754		assertEquals(expecting, result);
755	}
756
757	@Test public void testLeaveAloneDisjointInsert() throws Exception {
758		Grammar g = new Grammar(
759			"lexer grammar t;\n"+
760			"A : 'a';\n" +
761			"B : 'b';\n" +
762			"C : 'c';\n");
763		CharStream input = new ANTLRStringStream("abcc");
764		Interpreter lexEngine = new Interpreter(g, input);
765		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
766		tokens.fill();
767		tokens.insertBefore(1, "x");
768		tokens.replace(2, 3, "foo");
769		String result = tokens.toString();
770		String expecting = "axbfoo";
771		assertEquals(expecting, result);
772	}
773
774	@Test public void testLeaveAloneDisjointInsert2() throws Exception {
775		Grammar g = new Grammar(
776			"lexer grammar t;\n"+
777			"A : 'a';\n" +
778			"B : 'b';\n" +
779			"C : 'c';\n");
780		CharStream input = new ANTLRStringStream("abcc");
781		Interpreter lexEngine = new Interpreter(g, input);
782		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
783		tokens.fill();
784		tokens.replace(2, 3, "foo");
785		tokens.insertBefore(1, "x");
786		String result = tokens.toString();
787		String expecting = "axbfoo";
788		assertEquals(expecting, result);
789	}
790
791	@Test public void testInsertBeforeTokenThenDeleteThatToken() throws Exception {
792		Grammar g = new Grammar(
793			"lexer grammar t;\n"+
794			"A : 'a';\n" +
795			"B : 'b';\n" +
796			"C : 'c';\n");
797		CharStream input = new ANTLRStringStream("abc");
798		Interpreter lexEngine = new Interpreter(g, input);
799		TokenRewriteStream tokens = new TokenRewriteStream(lexEngine);
800		tokens.fill();
801		tokens.insertBefore(2, "y");
802		tokens.delete(2);
803		String result = tokens.toString();
804		String expecting = "aby";
805		assertEquals(expecting, result);
806	}
807
808}
809