苦境

ちょっと前まで

  • 体調不良(風邪)
  • 台所の配水管故障
  • PC不調(ハードディスクがおかしい)

の苦境に立たされていました。


とりあえず3つともほぼ解決しました。


わたしはえらいプログラマーなので、X86のレジスタの数が10個であることやJavaプラットフォームの仕様を決めるプロセスがJCP(Java Community Process)*であることなどを知っています。あと正規表現インタープリターを自作したりできますが、ハードに弱いのでハードディスクの移行で苦労しました。

* Japan Communist Partyと一緒、と覚えよう。


実のところ、パソコンにはあまり興味がない。プログラムが好きなだけで、PC本体にはそもそも興味がない。たぶんわたしが興味を持つには、具体的すぎるのだと思う。

* 「わたしが興味を持つには具体的すぎる」って、チョムスキーのセリフのパクりなんだけど、なかなかかっこいい言いまわしだと思う。



というわけで、2年前に親にもらったDellのノートPCをずっと使っている。Windows XP Homeエディションだ。

(これを買い与えたとき、親はまさか息子がプログラマーになるとは想像もしていなかっただろう。わたしも想像もしていなかった)。


この手のトラブルの解決にあたっては、以前買った↓この本がすごい役に立つんだ。

[わかったブック 2] 根本的解決!どうして起こる?パソコンのエラー (わかったブック)


おすすめ。



以下以降手順。

  • おいおい、ハードディスクから異音がするし、読み書きが以上に遅いよ。寿命は2年ほどだそうだし、もうダメっぽいなあ。
  • 新しいのを買いたいが、何を買えばいいのか?
  • ATAってなによ。
  • しらべたところ、「Ultra ATA」で2.5インチのを買えばいいらしい。
    • ふつうノートは2.5インチだそうだ。
    • 関係ないがPCの型番で検索していたら、「うしろにもUSBポートが2つあって便利だ」との情報。改めてPCの後部を見ると、本当にある。2年間使っててそこにUSBポートがあることに気づかなかった...。
  • 回転数は速い方がいいらしいので5400。80GB以上は認識しない可能性があるようなので、80GB。というわけでようやく条件が決まる。
  • 適当にバッファローのサイト見て、条件にあったものを購入。
  • 届くあいだに死にかけのハードディスクからバックアップ。
  • 起動ドライブ以外はまるまるコピーでいいとして。
  • 起動ドライブは「再インストール」にするか「設定ごと移行」にするか。
  • たまにOSを再インストールすべきだよね?と思ったので、起動ドライブは再インストールすることにして、必要なファイルのみバックアップの方針で決まる。

もろもろのバックアップ

  • Cygwin
    • ファイルをまるまるコピーして再インスールすれば動いた。ただし以前とまったく同じドライブの同じディレクトリに置くこと。
  • Colinux
    • ディスクイメージをコピーするだけ。ただし再インストールは必要(Tapを入れなおさないといけないし)。
    • 上の本にあったアドバイス通り、スクリーンショットをとってネットワークの設定を記録しておいたら役に立った。
  • Meadow
    • 起動ドライブ以外にあったし、.emacs と sitelisp を新ディスクに移行して同じ場所に再インストールするだけ。
  • Opera
    • user_jsとかツールバーの設定とかその他全部をコピー。
    • 実はOperaの設定を移行しそこねていて、古いハードディスクを入れなおしてバックアップをとりなおすはめになった。
  • Firefox
    • "C:\Documents and Settings\<ユーザー名>\Application Data\Mozilla\Firefox" をコピー。
  • 秀丸
    • いつのまにか設定が移行できるようになってる。「その他 > 設定内容の保存/復元」で設定をバックアップ。あと、マクロとかのファイルごと新ディスクに移行して再インストール。しかる後に設定内容を読みこみ。
  • 環境変数とか
    • レジストリエディタ(ファイル名を指定して実行 > regedit)で「HKEY_CURRENT_USER\Environment」などをエクスポートしてあとでインポート。
  • itunes
    • メニューの「詳細:から「ライブラリを統合」を実行し、ライブラリの中身を「iTunes Music」フォルダにまとめる。「iTunes Music」の中身をバックアップして再インストール。本当は、古いディスクの方で、いったんitune storeの契約を解除してから移行した方がいいが、忘れてた。5回までコピーできるらしいが、契約解除を忘れたせいで一機失なってしまった。



