/*
* 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.term_parser.states;
import net.sf.etl.parsers.PhraseParser;
import net.sf.etl.parsers.PhraseTokens;
import net.sf.etl.parsers.SyntaxRole;
import net.sf.etl.parsers.TermContext;
import net.sf.etl.parsers.Terms;
import net.sf.etl.parsers.internal.term_parser.AbstractPeer;
import net.sf.etl.parsers.internal.term_parser.DefaultTermParser;
/**
* This peer is based on state machine design. This is default unoptimized
* implementation.
*
* @author const
*/
public class StateMachinePeer extends AbstractPeer {
// NOTE POST 0.2: This is quite egoistic peer implementation. This can only
// interoperate with peers of the same type. Fix it sometime later.
/** State machine that handles end of source code */
private final static State endSourceStateMachine = makeSourceStateMachine();
/** State machine that start parsing process */
private final static State preapareStateMachine = makePrepareStateMachine();
/** Current activation for the peer */
private Activation current;
/**
* Peer factory that created this peer
*/
final StateMachinePeerFactory peerFactory;
/**
* initial context used by this peer
*/
private TermContext initialContext;
/**
* A constructor from fields.
*
* @param peerFactory
* a peer factory that created this peer
* @param termParser
* a term parser
* @param phraseParser
* a phrase parser
*/
public StateMachinePeer(StateMachinePeerFactory peerFactory,
DefaultTermParser termParser, PhraseParser phraseParser) {
super(termParser, phraseParser);
this.peerFactory = peerFactory;
}
/**
* {@inheritDoc}
*/
@Override
public boolean parseMore() {
while (!current.parseMore(phraseParser, this)) {
// parse more on activation will return only if there
// are tokens for parser to return to client. Otherwise
// just current activation has been changed.
}
// peer is never changed by this peer
return true;
}
/**
* {@inheritDoc}
*/
@Override
protected boolean startSource(String grammarContext, boolean inSegment) {
final ActivationFactory initialFactory = peerFactory
.getSegmentSequenceProduction(grammarContext);
if (initialFactory == null) {
return false;
}
final Activation endSource = new Activation(endSourceStateMachine, null);
if (inSegment) {
current = initialFactory.startWithAlternateEntry(endSource);
} else {
final Activation body = initialFactory
.startWithPrimaryEntry(endSource);
current = new Activation(preapareStateMachine, body);
}
initialContext = initialFactory.context();
return true;
}
/**
* {@inheritDoc}
*/
@Override
public TermContext getInitalContext() {
return initialContext;
}
/**
* @return a state machine for source activation.
*/
private static State makePrepareStateMachine() {
// after segment sequence has returned, only EOF might happen. So there
// choice between EOF and unreachable token. Also after EOF has been
// reported, parser peer should be never be called again. So there is
// unreachable state too.
State head = new ReturnState(false);
head = new SkipIgnorableState(head, false);
return head;
}
/**
* @return a state machine for source activation.
*/
private static State makeSourceStateMachine() {
// after segment sequence has returned, only EOF might happen. So there
// choice between EOF and unreachable token. Also after EOF has been
// reported, parser peer should be never be called again. So there is
// unreachable state too.
final State unreachable = new UnreachableState(
"Parser should never read past EOF.");
final State reportEof = new ReportToken(unreachable, Terms.EOF,
SyntaxRole.SPECIAL);
final PhraseKindChoice choice = new PhraseKindChoice(unreachable);
choice.onKind(PhraseTokens.EOF, reportEof);
return choice;
}
/**
* Set current activation
*
* @param current
* an activation to set
*/
public void setCurrentActivation(Activation current) {
this.current = current;
}
}