/*******************************************************************************
* Copyright (c) 2015 Bruno Medeiros and other Contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.utils.parse;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import org.junit.Test;
import melnorme.lang.tests.CommonToolingTest;
import melnorme.lang.tooling.parser.lexer.CharacterReader_SubReader;
import melnorme.utilbox.core.Assert.AssertFailedException;
public abstract class ParseSource_Test extends CommonToolingTest {
protected final String TEST_SOURCE = "abcdef";
protected ICharacterReader parseSource;
protected String source;
protected int sourceIx;
protected int lookahead;
protected void init(String source) {
this.source = source;
this.parseSource = createParseSource(source);
this.sourceIx = 0;
}
protected abstract ICharacterReader createParseSource(String source);
@Test
public void test() throws Exception { test$(); }
public void test$() throws Exception {
doTest______();
}
protected void doTest______() throws Exception {
init(TEST_SOURCE);
testLookahead('a');
assertTrue(parseSource.lookaheadMatches("abc", 0));
assertTrue(parseSource.lookaheadMatches("bc", 0) == false);
assertTrue(parseSource.lookaheadMatches("bc", 1));
assertTrue(parseSource.lookaheadMatches("abc", TEST_SOURCE.length()) == false);
assertTrue(parseSource.lookaheadMatches("", TEST_SOURCE.length()));
assertTrue(parseSource.lookaheadString(0, 6).equals(TEST_SOURCE));
parseSource.consumeAmount(2);
assertTrue(parseSource.lookaheadString(0, 4).equals("cdef"));
init(TEST_SOURCE);
testCharSource();
init(TEST_SOURCE);
assertTrue(parseSource.tryConsume("abc"));
assertTrue(parseSource.lookaheadMatches("def"));
init(TEST_SOURCE);
parseSource.consumeAmount(0);
assertTrue(parseSource.lookaheadMatches(TEST_SOURCE));
parseSource.consumeAmount(3);
assertTrue(parseSource.lookaheadMatches("def"));
parseSource.consumeAmount(3);
assertTrue(parseSource.lookaheadMatches(""));
test_consumeBeyondEnd();
parseSource.unread();
assertTrue(parseSource.lookaheadMatches("f"));
init(TEST_SOURCE);
assertTrue(parseSource.stringUntil("z").equals("abcdef"));
assertTrue(parseSource.stringUntil("a").equals(""));
assertTrue(parseSource.stringUntil("def").equals("abc"));
parseSource.consumeAhead("abc");
assertTrue(parseSource.stringUntil("def").equals(""));
assertTrue(parseSource.stringUntil("z").equals("def"));
init(TEST_SOURCE);
assertTrue(parseSource.consumeUntil("def").equals("abc"));
assertTrue(parseSource.lookaheadMatches("def"));
init(TEST_SOURCE);
assertTrue(parseSource.consumeUntil("de", true).equals("abc"));
assertTrue(parseSource.lookahead() == 'f');
assertTrue(parseSource.lookaheadMatches("f"));
}
protected void test_consumeBeyondEnd() {
assertTrue(parseSource.lookaheadIsEOS());
assertTrue(parseSource.lookaheadMatches(""));
parseSource.consumeAmount(2);
assertTrue(parseSource.lookaheadIsEOS());
parseSource.consume();
assertTrue(parseSource.lookaheadIsEOS());
parseSource.unread();
parseSource.unread();
parseSource.unread();
assertTrue(parseSource.lookaheadIsEOS());
}
protected void testCharSource() throws Exception {
// Test lookahead
checkBufferedCount(parseSource, 0);
lookahead = testLookahead(source.charAt(sourceIx));
// Test lookahead(1)
assertTrue(parseSource.lookahead(1) == source.charAt(sourceIx + 1));
// Test consume with buffered
checkBufferedCount(parseSource, 2);
assertTrue(parseSource.consume() == lookahead); sourceIx++;
checkBufferedCount(parseSource, 1);
assertTrue(parseSource.consume() == source.charAt(sourceIx)); sourceIx++;
checkBufferedCount(parseSource, 0);
checkBufferedCount(parseSource, 0);
lookahead = testLookahead(source.charAt(sourceIx));
// Test consume with buffered
checkBufferedCount(parseSource, 1);
assertTrue(lookahead == parseSource.consume()); sourceIx++;
assertTrue(lookahead == 'c');
checkBufferedCount(parseSource, 0);
assertTrue(parseSource.consume() == source.charAt(sourceIx));
sourceIx++;
while(sourceIx < source.length()) {
int ch = testLookahead(source.charAt(sourceIx));
assertTrue(parseSource.consume() == ch);
sourceIx++;
}
// EOF
testLookahead(-1);
verifyThrows(() -> parseSource.consume(), AssertFailedException.class);
}
protected void checkBufferedCount(ICharSource<?> parseSource, int expected) {
assertTrue(parseSource.bufferedCharCount() == expected);
}
protected int testLookahead(int expected) throws Exception {
return testLookAhead(parseSource, expected);
}
public static int testLookAhead(ICharSource<?> parseSource, int expected) throws Exception {
int lookahead = parseSource.lookahead();
assertTrue(lookahead == expected);
assertTrue(lookahead == parseSource.lookahead(0));
return lookahead;
}
@Test
public void test_consumeDelimited() throws Exception { test_consumeDelimited$(); }
public void test_consumeDelimited$() throws Exception {
init("blah");
testConsumeDelimitedString(parseSource, '|', '#', "blah");
init("one|two|three##|four#|xxx|###|five");
testConsumeDelimitedString(parseSource, '|', '#', "one");
testConsumeDelimitedString(parseSource, '|', '#', "two");
testConsumeDelimitedString(parseSource, '|', '#', "three#");
testConsumeDelimitedString(parseSource, '|', '#', "four|xxx");
testConsumeDelimitedString(parseSource, '|', '#', "#|five");
}
protected void testConsumeDelimitedString(ICharacterReader parseSource, char delimiter, char escapeChar,
String expected) throws Exception {
CharacterReader_SubReader subReader = new CharacterReader_SubReader(parseSource);
CharacterReader_SubReader subReaderAlt2 = new CharacterReader_SubReader(parseSource);
assertEquals(LexingUtils.consumeUntilDelimiterOrEOS(subReader, delimiter, escapeChar), expected);
// ensure advanceDelimitedString reads same number of strings;
LexingUtils.advanceDelimitedString(subReaderAlt2, delimiter, escapeChar);
assertTrue(subReader.readPosition == subReaderAlt2.readPosition);
assertEquals(LexingUtils.consumeUntilDelimiterOrEOS(parseSource, delimiter, escapeChar), expected);
}
@Test
public void testConsumeNewline() throws Exception { testConsumeNewline$(); }
public void testConsumeNewline$() throws Exception {
init("abc\ndef\r\nzzz");
assertAreEqual(LexingUtils.stringUntilNewline(parseSource, 0), "abc");
assertAreEqual(LexingUtils.stringUntilNewline(parseSource, 1), "bc");
assertAreEqual(LexingUtils.stringUntilNewline(parseSource, 3), "");
assertAreEqual(LexingUtils.consumeLine(parseSource), "abc");
assertAreEqual(LexingUtils.consumeLine(parseSource), "def");
assertAreEqual(LexingUtils.consumeLine(parseSource), "zzz");
assertAreEqual(LexingUtils.consumeLine(parseSource), null);
}
/* ----------------- Actual tests ----------------- */
public static class StringParseSource_Test extends ParseSource_Test {
@Override
protected ICharacterReader createParseSource(String source) {
return new StringCharSource(source);
}
@Override
protected void checkBufferedCount(ICharSource<?> parseSource, int expected) {
assertTrue(parseSource.bufferedCharCount() == source.length() - sourceIx);
}
}
public static class SubReader_Test extends ParseSource_Test {
@Override
protected ICharacterReader createParseSource(String source) {
return new CharacterReader_SubReader(new StringCharSource(source));
}
@Override
protected void checkBufferedCount(ICharSource<?> parseSource, int expected) {
assertTrue(parseSource.bufferedCharCount() == source.length() - sourceIx);
}
}
}