/* * 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; } }