/*
* Reference ETL Parser for Java
* Copyright (c) 2000-2009 Constantine A Plotnikov
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.sf.etl.parsers.internal.phrase_parser;
import java.io.Reader;
import net.sf.etl.parsers.Lexer;
import net.sf.etl.parsers.LexerFactory;
import net.sf.etl.parsers.LexerStates;
import net.sf.etl.parsers.PhraseParser;
import net.sf.etl.parsers.PhraseToken;
import net.sf.etl.parsers.PhraseTokens;
import net.sf.etl.parsers.TextPos;
import net.sf.etl.parsers.Tokens;
import net.sf.etl.parsers.internal.AbstractParserImpl;
import org.xml.sax.InputSource;
/**
* A default implementation of phrase parser.
*/
public final class DefaultPhraseParser extends AbstractParserImpl<PhraseToken>
implements PhraseParser {
/**
* current token
*/
PhraseToken currentToken;
/**
* special not started state
*/
private static final PhraseToken NOT_STARTED = null;
/**
* a lexer
*/
Lexer lexer;
/**
* current parsing state
*/
ParsingState state;
/** a system identifier */
String systemId;
/**
* If true, the partial tokens are reported
*/
private boolean reportPartialTokens = false;
/**
* {@inheritDoc}
*/
public boolean arePartialTokensReported() {
return reportPartialTokens;
}
/**
* {@inheritDoc}
*/
public void setPartialTokensReported(boolean value) {
reportPartialTokens = value;
if (lexer != null) {
lexer.setPartialTokensReported(value);
}
}
/**
* start parsing
*
* @param systemId
* a system identifier
* @param lexer
* an lexer
*/
private void parse(String systemId, Lexer lexer) {
this.lexer = lexer;
this.lexer.setPartialTokensReported(reportPartialTokens);
this.systemId = systemId;
new SegmentSequenceState(this, false);
}
/**
* {@inheritDoc}
*/
public void close() {
checkClosed();
isClosed = true;
lexer.close();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "PhraseParser[token=" + currentToken + ",lexer=" + lexer + "]";
}
/**
* {@inheritDoc}
*/
public PhraseToken current() {
checkValid();
if (currentToken == null) {
throw new IllegalStateException("Parsing has not yet started.");
}
return currentToken;
}
/**
* {@inheritDoc}
*/
public boolean advance() {
checkValid();
try {
if (currentToken != null && currentToken.kind() == PhraseTokens.EOF) {
return false;
}
if (currentToken == NOT_STARTED || currentToken.hasToken()) {
lexer.advance();
}
while (state != null) {
if (state.parse()) {
return true;
}
}
if (lexer.current().kind() == Tokens.EOF) {
currentToken = new PhraseToken(PhraseTokens.EOF, lexer
.current());
} else {
throw new RuntimeException(
"segment parser should not call this. there is possibly an error.");
}
return true;
} catch (final RuntimeException ex) {
invalidate();
throw ex;
} catch (final Error ex) {
invalidate();
throw ex;
}
}
/**
* {@inheritDoc}
*/
public void parse(InputSource source) {
try {
lexer = LexerFactory.newInstance().newLexer();
lexer.setEntityResolver(getEntityResolver());
lexer.parse(source);
parse(lexer.getSystemId(), lexer);
} catch (final RuntimeException ex) {
invalidate();
throw ex;
} catch (final Error ex) {
invalidate();
throw ex;
}
}
/**
* {@inheritDoc}
*/
public void reparse(String systemId, Reader r, TextPos start) {
try {
lexer = LexerFactory.newInstance().newLexer();
lexer.reparse(systemId, r, start, LexerStates.DEFAULT_STATE);
parse(systemId, lexer);
} catch (final RuntimeException ex) {
invalidate();
throw ex;
} catch (final Error ex) {
invalidate();
throw ex;
}
}
/**
* {@inheritDoc}
*/
public String getSystemId() {
return systemId;
}
}