public void finish() {
		
		for (NonTerminal n : nonTerminals.values()) {
			n.finish();
		}
		
		// calculate highest character used
		if (scannerless) {
			int max = 0;
			for (Production p : productions) {
				for (Symbol s : p.rhs) {
					if (s instanceof CharacterClass) {
						int m = ((CharacterClass) s).getMaxCharacter();
						if (m > max) {
							max = m;
						}
					}
				}
			}
			Character.maxCharacterUsed = Character.maxCharacterInOriginalGrammar = max; // probably always 256
		}
		
		calcReachableAndRejects();
		splitReachableAndReject();
	
		verifyBasic();
		
		buildFirst();
		buildFollow();
		
		buidItemFirst(1);
		verifyTemp();
		buildItemFollow(1);
		
		buildEmptyFreeFirst();
		
		if (!scannerless) {
			calcMinimalStrings();
		}
	}