001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright 2005-2011 the ConQAT Project                                   |
004|                                                                          |
005| Licensed under the Apache License, Version 2.0 (the "License");          |
006| you may not use this file except in compliance with the License.         |
007| You may obtain a copy of the License at                                  |
008|                                                                          |
009|    http://www.apache.org/licenses/LICENSE-2.0                            |
010|                                                                          |
011| Unless required by applicable law or agreed to in writing, software      |
012| distributed under the License is distributed on an "AS IS" BASIS,        |
013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014| See the License for the specific language governing permissions and      |
015| limitations under the License.                                           |
016+-------------------------------------------------------------------------*/
017package eu.cqse.check.framework.shallowparser.languages.abap;
018
019import static eu.cqse.check.framework.scanner.ETokenType.DOT;
020import static eu.cqse.check.framework.scanner.ETokenType.ENDMODULE;
021import static eu.cqse.check.framework.scanner.ETokenType.INPUT;
022import static eu.cqse.check.framework.scanner.ETokenType.MODULE;
023import static eu.cqse.check.framework.scanner.ETokenType.OUTPUT;
024
025import java.util.EnumSet;
026import java.util.List;
027
028import eu.cqse.check.framework.scanner.IToken;
029import eu.cqse.check.framework.shallowparser.TokenStreamUtils;
030import eu.cqse.check.framework.shallowparser.framework.ParserState;
031import eu.cqse.check.framework.shallowparser.framework.RecognizerBase;
032import eu.cqse.check.framework.shallowparser.languages.abap.AbapShallowParser.EAbapParserStates;
033
034/**
035 * Precondition recognizer that matches if a module block (not a module
036 * statement) starts at the current location, but does not consume any tokens. A
037 * module block starts with one of:
038 * 
039 * <pre>
040 * module x.
041 * module x input.
042 * module x output.
043 * </pre>
044 * 
045 * and ends with <code>endmodule</code>.
046 * <p>
047 * This recognizer is used to distinguish module statements (that invoke a
048 * module) from module declarations (matched by this recognizer).
049 * <p>
050 * Note that module statements cannot appear inside module blocks.
051 */
052public class ModuleBlockStartRecognizer extends RecognizerBase<EAbapParserStates> {
053
054        /** {@inheritDoc} */
055        @Override
056        protected int matchesLocally(ParserState<EAbapParserStates> parserState, List<IToken> tokens, int startOffset) {
057                if (tokens.size() < startOffset + 3) {
058                        return NO_MATCH;
059                }
060
061                if (tokens.get(startOffset).getType() != MODULE) {
062                        return NO_MATCH;
063                }
064
065                if (!EnumSet.of(DOT, INPUT, OUTPUT).contains(tokens.get(startOffset + 2).getType())) {
066                        return NO_MATCH;
067                }
068
069                int endModuleIndex = TokenStreamUtils.firstTokenOfType(tokens, startOffset, ENDMODULE);
070                if (endModuleIndex == -1) {
071                        return NO_MATCH;
072                }
073
074                int moduleIndex = TokenStreamUtils.firstTokenOfType(tokens, startOffset + 1, MODULE);
075                if (moduleIndex != -1 && moduleIndex < endModuleIndex) {
076                        return NO_MATCH;
077                }
078
079                return startOffset;
080        }
081}