Javaのコメントを削除する


Javaのコメント
https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.7

/* text */
// text

flexを使ってコメントを削除する


flexをインストールする

$ sudo yum install flex
$ sudo yum install flex-devel


(delete_java_comments.l)

%x COMMENT
%%
"/*"          { BEGIN(COMMENT); }
<COMMENT>"*/" { BEGIN(INITIAL); }
<COMMENT>.|\n
"//".*\n      { printf("\n"); }
.|\n          { printf("%s",yytext); }
%%
main(int argc, char **argv){
  yylex();
}


コンパイルする

$ flex delete_java_comments.l 
$ cc lex.yy.c -lfl


実行してみる

$ cat test.txt
/* aaa */ aaa bbb // ccc
/* aaa */ ccc // ddd
aaa bbb /* ccc */ aaa /* // bbb */
aaa // bbb /* ccc */

$ ./a.out < test.txt
 aaa bbb 
 ccc 
aaa bbb  aaa 
aaa 


参照したURL:
・プログラムはここのです
https://books.google.co.jp/books?id=3Sr1V5J9_qMC&pg=PA40&lpg=PA40&dq=flex+bison+COMMENT&source=bl&ots=WGGrg9lLKP&sig=JosppcSvfFuf3UYhIX4gwqD7zIs&hl=ja&sa=X&ved=0ahUKEwjaj7if5vXZAhWKWbwKHQ63AJgQ6AEIWDAE#v=onepage&q=flex%20bison%20COMMENT&f=false


・dot doesn't match a newline
https://books.google.co.jp/books?id=3Sr1V5J9_qMC&pg=PA31&lpg=PA31&dq=flex+start+state+newline&source=bl&ots=WGGrg9oILN&sig=teAeeXLlk6MDIljpZ0cqtcf0PBI&hl=ja&sa=X&ved=0ahUKEwi55vOq8PXZAhVFxrwKHdpVBYwQ6AEIUzAD#v=onepage&q=flex%20start%20state%20newline&f=false

今まで知らんかった((((;゚Д゚))))

マニュアルに書いてあるわ

$ man flex
..
パターン
       入力ファイルのパターンは拡張した正規表現を使って記述します。
       以下に示します:

           x          文字 'x' にマッチ。
           .          改行を除く全ての文字(バイト)。
..


・BEGIN(INITIAL) in flex parser
 https://stackoverflow.com/questions/22527608/begininitial-in-flex-parser



PLY (Python Lex-Yacc)を使ってコメントを削除する

http://www.dabeaz.com/ply/ply.html


(delete_java_comments.py)

#!/usr/bin/env python
import sys
import ply.lex as lex

tokens = (
  'ANY',
)

def t_comment(t):
    r'(/\*(.|\n)*?\*/)|(//.*)'
    pass

def t_ANY(t):
    r'.|\n'
    sys.stdout.write("%s" % t.value[0])

def t_error(t):
    print("Illegal character '%s'" % t.value[0]),
    t.lexer.skip(1)

lexer = lex.lex()

data = sys.stdin.read()

lexer.input(data)

while True:
    tok = lexer.token()
    if not tok:
        break
    print(tok)


実行してみる

$ cat test.txt
/* aaa */ aaa bbb // ccc
/* aaa */ ccc // ddd
aaa bbb /* ccc */ aaa /* // bbb */
aaa // bbb /* ccc */

$ ./delete_java_comments.py < test.txt
 aaa bbb 
 ccc 
aaa bbb  aaa 
aaa 

↑たまたまうまく動作したと思われる。


def t_comment(t)とdef t_ANY(t)の順番を逆にしたらコメント削除しない。。
本当は、ちゃんとstart conditionの定義をしないといけないんだろう。

(delete_java_comments_fail.py)

#!/usr/bin/env python
import sys
import ply.lex as lex

tokens = (
  'ANY',
)

def t_ANY(t):
    r'.|\n'
    sys.stdout.write("%s" % t.value[0])

def t_comment(t):
    r'(/\*(.|\n)*?\*/)|(//.*)'
    pass

#def t_ANY(t):
#    r'.|\n'
#    sys.stdout.write("%s" % t.value[0])

def t_error(t):
    print("Illegal character '%s'" % t.value[0]),
    t.lexer.skip(1)

lexer = lex.lex()

data = sys.stdin.read()

lexer.input(data)

while True:
    tok = lexer.token()
    if not tok:
        break
    print(tok)


実行してみる

$ ./delete_java_comments_fail.py < test.txt
/* aaa */ aaa bbb // ccc
/* aaa */ ccc // ddd
aaa bbb /* ccc */ aaa /* // bbb */
aaa // bbb /* ccc */