導入
最近、Rustを使うことが多くなってきました。ので、今更ながらに勉強をはじめました。
Rustで実際に開発をした感想
コンパイルが通ればそれなりに動く、というのは素敵だなぁ、と思います。その他はとりたてて感想はありません。
ところで、電卓っていうと
Rustで電卓を書くというと、やはりナウなヤングは、パーサコンビネータで文法を書いてバカうけ、という感じなのでしょうか?
ところで、電卓っていうと
残念ながら私はそんなことはできないので、古風なアプローチをしようと思います。
hocというコマンドを知っていますか?
「UNIXプログラミング環境」という本に出てくる、結構高性能な電卓です。
hocというコマンドを知っていますか?
「UNIXプログラミング環境」という本の中では、5回に渡って機能を追加してく作業が描かれています。
hocというコマンドを知っていますか?
全く関係ないのですが、Plan9では標準コマンドで、man 1 hocにきちんと記されています。
hocというコマンドを知っていますか?
これをRustで5回に分けて作ってみようと思います。
hocというコマンドを知っていますか?
5回分のネタをゲットしたぜ!
hocというコマンドを知っていますか?
前述の本の中では、yaccで文法が書かれているのですが、Rustでこれが書けないかなぁ、と、Rustでyaccを使う方法をググってみました。
grmtoolsというのがあるのですね
クイックスタートガイドもあって最高じゃないですか!
とりあえずコピペして動かしてみました
デモ
「UNIXプログラミング環境」での第一回の文法は下記の通り(以下引用です)
$ cat hoc.y
%{
#define YYSTYPE double /* data type of yacc stack */
}
%token NUMBER
%left '+' '-' /* left associative, same precadence */
%left '*' '/' /* left assoc., higher precedence */
%%
list: /* nothing */
| list '\n'
| list expr '\n' { printf("\t%.8g\n", $2); }
;
expr: NUMBER { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
;
$$
grmtoolsとQuickstart Guideにある文法は下記の通り
%start Expr
%%
Expr -> Result<u64, ()>:
Expr '+' Term { Ok($1? + $3?) }
| Term { $1 }
;
Term -> Result<u64, ()>:
Term '*' Factor { Ok($1? * $3?) }
| Factor { $1 }
;
Factor -> Result<u64, ()>:
'(' Expr ')' { $2 }
| 'INT'
{
let v = $1.map_err(|_| ())?;
parse_int($lexer.span_str(v.span()))
}
;
%%
これに、「UNIXプログラミング環境」のhocの解説の第1回と同様、MINUSを付け加えた
デモ
参考文献
- UNIXプログラミング環境 B. Kernighan, R. Pike, (訳 石田晴久)
- grmtoolsドキュメント https://softdevteam.github.io/grmtools/master/book/index.html
とりあげたソースコード
https://www.snthtns.jp/gitea/hhh/pseudo_hoc (←自宅サーバなので、いつまであるか分からないです)
ご清聴
ありがとうございました。