ステップ 4 : 式と実行制御の関連の処理
元のプログラムはシリーズ(5)の最後に掲載した eltaso2.lua。
式を分解する
整数の四則演算について、TeX には単純な + - * /
は無くて、(C言語の)複合代入 += -= *= /=
に相当する機能だけが用意されている。(Lua には複合代入文がない(a += b
は単純に a = a + b
と書く)ので、この節では C言語風の記述を用いる。)だから全ての整数の式を
〈変数1〉〈= += -= *= /= の何れか〉〈- か空か〉〈変数2/定数〉
のみを用いた形(右辺に単項マイナスが使えることに注意)に分解する必要がある。幾つか例を示す。
a = b + c ↓ a = b; a += c
s = (a + b) * h / 2 ↓ s = a; s += b; s *= h; s /= 2
nq = x * x + y * y ↓ (変数 t を導入する) nq = x; nq *= x; t = y; t *= y; nq += t
u = nz - u * u ↓ u *= -u; u += nz
なお、四則演算以外の演算は直接にはサポートされないので、そういう演算がある場合は、ステップ 2 の段階で関数にして分離しておく必要がある。(eltaso1.lua の remainder()
関数のように。)
文字列の式に関しては、連接演算についてはそのままの形で構わない。(\edef
で多数の項を一度に連接することが可能だから。)それ以外の演算は直接にはサポートされないのでやはり分離する必要がある。ただし文字列の演算は初級者には難しいので何らかの既存のパッケージを導入した方がよいかも知れない。
以上で式の分解の話を終えるが、実のところ、eltaso2.lua には分解すべき式が存在しない。だからここでは何もすることがない。
for 文等を while 文に置き換える
今回の TeX(on LaTeX)への変換作業においては、ループ構文を全て \@whilenum
で表すことにする。従って、while 文以外のループ構文を全て while に置き換えておく。(for-each 構文はそのまま残す。)例えば、eltaso1.lua には以下のような for 文があるが、
for j = 1, max do eltaso_name(j) print(sres) end
これを次のような while 文に置き換えよう。((最も素直に書くと、「j = 1; while j <= max do ... ; j = j + 1; end
」となるはずだが、TeX では「<=」が扱い難いので、敢えてこの形にしている。))
j = 0 while j < max do j = j + 1 eltaso_name(j) print(sres) end
変換後のプログラム
-- [変数一覧] -- 整数: max, j, ires(戻り値) -- 文字列: dm, dc, dx, di, km, kc, kx, sres(戻り値) -- 配列: alpha_name, digit alpha_name = { [0] = "ぜっと", "えー", "びー", "しー", "でー", "いー", "えふ", "じー", "えいち", "あい", "じぇー", "けー", "える", "えむ", "えぬ", "おー", "ぴー", "きゅー", "あーる", "えす", "てぃー", "ゆー", "ぶい", "だぶりゅー", "えっくす", "わい" } digit = { [0] = "", "一", "二", "三", "四", "五", "六", "七", "八", "九" } function knumeral(_1) split_digit(_1) knum_pos(dm, "千"); km = sres knum_pos(dc, "百"); kc = sres knum_pos(dx, "十"); kx = sres sres = km .. kc .. kx .. digit[tonumber(di)] end function split_digit(_1) -- TeXでは再実装が必要 dm, dc, dx, di = -- 直接に目的の変数に値を返す ("%04d"):format(_1):match("^(.)(.)(.)(.)$") end function knum_pos(_1, _2) if tonumber(_1) == 0 then sres = "" elseif tonumber(_1) == 1 then sres = _2 else sres = digit[tonumber(_1)] .. _2 end end function eltaso_name(_1) knumeral(_1) -- sres に返る remainder(_1, 26) -- ires に返る sres = sres .. "反田" .. alpha_name[ires] end function remainder(_1, _2) -- TeXでは再実装が必要 ires = _1 % _2 end function eltaso(_1) max = _1 if max > 9999 then max = 9999 end j = 0 while j < max do j = j + 1 eltaso_name(j) print(sres) end end eltaso(1000)