自作言語を作り始めた話
久々のブログ更新でこの1年何もやってなかったことが露呈してしまう。
今回は何を血迷ったか急にプログラミング言語が作りたくなったので、作ってみることにしました。
プログラミング言語 Sobaの開発
とりあえず、四則演算とかできるところまでは作ってみようというわけで、やってみました。
実際に実装した機能は、
- 四則演算
- 変数代入, 参照
- if文
大したものはやってないです。
概要
今回つかったツールは以下のようになります。
Bisonは構文解析を行うパーサーを生成するツールで、yaccの上位互換となっています。
Flexは字句解析器とよばれ、文字列の変換抽出を行います。
実際に、Flexでプログラム中のキーワード(if, for, 演算子、数字など)を抽出し、それをBisonに渡して、Bisonはキーワードの組み合わせを解析し、その組み合わせごとに決められた処理を行わせます。
実装
実際に私が書いたコードは以下の2つのみです。
- soba.l: 字句解析を行ってキーワードをbisonに渡します。
- soba.y: パーサーを生成し、パターンごとの処理をさせます。
src/soba.l
%{ #include <stdio.h> #include <string.h> #include "soba.tab.h" int yywrap(void) { return 1; } %} %% "udon" { fprintf(stderr, "Syntax Error: %s\n", yytext); exit(1); } [+\-*/%=<>:;] { return yytext[0]; } "\n" return LF; "if" return IF; "for" return FOR; "in" return IN; "print" return PRINT; "println" return PRINTLN; [ \t]+ {} \".*\" { yytext[strlen(yytext)-1] = '\0'; yylval.string = strdup(&yytext[1]); printf("%s\n", yylval.string); return STR; } [1-9][0-9]\.\.[1-9][0-9] { yylval.string = strdup(yytext); return RANGE; } [1-9]?[0-9]* { int temp; // 入力から実数を取得 sscanf(yytext, "%d", &temp); yylval.int_value = temp; return INTEGER; } [0-9]*\.[0-9]* { double temp; sscanf(yytext, "%lf", &temp); yylval.double_value = temp; return FLOAT; } [a-zA-Z_]+ { yylval.string = strdup(yytext); return(VAR); } . { fprintf(stderr, "Syntax Error: %s\n", yytext); exit(1); } %%
src/soba.y
%{ #include <stdio.h> #include <stdlib.h> #include <string.h> #define YYDEBUG 1 #define VARSIZE 255 typedef struct { char *name; double value; } variable; int var_used = 0; variable var[VARSIZE]; double get_value(char *name); int substitution(char *name, double value); %} %union { int int_value; double double_value; char *string; } %token <int_value> INTEGER %token <double_value> FLOAT %token <string> VAR STR RANGE %token LF IF PRINT PRINTLN FOR IN %type <int_value> block expr number if_stmt %type <string> string %start program %left '+' '-' %left '*' '/' '%' %% program : | PRINT block LF { printf("%d", $2); } | PRINTLN block LF { printf("%d\n", $2); } | PRINT string LF { printf("%s", $2); } | PRINTLN string LF { printf("%s\n", $2); } | program PRINT block LF { printf("%f", $3); } | program PRINTLN block LF { printf("%d\n", $3); } | program PRINT string LF { printf("%s", $3); } | program PRINTLN string LF { printf("%s\n", $3); } | program block LF { printf("--> %d\n", $2);} | string LF { printf("--> %s\n", $1); } | block LF { printf("--> %d\n", $1);} ; string : STR { $$ = $1; } ; block : expr { $$ = $1; } | VAR '=' expr { substitution($1, $3); $$ = $3; } | if_stmt { $$ = $1; } ; if_stmt : IF expr ':' block { if ( $2 != 0 ) $$ = $4; else $$ = 0; } | block IF block { if ( $3 != 0 ) $$ = $3; else $$ = 0; } ; expr : number { $$ = $1; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '%' expr { $$ = $1 % $3; } ; number : INTEGER { $$ = (double)$1; } | FLOAT { $$ = $1; } | VAR { $$ = get_value($1); } ; %% int search_variable(char *name) { for ( int i = 0; i < var_used; i++ ) { if ( !strcmp(var[i].name, name) ) { return i; } } return -1; } int substitution(char *name, double value) { int i = search_variable(name); if ( i == -1 ) { var[var_used].name = strdup(name); var[var_used].value = value; var_used++; } else { var[i].value = value; } return 0; } double get_value(char *name) { int i = search_variable(name); if ( i != -1 ) { return var[i].value; } printf("%s is not definded\n", name); return 0; } int yyerror(char const *str) { extern char *yytext; fprintf(stderr, "Syntax Error: %s\n", yytext); return 0; } int main(int argc, char* argv[]) { extern int yyparse(void); extern FILE *yyin; if ( argc < 2 ) { yyin = stdin; } else { yyin = fopen(argv[1], "r"); } do { if (yyparse()) { fprintf(stderr, "Error Occured!\n"); exit(1); } } while(!feof(yyin)); }
実行結果
…電卓っすね。
今後の実装予定(言い訳フェイズ)
実装力の限界ッ!
文字列とfor文を今せっせと書いてるところです。
早いとこFizzBuzzできるようになりたいなあ。
今回内容が薄いのは今後に期待という感じでよろしくお願いします。
一応ここに、置いときますね。
https://github.com/guni973/soba
B3になったときのコンパイラの授業が楽しみでならない。
今後も機能追加、改善していくつもりなので、よろしくです。
参考リンク
1年の振り返りと言いますか
技術とはあまり関係ない自分の思ったことや今年1年の振り返りでもしようかと。 実際ポエムに近い。
まあ今年何があったかざっくりと
- 大学入った
- MacBook Pro Early2015買ってもらう
- 自作PCした
- SLP(サークル)に入った
- Pythonに手を出した
- Linuxに興味を持ち出した
主に大学に入って思ったことと、今年1年の反省を書いていこうと思う。
大学に入った感想
工業高校から某国立大学に推薦入試で入った。
地元から離れ、一人暮らしをするのもなかなか面白いもので、寂しいとか実家に帰りたいとはあまり思わなかった。
サークルは、技術力の高い人が同期にも上にもたくさんいて、自分にとってとても良い刺激になったと思う。
工業高校といっても私は情報系出身ではないため、情報系の人間との関わりはせいぜいTwitterぐらいだった。
だからサークルでの活動は刺激的だったと思う。技術面だけでなく、精神面でも視野が広がったと思える。
人間関係が思ったより重要さを実感した。サークルで得られた情報も多いし、いろんなきっかけづくりになったと思う。
はじめは…
工業高校から大学に入って進学校出身の人間といろいろ話すと違うと思っていた。
だが、同期はさほど高校時代と変わらなかった。
自分から技術的なことを勉強するわけでもなく、
学校で教えてもらえると思っている人間が多く、はじめは嫌悪することもあった。
自分で勉強しに来たんだから他人に高めてもらうとかおこがましいとか思ってた。
価値観の違いが許容できないこともあり、
自分の理想を他人に押し付けたりするような言動もあったと思う。
良かれと思っていろいろ言った。
だが…、
ここから良い話になるかと思ったら大間違いだ。
別に技術力や関心がなくてもいっか。私に関係ない限りは。
だって大学生だぜ?自分の意思で来たんだろ?じゃあどうなっても知らねえ。
…と、無関心になるのがある意味お互いハッピーなんじゃないかと思った。
そんなこと考えてる暇あったらなんか勉強するほうがマシだ。
それでも反省すべき点はいろいろある
傲慢なところ、独善的なところは他人に無関心になることで少しは改善できると思う。 昔から道徳観のないところは直す気がまったくないからどうでも良い。むしろいらない。 謙虚じゃない、自重しない点は…直せる気がしない。
反省するとは言ったが直すとは言ってない。
…ひどい男だ
どこまでも自分勝手な人間だと思う。
それでも自分は構わないし自分の性格が本気で悪いと思ったことは実はあまりない。
ただ、こんな偉そうなことを言っても説得力のある人間になりたいものだ。
来年の目標みたいなもの
- 技術力の向上(最優先)
- 自分が自由に動ける環境を構築する
駄文でお目汚し失礼しました
単なる率直な感想並べただけなのでスルー推奨です。
ConoHaで初めてのVPS(ArchLinux)
この記事はSLP_KBIT Advent Calendar 2016の6日目の記事です。
はじめに
サーバーほしいなあと思って、でもレンタルサーバーだったらCentOSとかUbuntu使うわけだからハードル高いですよね。(錯乱) じゃあVPSで自分の好きなディストリが入れたい。って思っていたらとあるイベントにて、
「ConoHaならArchLinuxのOSテンプレートがありますよ。」
と耳寄りな情報が。ConoHaってなんぞ?VPSはさくらぐらいしか知らないんだが状態な自分には新天地。 調べてみると
- 豊富なOSテンプレートがある。
- 豊富なアプリケーションテンプレートがある(主にCentOS用)
- クレジットカードなしでもできる。
- 最小構成で月630円~から始められる
- 美雲このはちゃんがかわいい
目的
- 今作ってるWebアプリの本番環境として
- 自分で自由に管理できるサーバーが欲しかった
- dockerの勉強用
環境
スペック
手順
必要なもの
- PC
- 630円以上のお金
サーバー起動まで
- ますConoHaに会員登録する
- 支払い方法(クレカ、銀行、PayPal、コンビニ)を決める
- サーバーを追加する
- スペック等の入力をする
- 構築するまで待って起動したらSSH接続してみる
- コントロールパネルで、SSH以外のポートを閉じる
各種設定
ssh 接続して、とりあえず更新
# ssh root@XXX.XXX.XXX.XXX # pacman -Syu
ホストネームの変更
# echo [HOST_NAME] > /etc/hostname
あまりrootで作業したくないのでユーザーの追加
# useradd -m -g wheel <USERNAME> # passwd <USERNAME>
あとsudoの権限を変える
# visudo # %wheel ALL=(ALL) ALLのコメントアウトを外す
自分好みに必要なものインストール
# pacman -S zsh vim emacs tmux git
dotfilesのインストール
ますはrootで
# git clone https://github.com/guni973/dotfiles # cd dotfiles # ./makelink.sh
次はユーザに移って、ついでにシェルもZshに変える
# su <USERNAME> $ cd $ git clone https://github.com/guni973/dotfiles $ cd dotfiles $ ./makelink.sh $ chsh /usr/bin/zsh
ここで再起動させる。
powerlineのイントール
$ sudo pacman -S python python-pip powerline powerline-common $ source ~/.zshrc
zplugのインストール
$ curl -sL zplug.sh/installer | zsh $ zplug install
dockerのインストール
$ su # pacman -S docker # systemctl start docker
とりあえずArchLinuxいれてやってみる
# docker pull base/archlinux # docker run -it base/archlinux bash
一応動いた。あとはこれから勉強する。
まとめ
- 自分の好きにできる環境を作った
- あとはrootでのログインを禁止にしたりする
- 必要なもの入れたからあとはDockerなり、Nginxなどの環境作る
- VPS初体験だったけど作業的にはインストール後のArchLinuxと変わらない
ArchLinuxのデスクトップ環境を構築する
ArchLinuxのデスクトップ環境を構築する
ArchLinuxをインストールしたあとの作業です。
ここからの作業は人それぞれになりますが、今回は私の環境を構築する際の手順を書いておきます。
使用環境
PC: Thikpad X250 DE: Gnome3 DM: GDM
インターネット接続
Wifiを使うのはNetworkManagerを入れてからにします。
# systemctl enable dhcpcd.service # systemctl start dhcpcd.service
ユーザーの追加
# useradd -m -g wheel [USERNAME] # passwd [USERNAME]
sudoの導入
# pacman -S sudo # visudo
以下のコメントアウトを外して有効化する
Defaults env_keep += "HOME" %wheel ALL=(ALL) ALL
ssh接続の設定
# pacman -S openssh # systemctl enable sshd # systemctl start sshd # su [USER_NAME]
ssh接続
$ ssh [USERNAME]@192.168.XX.X
必要なもののインストール
$ sudo pacman -S vim git zsh tmux
X Window Systemのインストール
$ sudo pacman -S xorg-server xorg-server-utils xorg-xinit xorg-xclock xterm
グラフィックドライバはここを参考に
https://wiki.archlinuxjp.org/index.php/Xorg
自分はintelのグラフィックドライバなので
sudo pacman -S xf86-video-intel
タッチパッドの設定
sudo pacman -S xf86-input-synaptics
タッチパッドの設定は/etc/X11/xorg.conf.d/に記述します。
設定ファイルはここを参考に
https://wiki.archlinuxjp.org/index.php/Synaptics_%E3%82%BF%E3%83%83%E3%83%81%E3%83%91%E3%83%83%E3%83%89
ちなみに私の設定を載せておきます。
Section "InputClass" Identifier "touchpad catchall" Driver "synaptics" MatchIsTouchpad "on" MatchDevicePath "/dev/input/event*" #Option "TapButton1" "1" #Option "TapButton2" "2" #Option "TapButton3" "3" Option "VertScrollDelta" "-111" Option "HorizScrollDelta" "-111" # 横エッジスクロール Option "HorizEdgeScroll" "on" # 縦エッジスクロール Option "VertEdgeScroll" "on" # 左右同時クリックで中ボタン Option "Emulate3Buttons" "on" EndSection
GNOMEの導入
$ sudo pacman -S gnome gnome-tweak-tool
ディスプレイマネージャの有効化
# systemctl enable gdm
Yaourt(AURヘルパー)の導入
AUR(Arch User Repository)を使うための準備
# vim /etc/pacman.conf
以下を追記
[archlinuxfr] SigLevel = Never Server = http://repo.archlinux.fr/$arch [pnsft-pur] SigLevel = Optional TrustAll Server = http://downloads.sourceforge.net/project/pnsft-aur/pur/$arch
以下のコメントアウトを外す
[multilib] Include = /etc/pacman.d/mirrorlist
保存して終了する
# pacman --sync --refresh yaourt # pacman -Syu
これでyaourtが使えるようになる
日本語フォントの導入
# yaourt -S otf-ipaexfont
fcitxの導入
日本語を入力するため、fcitxとfcitx-mozcをインストールする
$ sudo pacman -S fcitx-im fcitx-mozc fcitx-configtool
.xprofileのに追記する
fcitx export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS=@im=fcitx
NetworkManagerの導入
NetworkManagerを導入する際にはntctlやwicdなどをを無効化しておく
$ sudo pacman -S networkmanager network-manager-applet xfce4-notifyd $ sudo systemctl enable NetworkManager.service
ArchLinuxをThinkPadにインストールする
ArchLinuxをThinkPadにインストールした
ArchLinuxとは
非常に軽量で自由度の高いLinuxのディストリビューションです。有名なUbuntuやCentOSはインストール後はある程度誰でも使えるようになっていますが、Archははじめからなんでも揃っているわけではないので使う人を選ぶと思います。
ArchLinuxのメリット・デメリット
メリット
デメリット
- インストールがめんどくさい。
- インストールしてもはじめはブラウザも日本語環境も何もない。
- 安定性がない。
Archがどうしても敷居が高くて無理という方はUbuntuを使ってLinuxに慣れたり、ManjaroなどのArchベースのディストリビュージョン)を使って慣れておくと良いと思います。
必要なもの
環境
今回はGPTで、パーティション分割にはgdiskを用います ブートローダはBIOS、UEFI両方に対応(インストール方法は違う)しているgrubを用います。
インストールメディアの作成(Macの場合)
今回はUSBメモリからArchをインストールする。
$ hdiutil convert -format UDRW -o arch arch.iso $ diskutil list $ df # /dev/diskX のMounted on を確認する /Volumes/XXX $ diskutil umount /Volumes/XXX $ sudo dd if=arch.dmg of=/dev/diskX bs=1m
Wifiの設定はインストールしてから行うため、インストール作業は有線LANで繋いで行います。
BIOSから起動順序変えて、ブートします。
SSHでMacBookProから接続
ThinkPadでの操作
# ip addr # IPアドレスを確認 # passwd # rootパスワードの変更 # systemctl start sshd
以下 MacBookProから操作
SSH接続
正直この作業をすべて手打ちで行うのが面倒なのでブログの内容をコピペします。 別のPCからssh接続して、作業を行います。
$ ssh root@192.168.XX.X
パーティション分割
パーティションの分割作業はパーティションテーブルがMBRかGPTかで異なります。 MBRにもGPTにも対応しているのがpartedですが正直なところ使いにくいので今回はGPT専用のgdiskを使います。 そして今回はデュアルブートではないのでSSD(またはHDD)の中身吹っ飛ばします。 デュアルブートにしたい方は別のサイトを参考にしてください。 また、今回はsdaにインストールするため、別の場所にインストールされる方は間違えないようにしてください。
# lsblk # gdisk /dev/sda
gdiskの使い方は割愛。
1 537MB fat32 EFI system boot,esp 2 2147MB ext4 Linux swap 3 237GB Linux filesystem
私と同じようなパーティション分割を行った方は下と同じ作業ですが、私と違う構成にされた方はファイルシステムの初期化とパーティションのマウントの作業などが異なります。
ファイルシステムの初期化
# lsblk /dev/sda # mkfs.vfat -F32 /dev/sda1 # ESPの初期化 # mkfs.ext4 /dev/sda3 # ext4のフォーマット # mkswap /dev/sda2 # swapの初期化 # swapon /dev/sda2
パーティションのマウント
# mount /dev/sda3 /mnt # mkdir /mnt/boot # mount /dev/sda1 /mnt/boot
ミラーの選択
# vim /etc/pacman.d/mirrorlist
Source : Japanを一番上に持ってくる
ベースシステムのインストール
# pacstrap -i /mnt base base-devel
Enterですべてインストール
fstabの生成
# genfstab -U -p /mnt > /mnt/etc/fstab
新しくインストールしたシステムにchrootして作業します。
# arch-chroot /mnt /bin/bash
ホストネーム、タイムゾーン、言語、rootパスワードの設定
# echo [HOST_NAME] > /etc/hostname # ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime # エリア設定 # vi /etc/locale.gen # en_US.UTF-8の行のコメントを外す。 # locale-gen # echo LANG=en_US.UTF-8 > /etc/locale.conf # hwclock -u -w # passwd
ブートローダのインストールと設定
GRUBはBIOSでもUEFIでも使えますが、手順が異なります。 ここではUEFIの場合の方法を記述します。
# pacman -S grub efibootmgr dosfstools efibootmgr # grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=arch_grub --recheck --debug # grub-mkconfig -o /boot/grub/grub.cfg
chroot環境から抜け、シャットダウンする
# exit # shutdown -h now
起動ディスクを取り出して、起動してArchが立ち上がれば成功です。