001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright (c) 2009-2017 CQSE GmbH                                        |
004|                                                                          |
005+-------------------------------------------------------------------------*/
006package eu.cqse.check.framework.shallowparser.languages.cobol;
007
008import static eu.cqse.check.framework.scanner.ETokenType.DOLLAR_ELSE;
009import static eu.cqse.check.framework.scanner.ETokenType.DOLLAR_IF;
010import static eu.cqse.check.framework.scanner.ETokenType.DOT;
011import static eu.cqse.check.framework.scanner.ETokenType.ELSE;
012
013import java.util.List;
014
015import eu.cqse.check.framework.scanner.ETokenType;
016import eu.cqse.check.framework.scanner.IToken;
017import eu.cqse.check.framework.shallowparser.TokenStreamUtils;
018import eu.cqse.check.framework.shallowparser.framework.ParserState;
019import eu.cqse.check.framework.shallowparser.framework.RecognizerBase;
020
021/**
022 * Recognizes that there is not an else token after an if token has been
023 * encountered. It caters for the IF statement and $IF meta entities.
024 */
025public class NoElseRecognizer extends RecognizerBase<ECobolParserState> {
026
027        /**
028         * The IF or $IF token types.
029         */
030        private ETokenType ifType;
031
032        /**
033         * The END_IF or $END token types.
034         */
035        private ETokenType endIfType;
036
037        /** Constructor. */
038        public NoElseRecognizer(ETokenType ifType, ETokenType endIfType) {
039                this.ifType = ifType;
040                this.endIfType = endIfType;
041        }
042
043        /** {@inheritDoc} */
044        @Override
045        protected int matchesLocally(ParserState<ECobolParserState> parserState, List<IToken> tokens, int startOffset) {
046                int endIfOrDotTokenIndex = TokenStreamUtils.firstTokenOfType(tokens, startOffset, endIfType, DOT);
047                if (endIfOrDotTokenIndex == NO_MATCH) {
048                        // This is unusual but we need handle it
049                        return NO_MATCH;
050                }
051
052                List<IToken> newTokens = tokens.subList(startOffset, endIfOrDotTokenIndex);
053                int countIfTokens = TokenStreamUtils.count(newTokens, ifType);
054                ETokenType elseType = ELSE;
055                if (ifType == DOLLAR_IF) {
056                        elseType = DOLLAR_ELSE;
057                }
058
059                int countElseTokens = TokenStreamUtils.count(newTokens, elseType);
060                if (countIfTokens >= countElseTokens) {
061                        // There could be matching If-else statements or just singleton if
062                        // statements.
063                        return super.matchesLocally(parserState, newTokens, startOffset);
064                }
065
066                return NO_MATCH;
067        }
068}