正規表現をつくった

JavaScriptで正規表現をつくった。むろんJSネイティブのものより、表現力が低く、パフォーマンスもおとる。

純然たる車輪の再発明がしたかったのでやった。


↓あと一応、この本で勉強したので卒業試験のつもり。

オートマトン・言語理論 (基礎情報工学シリーズ)

富田 悦次 (著), 横森 貴 (著)

森北出版、1992


ちなみにボトムアップパーサで構文解析し、NFA(非決定性有限オートマトン)で実装している。

Wikipediaで調べながら構文解析表を手でつくったのが一番大変だった。

(judeでグラフの絵を描いて、エクセルで表をつくった)。


特徴

  • "^"とか"$"とか"[]"みたいなイカした表記はない。連接とスターとORのみ。
  • 演算子の優先順位がいまいちなので、"aa|b"のような書き方はできない。"(aa)|b"と書かないとダメ。
  • マッチ結果をとってくるような気のきいた機能はない。マッチしたらtrueを返すだけ。

使い方

var r = new Regex("(ab)|c");
r.test("ab")
//=> true
/* parser.js */
Object.extend = function(des,or){
    for(var i in or){
        des[i] = or[i];
    }
    return des;
};
var Class = function(_opt,_proto){
    var opt = _opt || {};
    var proto = _proto || {};
    var klass = function(){
        this.constructor = klass;
        this.initialize.apply(this,arguments);
    };
    Object.extend(klass,opt);
    Object.extend(klass.prototype,proto);
    if(!klass.prototype.initialize)
    klass.prototype.initialize = function(){};
    return klass;
};

var Parser = new Class();
Object.extend(Parser,{
    'NS':['reg','cls','con','uni','cel'],
    'isNS': function(s){
        for(var i=0,l=this.NS.length;i<l;++i){
            if(this.NS[i]==s)
                return true;
        }
        return false;
    },
    'GRAMMER':{
        '0':['S','reg'],
        '1':['reg','cls'],
        '2':['reg','con'],
        '3':['reg','uni'],
        '4':['reg','cel'],
        '5':['cls','cel','*'],
        '6':['con','cel','cel'],
        '7':['con','cel','con'],
        '8':['uni','cel','|','cel'],
        '9':['cel','(','reg',')'],
        '10':['cel','ch'],
        '11':['cel','ep']
    },
    'ACTION_TABLE': [
        {/*state0*/
            'ep':["shift",1],
            'ch':["shift",2],
            '(':["shift",3]
        },
        {/*state1*/
            'ep':["reduce",11],
            'ch':["reduce",11],
            '*':["reduce",11],
            '|':["reduce",11],
            '(':["reduce",11],
            ')':["reduce",11],
            '$':["reduce",11]
        },
        {/*state2*/
            'ep':["reduce",10],
            'ch':["reduce",10],
            '*':["reduce",10],
            '|':["reduce",10],
            '(':["reduce",10],
            ')':["reduce",10],
            '$':["reduce",10]
        },
        {/*state3*/
            'ep':["shift",1],
            'ch':["shift",2],
            '(':["shift",3]
        },
        {/*state4*/
            'ep':["shift",1],
            'ch':["shift",2],
            '*':["shift",9],
            '|':["shift",10],
            '(':["shift",3],
            ')':["reduce",4],
            '$':["reduce",4]
        },
        {/*state5*/
            'ep':["reduce",3],
            'ch':["reduce",3],
            '*':["reduce",3],
            '|':["reduce",3],
            '(':["reduce",3],
            ')':["reduce",3],
            '$':["reduce",3]
        },
        {/*state6*/
            'ep':["reduce",2],
            'ch':["reduce",2],
            '*':["reduce",2],
            '|':["reduce",2],
            '(':["reduce",2],
            ')':["reduce",2],
            '$':["reduce",2]
        },
        {/*state7*/
            'ep':["reduce",1],
            'ch':["reduce",1],
            '*':["reduce",1],
            '|':["reduce",1],
            '(':["reduce",1],
            ')':["reduce",1],
            '$':["reduce",1]
        },
        {/*state8*/
            '$':["acc"]
        },
        {/*state9*/
            'ep':["reduce",5],
            'ch':["reduce",5],
            '*':["reduce",5],
            '|':["reduce",5],
            '(':["reduce",5],
            ')':["reduce",5],
            '$':["reduce",5]
        },
        {/*state10*/
            'ep':["shift",1],
            'ch':["shift",2],
            '(':["shift",3]
        },
        {/*state11*/
            'ep':["shift",1],
            'ch':["shift",2],
            '(':["shift",3],
            ')':["reduce",6],
            '$':["reduce",6]
        },
        {/*state12*/
            'ep':["reduce",7],
            'ch':["reduce",7],
            '*':["reduce",7],
            '|':["reduce",7],
            '(':["reduce",7],
            ')':["reduce",7],
            '$':["reduce",7]
        },
        {/*state13*/
            'ep':["reduce",8],
            'ch':["reduce",8],
            '*':["reduce",8],
            '|':["reduce",8],
            '(':["reduce",8],
            ')':["reduce",8],
            '$':["reduce",8]
        },
        {/*state14*/
            ')':["shift",15]
        },
        {/*state15*/
            'ep':["reduce",9],
            'ch':["reduce",9],
            '*':["reduce",9],
            '|':["reduce",9],
            '(':["reduce",9],
            ')':["reduce",9],
            '$':["reduce",9]
        }
    ],
    'GOTO_TABLE':[
        {/*state0*/
            'reg':8,
            'cls':7,
            'con':6,
            'uni':5,
            'cel':4
        },
        {/*state1*/
        },
        {/*state2*/
        },
        {/*state3*/
            'reg':14,
            'cls':7,
            'con':6,
            'uni':5,
            'cel':4
        },
        {/*state4*/
            'con':12,
            'cel':11
        },
        {/*state5*/
        },
        {/*state6*/
        },
        {/*state7*/
        },
        {/*state8*/
        },
        {/*state9*/
        },
        {/*state10*/
            'cel':13
        },
        {/*state11*/
            'con':12,
            'cel':11
        },
        {/*state12*/
        },
        {/*state13*/
        },
        {
        },
        {
        }
    ]
});
var Result = new Class();
Object.extend(Result.prototype,{
    'initialize':function(rule,tree){
        this.rules = rule;
        this.tree = tree;
    }
});

