/* * Copyright (C) 2011 Laurent Caillette * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.novelang.parser.antlr.delimited; import java.util.List; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.antlr.runtime.MismatchedTokenException; import org.antlr.runtime.Token; import org.novelang.common.LocationFactory; import org.novelang.common.Problem; import org.novelang.logger.Logger; import org.novelang.logger.LoggerFactory; /** * Delegates to multiple {@link BlockDelimitersBoundary}. * * @author Laurent Caillette */ public class DefaultBlockDelimiterSupervisor implements BlockDelimiterSupervisor{ private static final Logger LOGGER = LoggerFactory.getLogger( DefaultBlockDelimiterSupervisor.class ); private final LocationFactory locationFactory ; private final Stack stack = new Stack() ; private final List< Problem > problems = Lists.newArrayList() ; public DefaultBlockDelimiterSupervisor( final LocationFactory locationFactory ) { this.locationFactory = locationFactory; } @Override public void enterBlockDelimiterBoundary( final Token location ) { LOGGER.debug( "Entering block delimiter boundary at line " + location.getLine() ) ; stack.grow() ; } @Override public Iterable< Problem > leaveBlockDelimiterBoundary() { final Iterable< Problem > boundaryProblems = stack.getTop().getProblems() ; ( ( DefaultBlockDelimitersBoundary ) stack.getTop() ).dumpStatus() ; stack.shrink() ; Iterables.addAll( problems, boundaryProblems ) ; return boundaryProblems ; } @Override public Iterable< Problem > getProblems() { return ImmutableList.copyOf( problems ) ; } @Override public void startDelimitedText( final BlockDelimiter blockDelimiter, final Token startToken ) { if( stack.isEmpty() ) { LOGGER.warn( "Empty stack! Ignoring start of block delimiter" ) ; } else { stack.getTop().startDelimitedText( blockDelimiter, startToken ) ; } } @Override public void reachEndDelimiter( final BlockDelimiter blockDelimiter ) { if( stack.isEmpty() ) { LOGGER.warn( "Empty stack! Ignoring start of block delimiter" ) ; } else { stack.getTop().reachEndDelimiter( blockDelimiter ) ; } } @Override public void endDelimitedText( final BlockDelimiter blockDelimiter ) { if( stack.isEmpty() ) { LOGGER.warn( "Empty stack! Ignoring start of block delimiter" ) ; } else { stack.getTop().endDelimitedText( blockDelimiter ) ; } } @Override public void reportMissingDelimiter( final BlockDelimiter blockDelimiter, final MismatchedTokenException mismatchedTokenException ) throws MismatchedTokenException { if( stack.isEmpty() ) { LOGGER.warn( "Empty stack! Ignoring start of block delimiter" ) ; } else { stack.getTop().reportMissingDelimiter( blockDelimiter, mismatchedTokenException ) ; } } private class Stack { private final List< BlockDelimitersBoundary > blockDelimitersBoundaries = Lists.newArrayList() ; public void grow() { blockDelimitersBoundaries.add( new DefaultBlockDelimitersBoundary( locationFactory ) ) ; } public boolean isEmpty() { return blockDelimitersBoundaries.isEmpty() ; } public BlockDelimitersBoundary getTop() { if( blockDelimitersBoundaries.isEmpty() ) { throw new IllegalStateException( "Empty stack" ) ; } return blockDelimitersBoundaries.get( blockDelimitersBoundaries.size() - 1 ) ; } public void shrink() { if( blockDelimitersBoundaries.isEmpty() ) { throw new IllegalStateException( "Empty stack" ) ; } blockDelimitersBoundaries.remove( blockDelimitersBoundaries.size() - 1 ) ; } } }