オートマトン

オートマトンがじつはよくわかってないので、いろいろ見てみてます。
自動人形であるとか言う話は置いといて、実装しようとするとなかなか。。。


情けない。
逆にいえば、はっきりオートマトンが分かれば、何かと都合がいいと
思っています。


受理したときはいいとして、受理しなかったときのエラーメッセージを
どうすればいい感じに出せるのかなぁとか思ってみてるのだけど、
よくわかりましぇん。


生け垣オートマトンとかが、自分が考えてる言語にはあってるような
気がするのだけども、これまた難解というかなんというか、、、。
わかってるような、わかってないような、微妙な感じです。
頭悪いなぁ。


以下とりあえず、HSPのプログラムをjavascriptに移植してみたのソースです。
http://rpen.blogspot.com/2007/06/blog-post_30.html
字句解析するものですねぇ。
これのエラー状態が今1つしかないけども、きちんとエラーを出すには
複数のエラー状態が必要でしょう。
そして、エラーからの復帰も必要となるかもしれないです。
そのとき、どうしたらよいのでしょうか???
うーん。いろいろ、分からんこと多しなので、勉強してみまーす。

<script>
// オートマトンによる字句解析
var STATE_ERROR = 0;
var STATE_FIRST = 1;			// 初期状態。          0〜9でSTATE_INPUT_INTEGERへ、+-でSTATE_SIGNへ。
var STATE_SIGN = 2;				// 符号解析後。        0〜9でSTATE_INPUT_INTEGERへ。
var STATE_INPUT_INTEGER = 3;	// 整数部入力状態。    0〜9でSTATE_INPUT_INTEGERへ、.でSTATE_INPUT_FLOATへ。
var STATE_INPUT_FLOAT = 4;		// 小数点以下入力状態。0〜9でSTATE_INPUT_FLOATへ。

var IS_ERROR = 0;
var IS_INTEGER = 1;
var IS_FLOAT = 2;
var canAccept = new Array(STATE_INPUT_FLOAT + 1);
// モジュール初期化用命令
function init() {
    // 受理集合に属する状態を定義
    canAccept[STATE_INPUT_INTEGER] = IS_INTEGER;
    canAccept[STATE_INPUT_FLOAT]   = IS_FLOAT;
}

// 文字列が数値か否かを判別する関数
function isDigit(sArg) {
	var tmp = sArg.charAt(0);
	return ('0' <= tmp) & (tmp <= '9');
}

// 次の状態を返す関数
function nextState(nowState, sArg) {
	switch (nowState) {
	case STATE_FIRST:
		if ((sArg == "+") | (sArg == "-")) return STATE_SIGN;
	case STATE_SIGN:
		if (isDigit(sArg)) return STATE_INPUT_INTEGER;
		break;
	case STATE_INPUT_INTEGER:
		if (isDigit(sArg)) return STATE_INPUT_INTEGER;
		if (sArg == ".")   return STATE_INPUT_FLOAT;
		break;
	case STATE_INPUT_FLOAT:
		if (isDigit(sArg)) return STATE_INPUT_FLOAT;
		break;
	default:
		break;
	}
	return STATE_ERROR;
}

// 受理される文字列か否か判定する命令
function judge(sArg) {
	var state = STATE_FIRST;
	var tmp = sArg;
	for (var cnt = 0; cnt < sArg.length; cnt++) {
		state = nextState(state, tmp.charAt(cnt));
		if (state == STATE_ERROR) break;
	}
	return canAccept[state];
}
init();

// モジュールここまで

// 以下サンプルコード
var sQuestion = ["+123", "456", "-3.14", "1e-03", "10.", "I may be refused."];
for (var cnt = 0; cnt < sQuestion.length; cnt++) {
	switch (judge(sQuestion[cnt])) {
	case IS_INTEGER:
		p( sQuestion[cnt] + "は整数として受理されます。");
		break;
	case IS_FLOAT:
		p(sQuestion[cnt] + "は実数として受理されます。");
		break;
	default:
		p(sQuestion[cnt] + "は受理されませんでした。");
		break;
	}
}
function p(str) {
	document.write(str+"<br>");
}
</script>