001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.util; 017 018import java.io.BufferedReader; 019import java.io.PrintWriter; 020import java.io.File; 021import java.io.IOException; 022 023/** 024 * CommentLineParser.java は、ファイルを行単位に処理して、コメントを除去するクラスです。 025 * 1行分の文字列を読み取って、コメント部分を削除した文字列を返します。 026 * 027 * ブロックコメントの状態や、コメント除外の状態を管理しています。 028 * オブジェクト作成後、line( String ) メソッドに、ファイルから読み取った1行分の文字列を渡せば、 029 * コメントが除外された形で返されます。 030 * 行として存在しない場合は、null を返します。 031 * 032 * @og.rev 5.7.4.0 (2014/03/07) 新規追加 033 * @og.group ユーティリティ 034 * 035 * @version 6.0 036 * @author Kazuhiko Hasegawa 037 * @since JDK7.0, 038 */ 039public class CommentLineParser { 040 private String LINE_CMNT = "//" ; // ラインコメント 041 private String BLOCK_CMNT1 = "/*" ; // ブロックコメントの開始 042 private String BLOCK_CMNT2 = "*/" ; // ブロックコメントの終了 043 private char ESC_CHAR = '"' ; // コメント除外(プログラム等で使用) 044 045 private boolean escIn = false; // コメント除外中かどうか 046 private boolean blockIn = false; // ブロックコメントが継続しているかどうか 047 private boolean rtnOnly = false; // 前の行が改行のみだったかどうか。 048 049 /** 050 * コメントの種類を指定します。何も指定しない場合は、Javaコメントを初期値で設定します。 051 * 052 * Javaの場合は、順番に、// , /* , */ , "(二重引用符) になります。 053 * JavaScriptなら、// , <!-- , --> , " 054 * ORACLEなら、-- , /* , */ , "(一重引用符) になります。 055 * 056 * ※ サブクラスで分けてもよかったのですが、とりあえず引数私にしました。 057 * 058 * @og.rev 5.7.4.0 (2014/03/07) 新規追加 059 * 060 * @param lineCmnt ラインコメント 061 * @param blockCmnt1 ブロックコメントの開始 062 * @param blockCmnt2 ブロックコメントの終了 063 * @param escChar コメント除外(プログラム等で使用) 064 */ 065 public void init( final String lineCmnt,final String blockCmnt1,final String blockCmnt2,final char escChar ) { 066 LINE_CMNT = lineCmnt ; // ラインコメント 067 BLOCK_CMNT1 = blockCmnt1 ; // ブロックコメントの開始 068 BLOCK_CMNT2 = blockCmnt2 ; // ブロックコメントの終了 069 ESC_CHAR = escChar ; // コメント除外(プログラム等で使用) 070 } 071 072 /** 073 * 1行分の文字列を読み取って、コメント部分を削除した文字列を返します。 074 * 行として存在しない場合は、null を返します。 075 * 076 * @og.rev 5.7.4.0 (2014/03/07) 新規追加 077 * 078 * @param inLine 1行の文字列 079 * @return コメント削除後の1行の文字列 080 */ 081 public String line( final String inLine ) { 082 if( inLine == null ) { return null; } 083 084 int size = inLine.length(); 085 086 StringBuilder buf = new StringBuilder( size ); 087 088 for( int st=0; st<size; st++ ) { 089 char ch = inLine.charAt(st); 090 091 // ブロック外で、エスケープ文字の場合は、内外反転 092 if( !blockIn && ESC_CHAR == ch ) { escIn = !escIn ; } 093 094 if( !escIn ) { // エスケープ外ら、処理を進める 095 // ブロックコメント継続中 096 if( blockIn ) { 097 int ed = inLine.indexOf( BLOCK_CMNT2,st ) ; // 終了を見つける 098 if( ed >= 0 ) { // 終了があれば、そこまで進める。 099 blockIn = false; 100 st = ed+BLOCK_CMNT2.length(); 101 continue; // ブロックコメント脱出。再読み込み 102 } 103 break; // ブロックコメント未発見。次の行へ 104 } 105 106 // ラインコメント発見。次の行へ 107 if( inLine.startsWith( LINE_CMNT,st ) ) { break; } 108 109 // ブロックコメントを見つける 110 if( inLine.startsWith( BLOCK_CMNT1,st ) ) { 111 int ed = inLine.indexOf( BLOCK_CMNT2,st ) ; // 終了を見つける 112 if( ed >= 0 ) { 113 st = ed+BLOCK_CMNT2.length(); 114 continue; // ブロックコメント脱出。再読み込み 115 } 116 else { 117 blockIn = true; 118 } 119 break; // ブロックコメント未発見。次の行へ 120 } 121 } 122 123 // 通常の文字なので、追加する。 124 buf.append( ch ); 125 } 126 127 // rTrim() と同等の処理 128 int len = buf.length(); 129 while( 0 < len && buf.charAt(len-1) <= ' ' ) { 130 len--; 131 } 132 buf.setLength( len ); 133 134 String rtn = null; 135 // 長さが 0 の行は、連続で現れないようにします。 136 if( len == 0 ) { 137 if( !rtnOnly ) { 138 rtnOnly = true; 139 rtn = ""; 140 } 141 } 142 else { 143 rtnOnly = false; 144 rtn = buf.toString(); 145 } 146 147 return rtn ; 148 } 149 150 /** 151 * このクラスの動作確認用の、main メソッドです。 152 * 153 * Usage: java org.opengion.fukurou.util.CommentLineParser inFile outFile [encode] 154 * 155 * @param args コマンド引数配列 156 */ 157 public static void main( final String[] args ) { 158 if( args.length < 2 ) { 159 System.out.println( "Usage: java org.opengion.fukurou.util.CommentLineParser inFile outFile [encode]" ); 160 } 161 162 File inFile = new File( args[0] ); 163 File outFile = new File( args[1] ); 164 String encode = (args.length >= 3 ) ? args[3] : "UTF-8" ; 165 166 BufferedReader reader = FileUtil.getBufferedReader( inFile ,encode ); 167 PrintWriter writer = FileUtil.getPrintWriter( outFile ,encode ); 168 169 CommentLineParser clp = new CommentLineParser(); 170 171 try { 172 String line1; 173 while((line1 = reader.readLine()) != null) { 174 line1 = clp.line( line1 ); 175 if( line1 != null ) { 176 writer.println( line1 ); 177 } 178 } 179 } 180 catch( IOException ex ) { 181 String errMsg = "ファイルコピー中に例外が発生しました。\n" 182 + " inFile=[" + inFile + "] , outFile=[" + outFile + "]\n" ; 183 throw new RuntimeException( errMsg,ex ); 184 } 185 finally { 186 Closer.ioClose( reader ) ; 187 Closer.ioClose( writer ) ; 188 } 189 } 190}