6 初歩的な電卓(1)
計算順序
123 + 456 * 789
を とりあえず順々に計算する
(演算の優先順位はとりあえず考えない)
「計算」について(補足解説)
プログラミングの目的
- プログラミング言語について考えることが主題である当科目で、
こうして電卓を扱うのは、プログラミングという営みの
(ひいては、コンピュータという機械の元来の)目的が
「計算」にあった(右図)ことに関係している。
- プログラミング言語の古い歴史について触れたついでに、
こうした人工的に作られた言語に対して、我々が
日常使う(人と人とが意思疎通するための)言語を
「自然言語」と呼ぶことも知っておこう。
- 一般的な電卓では、式を入力して最後に「=」を叩くことで、
「結果を表示せよ」という指示を与えている。
- これに対して、今回作る電卓では、「=」を使わず、
式を入力して「Enter」を叩くことで結果を表示させる
(行単位の入力を行うと自動的にこういう仕組みになるため)
- なお、「=」という記号の意味は、小学校の算数の問題では
上図と同じ(「結果を書きなさい」)意味だったが、

数学では「両辺が等しい」という言明、
プログラミングでは「代入せよ」という指示、
というように場面によって違ったものになっている。
優先度について
演算子の優先度を考えるかどうかで答5えは違ったものになる。ちなみに、

- 市販の電卓(高価でないもの、例えば百均の商品)では、優先度を考慮しない(右図上)。
- Windowsのアクセサリとして入っている「電卓」では、
- 普通の電卓(図左)では優先度を考慮せず、
- 関数電卓(図右)、プログラマ電卓では考慮する(右図下)。

- irbに数式を入れると(一般のプログラミング言語と同様に)
優先度を考慮した演算を行う。

手順
1 トークンへの分解 |
字句解析 スキャン or Lexical Analyzing, |
2 構文解析 |
Parsing |
3 インストラクション実行 |
Execution |

6.1 プログラムの大枠
Read-eval-print loop(右図) 
1 トークンへの分解
日本語文
- 日本語文(上図;中国語なども同じ)は分かち書きが行われないので、単語に分解して理解する必要がある。
- 英語などの欧文は単語に分けて書かれる。(それぞれがトークンに相当する)

トークン
→ 結果は配列にして保持する(というプログラムの作り方が一般的)
方法として3通り
a 予め入力者が空白で区切っておいて、
splitメソッドで分ける
"123 + 456 * 789".split
# 入力する人が結構大変になるだろうな
digit
b ruby の機能を活用する
/(\d+).*/ # 例えば数値はこういう正規表現で
- rubyの正規表現では
\d
は [0-9]
と同じ
- d は digit の d

c 1文字ずつ見ていく
- このやりかたで処理をするプログラム(プログラム生成プログラム)として
lex という有名なものがある。

比較的 シンプルな(でも実用的な) スキャナー
- 前回の正規表現活用では、文字列の中でパターン(正規表現)にマッチするものを1つ見つけるために、
index
や =~
というメソッドを使った。
- 今回は、String#scan を使ってマッチをすべて見つける。
- 以下のようなプログラムを試してみて下さい。

while gets do
p $_.scan(%r!\d+|[-+/*%]!)
end
ここで使われている、
- ‘|’(たて棒)は、正規表現の中で、~ または ~ を示し、
- その左側は 整数にマッチするパターン
- その右側は 演算子にマッチするパターン
*
や +
は、正規表現の中では、量指定子といわれる特殊文字だが、
- 文字クラスの中では普通の文字として扱われる。逆に、
- ‘-’ (演算子マイナス)は、文字クラスの中では特殊な役割を持ち、
[a-z]
のような使い方で文字の範囲を表す。
- ‘-’ が特殊な意味だと解釈されないようにするためには、 ブラケット[]
の中で、最初か最後に置く。

- ‘/’
(割り算の演算子スラッシュ)は、正規表現そのものを囲む標準的文字なので、
バックスラッシュ
'\'
を前置するか、%r記法を用いる。
- なお、バックスラッシュ文字 ‘\’ は、日本では
’¥’と表示されることが多い(この資料でも混在している)。
- (日本でよくある)キーボードでは、右図の位置に’\’ と ‘¥’
があるが、内部では同じ文字コード。
- 正規表現で使われる前述の記号
|
は、
(ご存知の方は多いだろうが)C、Java、Rubyといったプログラミング言語や、シェル言語でも、2つ並べて「または」の意味の
演算子(あるいは制御構造)として使われてきている文字(右図)
解説(別頁
図が見にくいが)も参照されたし。
実際に 作って実行してみる
この先は(前に説明したように)エディタでプログラムを入力編集し、
それを実行する。
ソースファイル名は 適当でいいが
- 拡張子は .rb
- 意味のある名前が望ましい calc1.rb など
- 保存する場所にもご注意を
手順 a
RxPL
外側ループ
while gets do
# この中身をこれから作る
# ただし、一番外側のループは今後は省略して示していく
end
- この形のループは、1つの処理(ループの中身)が終わると次の入力行が
打鍵されるのを待ってブロックされた状態になり、
限りなくデータ入力を受付けるため、勝手には終了しない。
- プログラムに入力終了を伝える方法(右図)を知っておく必要がある。

- Windowsの場合、行頭で Ctrl-Z(Ctrlを押しながら Zを打鍵)のあと
Enterを押す。
- (停められなくなったら
コマンドプロンプトそのものを右上赤×ボタンで閉じてもかまわないが)
走査
スキャン
構文解析 (この2つは今日は省略する。
代わりに、ループの中身として、
puts $_ # 入力したものをそのまま出力
または、
p $_.scan(%r!\d+|[-+/*%]!)
# 前述の簡易スキャナーの結果を出力
を入れて動作させてみること。