コード圧縮
Posted feedbacks - Flatten
Nested Hiddenこんな感じでしょうか
$ runhaskell HaskellParser.hs < HaskellParser.hs
module Main where { import Language.Haskell.Parser; import Language.Haskell.Pretty; import Language.Haskell.Syntax; import Text.PrettyPrint.HughesPJ; main = do { (ParseOk x) <- return . parseModule =<< getContents; putStrLn $ prettyPrintStyleMode (Style OneLineMode maxBound 0) defaultMode{layout = PPSemiColon} x}}
1 2 3 4 5 6 7 8 9 10 | module Main where
import Language.Haskell.Parser
import Language.Haskell.Pretty
import Language.Haskell.Syntax
import Text.PrettyPrint.HughesPJ
main = do
(ParseOk x) <- return . parseModule =<< getContents
putStrLn $ prettyPrintStyleMode (Style OneLineMode maxBound 0) defaultMode {layout = PPSemiColon} x
|
Squeak Smalltalk で。
1 2 3 4 5 6 7 | | method |
method := Integer >> #factorial.
^method methodClass prettyPrinterClass
format: method getSource
in: method methodClass
notifying: nil
decorated: false.
|
すごいマイナス評価・・・!
Rのdeparse()は、適切にインデントを入れなおしてくれるという
(このお題的には)余計な機能がついてますが、とりあえずこんな感じで。
> writeLines(deparse(parse(text=code, srcfile=NULL)))
expression(sapply(1:10, function(n) {
for (i in 1:n) {
print(n)
}
print("------")
}))
1 2 3 4 5 6 7 8 9 10 11 12 | code <- ' sapply(1:10, function(n)
{
for(i in 1:n)
{
print(n)
}
print("------")
}
# comment
)
'
writeLines(deparse(parse(text=code, srcfile=NULL)))
|
:D
1 | import this
|
4番目の条件がなければ、 私はプラス評価しますよ(やらないけど)。 「コンパイラが構文解析した結果を利用する」 なら楽しそうじゃないですか。
Gauche で書いてみました。基本的に read して write しただけです。
1 2 3 4 | (define (main args)
(for-each write
(call-with-input-file (cadr args)
(cut port->list read <>))))
|
1 2 | <?php
echo php_strip_whitespace("filename.php");
|
C#でまじめにやってみた。
(あれ?α置換でも同じようなコード書いた気が)
動けばよかろう、な品質です。
(あれ?α置換でも同じようなコード書いた気が)
動けばよかろう、な品質です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | using System;
using System.Text;
using System.IO;
namespace DouKaku
{
class Program
{
/**
* 内部状態
* 通常,文字リテラル,文字列リテラル,逐語文字列リテラル,行コメント,範囲コメント
*/
enum State { None, Char, RegularStr, VerbatimStr, LineComment, DelimitedComment }
/* コード圧縮を行う */
static string Compress(string code)
{
string WhiteSpace = " \t\r\n"; //空白
string LineTerminator = "\r\n"; //行終端
string Kigou = @"{}[]().,:;+-*/%&|^!~=<>?""'@"; //演算子・記号
StringBuilder sb = new StringBuilder();
State state = State.None;
for (int i = 0 ; i < code.Length ; i++) {
switch (state) {
case State.LineComment: //行コメント
if (LineTerminator.IndexOf(code[i]) >= 0)
state = State.None;
break;
case State.DelimitedComment: //範囲コメント
if (code[i] == '*' && code[i + 1] == '/') {
state = State.None;
i++;
}
break;
case State.RegularStr: //文字列リテラル
case State.Char: //文字リテラル
if (code[i] == '\\')
sb.Append(code[i++]);
else if (code[i] == (state == State.Char ? '\'' : '"'))
state = State.None;
sb.Append(code[i]);
break;
case State.VerbatimStr: //逐語文字列リテラル
if (code[i] == '"')
if (code[i + 1] != '"')
state = State.None;
else {
sb.Append('"');
i++;
}
sb.Append(code[i]);
break;
case State.None: //通常
if (code[i] == '/' && code[i + 1] == '/') {
state = State.LineComment;
} else if (code[i] == '/' && code[i + 1] == '*') {
state = State.DelimitedComment;
i++;
} else if (code[i] == '"') {
state = State.RegularStr;
sb.Append(code[i]);
} else if (code[i] == '\'') {
state = State.Char;
sb.Append(code[i]);
} else if (code[i] == '@' && code[i + 1] == '"') {
state = State.VerbatimStr;
sb.Append("@\"");
i++;
} else if (WhiteSpace.IndexOf(code[i]) >= 0) {
if (WhiteSpace.IndexOf(code[i + 1]) < 0
&& Kigou.IndexOf(code[i + 1]) < 0
&& 0 < sb.Length
&& WhiteSpace.IndexOf(sb[sb.Length - 1]) < 0
&& Kigou.IndexOf(sb[sb.Length - 1]) < 0)
sb.Append(' ');
} else
sb.Append(code[i]);
break;
}
}
return sb.ToString();
}
static void Main(string[] args)
{
try {
string input = File.ReadAllText(args[0]);
string output = Compress(input);
Console.WriteLine(output);
} catch (ApplicationException ex) {
Console.WriteLine(ex.StackTrace);
}
}
}
}
|
Postscript では、通常、コードは実行可能な圧縮配列の形で current dict に記録されるので、それを書きだす、という方向 でいいのでしょうかね.... あまり潰しが利きませんが...
1 2 3 4 5 6 7 8 9 10 11 12 13 | %!PS
% テスト用コード
/TestProc { % Hogehoge Fugafuga
1 3 roll 10 add % areare
(abc%Hoge) == == % zzz
} def
% ======== 出力
currentdict /TestProc get ==
% ======== 以下出力結果
% {1 3 roll 10 add (abc%Hoge) == ==}
|
コメント #6548 を改造して、全てのコメントを除いて空白と改行を1個にまとめるプログラムにしました。
空白は削除できる場合もあるのですが、意味が変わる場合が考えられるために1個は残してあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import java.util.regex.*;
import java.io.*;
public class Decomment2 {
static final String LITERAL = "(?:\"(?:\\\\.|[^\"])*\")|(?:\'(?:\\\\.|[^\'])*\')";
static final String COMMENT1 = "(?s:/\\*.*?\\*/)";
static final String COMMENT2 = "//.*";
static final String SPACES = "\\s+";
static final Pattern DECOM_PAT = Pattern.compile("(" + LITERAL + ")|((" +
COMMENT1 + "|" + COMMENT2 + "|" + SPACES + ")+)");
static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
for (String name : args) {
BufferedReader r = new BufferedReader(new FileReader(name));
FileWriter w = new FileWriter(name + ".out");
StringBuilder sb = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
sb.append(line).append(LINE_SEPARATOR);
}
Matcher m = DECOM_PAT.matcher(sb);
StringBuffer replace = new StringBuffer();
while (m.find()) {
if (m.group(2) != null && m.group(2).length() > 0) {
m.appendReplacement(replace, " ");
} else {
m.appendReplacement(replace, "$1");
}
}
m.appendTail(replace);
w.write(replace.toString());
w.close();
}
}
}
|
readで読んで、writeでプリティプリント属性をオフにして印字してみています。
入力ファイル:
;;; doukaku-189.data -*- lisp -*-
;; 1
(let ((x 10 )
(y 20 ))
(list x y ))
;; 2
(let ((x 10)
(y 20))
(list x y ))
~~
印字結果:
(LET ((X 10) (Y 20)) (LIST X Y))(LET ((X 10) (Y 20)) (LIST X Y))
入力ファイル:
;;; doukaku-189.data -*- lisp -*-
;; 1
(let ((x 10 )
(y 20 ))
(list x y ))
;; 2
(let ((x 10)
(y 20))
(list x y ))
~~
印字結果:
(LET ((X 10) (Y 20)) (LIST X Y))(LET ((X 10) (Y 20)) (LIST X Y))
1 2 3 | (with-open-file (str "doukaku-189.data")
(loop :for in := (read str nil nil) :while in
:do (write in :pretty nil)))
|
昔ゴルフ用に書いたものを書き直しました。Emacs のバッファを書き換えます。対象言語は Common Lisp で、バッファのモードは lisp-mode と仮定しています。
- 出力例:
- (defun mylib-compress-need-space-p()(cond((or(bobp)(eobp))nil)((string-match"["'(),`]"(string(following-char)))nil)((looking-back"#[0-9]+#")nil)((looking-back"#\\.")t)((string-match"["()]"(string(preceding-char)))nil)(t)))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | (defun mylib-compress-region (&optional start end)
(interactive "r")
(save-restriction
(when (and start end)
(narrow-to-region start end)
(goto-char (point-min)))
(loop
do (delete-region (point)
(progn (while (forward-comment 1)) (point)))
until (or (eobp) (= (following-char) ?\)))
if (mylib-compress-need-space-p)
do (insert " ")
if (looking-at "\\(#'?\\|['`]\\|,@?\\)?(")
do
(down-list 1)
(mylib-compress-region)
(up-list 1)
else do (forward-sexp 1))))
(defun mylib-compress-need-space-p ()
(cond ((or (bobp) (eobp))
nil)
((string-match "[\"'(),`]" (string (following-char)))
nil)
((looking-back "#[0-9]+#")
nil)
((looking-back "#\\\\.")
t)
((string-match "[\"()]" (string (preceding-char)))
nil)
(t)))
|




sweetie089 #6664() Rating-6/10=-0.60
[ reply ]