有限オートマトンを利用した字句解析。
文字列に対してそれが実数であるか整数であるかを判別し、その結果を返す。
// オートマトンによる字句解析
#module AUTO_MATON
/*
STATE_FIRST : 初期状態。 0~9でSTATE_INPUT_INTEGERへ、+-でSTATE_SIGNへ。
STATE_SIGN : 符号解析後。 0~9でSTATE_INPUT_INTEGERへ。
STATE_INPUT_INTEGER : 整数部入力状態。 0~9でSTATE_INPUT_INTEGERへ、.でSTATE_INPUT_FLOATへ。
STATE_INPUT_FLOAT : 小数点以下入力状態。0~9でSTATE_INPUT_FLOATへ。
*/
#enum STATE_ERROR = 0
#enum STATE_FIRST
#enum STATE_SIGN
#enum STATE_INPUT_INTEGER
#enum STATE_INPUT_FLOAT
#enum global IS_ERROR = 0
#enum global IS_INTEGER
#enum global IS_FLOAT
// モジュール初期化用命令
#deffunc init
// 受理集合に属する状態を定義
dim canAccept, STATE_INPUT_FLOAT + 1
canAccept(STATE_INPUT_INTEGER) = IS_INTEGER
canAccept(STATE_INPUT_FLOAT) = IS_FLOAT
return
// 文字列が数値か否かを判別する関数
#defcfunc isDigit@AUTO_MATON str sArg, local tmp
tmp = sArg : tmp = peek(tmp, 0)
return ('0' <= tmp) & (tmp <= '9')
// 次の状態を返す関数
#defcfunc nextState@AUTO_MATON int nowState, str sArg, local result
result = STATE_ERROR
switch nowState
case STATE_FIRST
if (sArg == "+") | (sArg == "-") : result = STATE_SIGN
case STATE_SIGN
if isDigit(sArg) : result = STATE_INPUT_INTEGER
swbreak
case STATE_INPUT_INTEGER
if isDigit(sArg) : result = STATE_INPUT_INTEGER
if sArg = "." : result = STATE_INPUT_FLOAT
swbreak
case STATE_INPUT_FLOAT
if isDigit(sArg) : result = STATE_INPUT_FLOAT
swbreak
default
// エラー
swbreak
swend
return result
// 受理される文字列か否か判定する命令
#defcfunc judge str sArg, local state, local tmp
state = STATE_FIRST : tmp = sArg
repeat strlen(sArg)
state = nextState(state, strmid(tmp, cnt, 1))
if state == STATE_ERROR : break
loop
return canAccept(state)
#global
init
// モジュールここまで
// 以下サンプルコード
sQuestion = "+123", "456", "-3.14", "1e-03", "10.", "I may be refused."
repeat length(sQuestion)
switch judge(sQuestion(cnt))
case IS_INTEGER
mes sQuestion(cnt) + "は整数として受理されます。"
swbreak
case IS_FLOAT
mes sQuestion(cnt) + "は実数として受理されます。"
swbreak
default
mes sQuestion(cnt) + "は受理されませんでした。"
swbreak
swend
loop
stop
0 件のコメント:
コメントを投稿