Object.extend(Parser.prototype,{
    'initialize':function(){},
    'parse':function(str){
         return this.proc(str,[0],[]);
    },
    'read':function(str){
        if(typeof arguments.callee.s == "undefined")
            arguments.callee.s = 0;
        if(arguments.callee.s==0 && str=="")
            return ["ep","",""];
        else if(arguments.callee.s==0)
            arguments.callee.s = 1;
        
        if(str=="")
            return ["$","",""];
        var chr;
        if(str.charAt(0)=="¥¥"){
            chr = str.substr(0,2);
            str = str.slice(2);
        }
        else{
            chr = str.charAt(0);
            str = str.slice(1);
        }

        if(Parser.isNS(chr))
            return [chr,str,chr];
        switch(chr){
        case '*':
        case '|':
        case '(':
        case ')':
            return [chr,str,chr];
        default:
            return ["ch",str,chr];
        }
    },
    'makeTree':function(stk,grm,raw){
        var p = [ ];
        
        for(var i=grm.length-1;i>0;--i){
            if(Parser.isNS(grm[i])){
                p.unshift( stk.pop() );
            }
            else{
                if(grm[i]=="ch")
                    p.unshift(raw);
                else
                    p.unshift(grm[i]);
            }
        }
        p.unshift(grm[0]);
        stk.push(p);
    },
    'proc':function(str,stack,output){
        var state;
        var action;
        var stk = [];
        
        var res = this.read(str);
        var input = res[0]; var lastch;
        str = res[1];
        var raw = res[2];
        
        while(true){
            state = stack[stack.length-1];
            action = Parser.ACTION_TABLE[state][input];
            //console.log("input:"+raw);
            //console.log(action);
            if(!action)
                throw new Error("invalid input");
            else if(action[0]=="shift"){
                res = this.read(str);
                lastch = raw;
                input = res[0]; str = res[1]; raw=res[2];
                stack.push(action[1]);
                continue;
            }
            else if(action[0]=="reduce"){
                var g = Parser.GRAMMER[action[1]];
                this.makeTree(stk,g,lastch);
                //console.log(stk,action[1]);
                output.push(action[1]);
                for(var i=0,l=g.length-1;i<l;++i)
                    stack.pop();
                state = stack[stack.length-1];
                var go = Parser.GOTO_TABLE[state][g[0]];
                stack.push(go);
                continue;
            }
            else if(action[0]=="acc"){
                return new Result(output,stk[0]);
            }
        }
        return null;
    }
});



