001package eu.cqse.check.framework.scanner;
002
003import java.util.EnumSet;
004
005import org.conqat.lib.commons.collections.ILookahead;
006
007/**
008 * {@link IStatementOracle} for Cobol.
009 */
010public class CobolStatementOracle implements IStatementOracle {
011
012        /** Those token types mark the beginning of a new statement */
013        private final static EnumSet<ETokenType> BOS = EnumSet.of(
014                        // real verbs:
015                        ETokenType.ACCEPT, ETokenType.ADD, ETokenType.ALLOCATE, ETokenType.ALTER, ETokenType.CALL,
016                        ETokenType.CANCEL, ETokenType.CLOSE, ETokenType.COMPUTE, ETokenType.CONTINUE, ETokenType.DELETE,
017                        ETokenType.DISPLAY, ETokenType.DIVIDE, ETokenType.EVALUATE, ETokenType.EXIT, ETokenType.GO,
018                        ETokenType.GOBACK, ETokenType.GOTO, ETokenType.IF, ETokenType.INITIALIZE, ETokenType.INSPECT,
019                        ETokenType.INVOKE, ETokenType.MERGE, ETokenType.MOVE, ETokenType.MULTIPLY, ETokenType.OPEN,
020                        ETokenType.PERFORM, ETokenType.RELEASE, ETokenType.RETURN, ETokenType.REWRITE, ETokenType.SEARCH,
021                        ETokenType.SET, ETokenType.SORT, ETokenType.START, ETokenType.STOP, ETokenType.STRING, ETokenType.SUBTRACT,
022                        ETokenType.UNSTRING, ETokenType.WRITE, ETokenType.XML,
023                        // other begin of statement:
024                        ETokenType.BASIS, ETokenType.CBL, ETokenType.CONTROL, ETokenType.COPY, ETokenType.DELETE, ETokenType.EJECT,
025                        ETokenType.ENTER, ETokenType.INSERT, ETokenType.READY, ETokenType.RESET, ETokenType.REPLACE,
026                        ETokenType.SERVICE, ETokenType.SKIP1, ETokenType.SKIP2, ETokenType.SKIP3, ETokenType.TITLE, ETokenType.USE,
027                        ETokenType.WHEN,
028                        // begin of statement for DELTA COBOL:
029                        ETokenType.PREPROCESSOR_DIRECTIVE);
030
031        /** Those token types mark the end of a statement */
032        private final static EnumSet<ETokenType> EOS = EnumSet.of(ETokenType.DOT, ETokenType.SENTINEL,
033                        ETokenType.END_ACCEPT, ETokenType.END_ADD, ETokenType.END_CALL, ETokenType.END_COMPUTE,
034                        ETokenType.END_DELETE, ETokenType.END_DISPLAY, ETokenType.END_DIVIDE, ETokenType.END_EVALUATE,
035                        ETokenType.END_IF, ETokenType.END_INVOKE, ETokenType.END_MULTIPLY, ETokenType.END_PERFORM,
036                        ETokenType.END_READ, ETokenType.END_RECEIVE, ETokenType.END_RETURN, ETokenType.END_REWRITE,
037                        ETokenType.END_SEARCH, ETokenType.END_START, ETokenType.END_STRING, ETokenType.END_UNSTRING,
038                        ETokenType.END_UNSTRING, ETokenType.END_WRITE, ETokenType.END_XML);
039
040        /** {@inheritDoc} */
041        @Override
042        public <X extends Exception> boolean isEndOfStatementTokenType(ETokenType tokenType,
043                        ILookahead<ETokenType, X> lookahead) throws X {
044                return EOS.contains(tokenType) || BOS.contains(lookahead.lookahead(1));
045        }
046
047        /** {@inheritDoc} */
048        @Override
049        public <X extends Exception> boolean isEndOfStatementToken(ETokenType tokenType, ILookahead<IToken, X> lookahead)
050                        throws X {
051                return EOS.contains(tokenType)
052                                || (lookahead.lookahead(1) != null && BOS.contains(lookahead.lookahead(1).getType()));
053        }
054
055}