/*******************************************************************************
* 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.assertNotNull;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
public interface ICharSource<EXC extends Exception> extends IBasicCharSource<EXC> {
@Override
default int lookahead() throws EXC {
return lookahead(0);
}
int lookahead(int offset) throws EXC;
/** @return number of characters available that can be consumed without having to wait for external input,
* and with no risk exceptions being thrown.
*
* Use intended for tests or performance optimizations
*/
int bufferedCharCount();
/** Return a substring from the source, starting at given offset, with given length.
* Although a default implementation could be provided, this is left for subclasses to implement,
* so that an optimized version can be defined. */
String lookaheadString(int offset, int length) throws EXC;
/* ----------------- Some common helpers ----------------- */
default boolean tryConsume(String string) throws EXC {
for(int ix = 0; ix < string.length(); ix++) {
if(lookahead(ix) != string.charAt(ix)) {
return false;
}
}
consumeAmount(string.length());
return true;
}
default String consumeString(int length) throws EXC {
String string = lookaheadString(0, length);
consumeAmount(length);
return string;
}
default void consumeAhead(String string) throws EXC {
assertNotNull(string);
assertTrue(lookaheadMatches(string));
consumeAmount(string.length());
}
default boolean lookaheadMatches(String string) throws EXC {
return lookaheadMatches(string, 0);
}
default boolean lookaheadMatches(String string, int fromIndex) throws EXC {
for(int ix = 0; ix < string.length(); ix++) {
if(lookahead(ix + fromIndex) != string.charAt(ix)) {
return false;
}
}
return true;
}
/* ----------------- ----------------- */
default String stringUntil(String string) throws EXC {
int length = 0;
while(true) {
int charAtIx = lookahead(length);
if(charAtIx == EOS || lookaheadMatches(string, length)) {
break;
}
length++;
}
return lookaheadString(0, length);
}
default String consumeUntil(String string) throws EXC {
String stringUntil = stringUntil(string);
consumeAmount(stringUntil.length());
return stringUntil;
}
/**
* Consume characters until lookhead position matches given endString
* If consumeEndString, also consume endString from source (although this is not included in result)
*
* @return the consumed characters until endString
*/
default String consumeUntil(String endString, boolean consumeEndString) throws EXC {
String firstString = consumeUntil(endString);
if(consumeEndString) {
tryConsume(endString);
}
return firstString;
}
}