/* regex.js */
var Automaton = new Class({},
    {
        'initialize': function(){
            this.state = 0;
            this.rules = [];
        },
        'set': function(rules,lastState){
            this.rules = rules;
            this.lastState = lastState;
        },
        'read': function(str){
            if(str.charAt(0)=='¥¥'){
                return [str.substr(0,2),str.slice(2)];
            }
            else
                return [str.substr(0,1),str.slice(1)];
        },
        'test': function(str){
            return this.proc(0,str);
        },
        'proc': function(state,str){
            if(str=="" && state==this.lastState)
                return true;
            
            var res = this.read(str);
            var rules = this.rules;
            var path = [];
            var rule;
            var p;
            for(var i=0,l=rules.length;i<l;++i){
                rule = rules[i];
                if(rule[0]==state && ( rule[1]=="ep" || rule[1]==res[0]))
                    path.push(rule);
            } 
            var test = false;
            while(!test && path.length>0){
                p = path.shift();
                if(p[1]=="ep")
                    test = this.proc(p[2],str);
                else
                    test = this.proc(p[2],res[1]);
                if(test)
                    return test;
            }
            return false;
        }
    }
);

var Regex = new Class({

    },
    {
        'initialize':function(str){
            var p = new Parser();
            this.res = p.parse(str);
            this.automaton = new Automaton();
            var r = this.interpret(0,this.res.tree);
            this.automaton.set(r.rules,r.end);
        },
        'test': function(str){
            return this.automaton.proc(0,str);
        },
        'interpret': function(start,parseTree){
            var self = arguments.callee;
            var res,res2;
            var newS,newS2;
            var rules = [];
            
            switch(parseTree[0]){
            case 'cls':
                res = self(start+1,parseTree[1]);
                rules.push([start,"ep",start+1]);
                rules = rules.concat(res.rules);
                rules.push([res.end,"ep",start]);
                return {
                    'end':start, 'size':res.size+1,
                    'rules': rules
                };
            case 'con':
                res = self(start+1,parseTree[1]);
                res2 = self(res.end+1,parseTree[2]);
                rules.push([start,"ep",start+1]);
                rules = rules.concat(res.rules);
                rules.push([res.end,"ep",res.end+1]);
                rules = rules.concat(res2.rules);
                rules.push([res2.end,"ep",res2.end+1]);
                return {
                    'end': res2.end+1, 'size':res.size+res2.size+2,
                    'rules': rules 
                };                
            case 'uni':
                res = self(start+1,parseTree[1]);
                newS = start + res.size;
                res2 = self(newS,parseTree[3]);
                newS2 = newS + res2.size;

                rules.push([start,"ep",start+1],[start,"ep",newS]);
                rules = rules.concat(res.rules);
                rules.push([res.end,"ep",newS2]);
                rules = rules.concat(res2.rules);
                rules.push([res2.end,"ep",newS2]);
                return {
                    'end': newS2, 'size': res.size+res2.size+2,
                    'rules': rules 
                };
            case 'cel':
                if(parseTree.length==2){
                    rules.push([start,parseTree[1],start+1]);
                    return {
                        'end':start+1,'size':2,'rules':rules
                    };
                }
                else
                    return self(start,parseTree[2]);
            default:
                return self(start,parseTree[1]);
            }
            return null;
        }
    }
);

コメントする

トラックバック(0)

このブログ記事を参照しているブログ一覧: 雑記2008年7月6日(日)

このブログ記事に対するトラックバックURL: http://www.at-akada.org/mt/mt-tb.cgi/932

著者について

赤田敦

nightly[at]at-akada.org

紹介: about

ホーム: at-akada.org

-> 携帯電話用

なかなか更新されないときは...

-> 赤田ブログ生成器

2009年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