import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
/**
 * HTML解析プログラム(タグの対応をチェックするだけ）
 */
public class HTMLChecker {
    static ArrayList tag_array;
    static ArrayList tagcheck_array;
    static boolean flg;
    static int error_count = 0;
	/**
	 * メインメソッド
	 */
	public static void main(String[] args) throws IOException{
		prepare();
		file_read_and_write(args[0]);
		checkRestOpenTag();
		correct_check();
	}
	/**
	 * プログラムの初期処理をするメソッド
	 */
	public static void prepare(){
		tag_array = new ArrayList();
		tagcheck_array = new ArrayList();
		flg = true;
	}
	/**
	 * ファイルの読み込み・画面に出力するメソッド
	 */
	public static void file_read_and_write(String filename) throws IOException{
		String line;
    	FileReader fi = new FileReader(filename);
		BufferedReader buf = new BufferedReader(fi);
		line = buf.readLine();
		while(line != null){
			System.out.println(line);
			tag_line_check(line);
			line = buf.readLine();
		}
    }
	/**
	 * 入力されたHTMLファイルのタグが対応付けられているかの結果を出力する
	 */
    public static void correct_check(){
    	if(flg){
			System.out.println("正常！");
		}else{
			System.out.println("エラー "+ error_count + " 個！");
		}
    	System.out.println("あなたが使用したタグ");
    	for(int i = 0;i < tag_array.size();i++){
    		System.out.println("<" + (String)(tag_array.get(i)) + ">");
    	}
    }
    /**
	 * 読み込まれた行に対し、1文字ずつ取り出して、タグがないか等をチェックするメソッド。
	 */
    public static void tag_line_check(String line){
    	String tagname = "";
    	int state = 0;
    	for(int i = 0;i < line.length();i++){
			String c = getCharacter(line,i);
			if(c.equals("<")){
				state = 1;
				tagname = "";
			}else{
				if(c.equals("/")){
					if(state == 1){
						state = 2;
					}
				}else{
					if(c.equals(">")){
						if(state == 1){
							add_tag_to_array(tagname);
						}else{
							check_closetag(tagname);
						}
						state = 0;
					}else{
						if(state == 1 || state == 2){
							tagname = tagname + c;
						}
					}
				}
			}
		}
    }
    /**
	 * 引数として与えられた行の指定された文字数目の文字を返すメソッド
	 */
    public static String getCharacter(String line,int n){
		return line.substring(n,n+1);
	}
    /**
	 * リストにHTMLファイルで使用されているタグを登録（追加）するメソッド
	 */
    public static void add_tag_to_array(String tagname){
    	tag_array.add(tagname);
		tagcheck_array.add(tagname);
    }
    /**
	 * 閉じタグが出現したときに、対応する開始タグがあるかチェックするメソッド
	 */
    public static void check_closetag(String tagname){
    	String cs = (String)(tagcheck_array.get(tagcheck_array.size() - 1));
		if(!cs.equals(tagname)){
			flg = false;
			isTagExist(tagname);
		}else{
			tagcheck_array.remove(tagcheck_array.size() - 1);
		}
    }
    /**
	 * リストの中に、閉じタグと同じ名前のタグがあるかチェックするメソッド。
	 */
    public static void isTagExist(String tagname){
    	boolean exist = false;
    	for(int i = tagcheck_array.size() - 2;i >= 0;i--){
    		String cs = (String)(tagcheck_array.get(i));
    		if(cs.equals(tagname)){
    			int size = tagcheck_array.size();
    			for(int j = i + 1;j < size;j++){
    				System.out.println("対応する終了タグがありません。-> "+(String)(tagcheck_array.get(j)));
    				error_count = error_count + 1;
    			}
    			for(int j = i + 1;j < size;j++){
    				tagcheck_array.remove(i + 1);
    			}
    			tagcheck_array.remove(i);
    			exist = true;
    		}
    	}
    	if(!exist){
	    	System.out.println("対応する開始タグがありません。-> "+ tagname);
	    	error_count = error_count + 1;
	    	tag_array.add(tagname);
	    }
    }
    /**
	 * HTMLファイルが読み込み終了の時点で、閉じられていないタグがないかチェックするメソッド
	 */
    public static void checkRestOpenTag(){
    	if(tagcheck_array.size() != 0){
    		for(int i = 0;i < tagcheck_array.size();i++){
    			System.out.println("対応する終了タグがありません -> " + (String)(tagcheck_array.get(i)));
    			error_count = error_count + 1;
    		}
    		flg = false;
    	}
    }
}
