package fortran.lexer;

import static fortran.lexer.LiteralType.*;

import java.util.AbstractSet;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;

import com.google.common.collect.UnmodifiableIterator;

/**
 * This class contains the definition of the subset of {@link LiteralType}s,
 * that directly represent a keyword of the FORTRAN language:
 * <ul>
 *  <li>Control Statements:
 *  <tt>GO, TO, ASSIGN, IF,
 *  SENSE, LIGHT, SWITCH,
 *  ACCUMULATOR, OVERFLOW, QUOTIENT, DIVIDE, CHECK,
 *  PAUSE, STOP, DO, CONTINUE</tt></li>
 *  <li>Input/Output:
 *  <tt>READ, PUNCH, PRINT, INPUT,
 *  WRITE, OUTPUT,
 *  FORMAT,
 *  TAPE, DRUM,
 *  END, FILE, REWIND, BACKSPACE</tt></li>
 *  <li>Specification Statements:
 *  <tt>DIMENSTION, EQUIVALENCE, FREQUENCY</tt></li>
 * </ul> 
 * @author oreissig
 */
public class Keyword {
	/**
	 * All {@link LiteralType}s, that directly represent a
	 * keyword of the FORTRAN language.
	 */
	public static final Set<LiteralType> set;
	
	static {
		EnumSet<LiteralType> keywords = EnumSet.of(
			    // Control Statements
			    GO, TO, ASSIGN, IF,
			    SENSE, LIGHT, SWITCH,
			    ACCUMULATOR, OVERFLOW, QUOTIENT, DIVIDE, CHECK,
			    PAUSE, STOP, DO, CONTINUE,
			    // Input/Output
			    READ, PUNCH, PRINT, INPUT,
			    WRITE, OUTPUT,
			    FORMAT,
			    TAPE, DRUM,
			    END, FILE, REWIND, BACKSPACE,
			    // Specification Statements
			    DIMENSTION, EQUIVALENCE, FREQUENCY
				);
		set = Collections.unmodifiableSet(keywords);
	}
	
	/**
	 * String representations of all {@link LiteralType}s
	 * contained in {@link #set}.
	 */
	public static final Set<String> names = new AbstractSet<String>() {
		@Override
		public boolean contains(Object o) {
			try {
				LiteralType e = LiteralType.valueOf(o.toString().toUpperCase());
				return set.contains(e);
			} catch (IllegalArgumentException e) {
				return false;
			}
		}
		
		@Override
		public boolean remove(Object o) {
			throw new UnsupportedOperationException();
		}
		
		@Override
		public Iterator<String> iterator() {
			final Iterator<LiteralType> i = set.iterator();
			return new UnmodifiableIterator<String>() {
				@Override
				public boolean hasNext() {
					return i.hasNext();
				}
				
				@Override
				public String next() {
					return i.next().name();
				}
			};
		}
		
		@Override
		public int size() {
			return set.size();
		}
	};
	
	/**
	 * Tells whether or not a given string represents a valid
	 * keyword in the FORTRAN language.
	 * 
	 * @param string to test
	 * @return true if it is a keyword, false otherwise
	 */
	public static boolean isKeyword(String string) {
		return names.contains(string);
	}
	
	private Keyword() {
		// forbid instantiation
	}
}

@@ -226,36 +226,64 @@
 mon.
-collect.Unmodifiable
+base.Function;%0Aimport com.google.common.collect.
 Iterator
 ;%0A%0A/
@@ -278,16 +278,17 @@
 Iterator
+s
 ;%0A%0A/**%0A 
@@ -2110,21 +2110,22 @@
 () %7B%0A%09%09%09
-final
+return
  Iterato
@@ -2129,207 +2129,129 @@
 ator
-%3CLiteralType%3E i = set.iterator();%0A%09%09%09return new UnmodifiableIterator%3CString%3E() %7B%0A%09%09%09%09@Override%0A%09%09%09%09public boolean hasNext() %7B%0A%09%09%09%09%09return i.hasNext();%0A%09%09%09%09%7D%0A%09%09%09%09%0A%09%09%09%09@Override%0A%09%09%09%09public String next(
+s.transform(set.iterator(), new Function%3CLiteralType, String%3E() %7B%0A%09%09%09%09@Override%0A%09%09%09%09public String apply(LiteralType input
 ) %7B%0A
@@ -2267,15 +2267,12 @@
 rn i
-.next()
+nput
 .nam
@@ -2286,16 +2286,17 @@
 %09%09%7D%0A%09%09%09%7D
+)
 ;%0A%09%09%7D%0A%09%09

use guava transformation