/* * 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 java.util.Map; import com.google.common.collect.Lists; import com.google.common.collect.Maps; 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; /** * Receives notifications from {@link org.novelang.parser.antlr.GrammarDelegate} from what's going on with delimiters. * * @author Laurent Caillette */ public class DefaultBlockDelimitersBoundary implements BlockDelimitersBoundary { private static final Logger LOGGER = LoggerFactory.getLogger( DefaultBlockDelimitersBoundary.class ); private final LocationFactory locationFactory ; private final Map< BlockDelimiter, DelimitedBlockStatus > primes = Maps.newHashMap() ; public DefaultBlockDelimitersBoundary( final LocationFactory locationFactory ) { this.locationFactory = locationFactory ; for( final BlockDelimiter blockDelimiter : BlockDelimiter.values() ) { primes.put( blockDelimiter, new DelimitedBlockStatus( blockDelimiter ) ) ; } } @Override public void startDelimitedText( final BlockDelimiter blockDelimiter, final Token startToken ) { primes.get( blockDelimiter ) .updatePosition( startToken.getLine(), startToken.getCharPositionInLine() ) .increaseStartCount() ; } @Override public void reachEndDelimiter( final BlockDelimiter blockDelimiter ) { primes.get( blockDelimiter ).increaseReachEndCount() ; } @Override public void endDelimitedText( final BlockDelimiter blockDelimiter ) { primes.get( blockDelimiter ).increaseEndPassedCount() ; } @Override public void reportMissingDelimiter( final BlockDelimiter blockDelimiter, final MismatchedTokenException mismatchedTokenException ) throws MismatchedTokenException { primes.get( blockDelimiter ).increaseMissingDelimiterCount() ; } public Iterable< DelimitedBlockStatus > getFaultyDelimitedBlocks() { final List< DelimitedBlockStatus > faultyDelimitedBlockStatuses = Lists.newArrayList() ; for( final BlockDelimiter blockDelimiter : BlockDelimiter.getPairedDelimiters() ) { final DelimitedBlockStatus status = primes.get( blockDelimiter ) ; if( ! status.isConsistent() ) { faultyDelimitedBlockStatuses.add( status ) ; } } if( faultyDelimitedBlockStatuses.isEmpty() ) { for( final BlockDelimiter blockDelimiter : BlockDelimiter.getTwinDelimiters() ) { final DelimitedBlockStatus status = primes.get( blockDelimiter ) ; if( ! status.isConsistent() ) { faultyDelimitedBlockStatuses.add( status ) ; } } } return faultyDelimitedBlockStatuses ; } @Override public Iterable<Problem> getProblems() { return BlockDelimiterTools.createProblems( locationFactory, getFaultyDelimitedBlocks() ) ; } public void dumpStatus() { final StringBuffer buffer = new StringBuffer() ; for( final BlockDelimiter blockDelimiter : BlockDelimiter.values() ) { final DelimitedBlockStatus status = primes.get( blockDelimiter ) ; buffer.append( "\n" ) ; buffer.append( String.format( "%1$16s", blockDelimiter.name() ) ) ; buffer.append( " " ) ; buffer.append( status.getInternalStatusAsString() ) ; } LOGGER.debug( buffer.toString() ) ; } }