Guniの備忘録

ArchLinuxやプログラミングの勉強状況を更新していきます

自作言語を作り始めた話

久々のブログ更新でこの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));
}

実行結果

f:id:guni1192:20171213121603p:plain

…電卓っすね。

今後の実装予定(言い訳フェイズ)

実装力の限界ッ!

文字列とfor文を今せっせと書いてるところです。
早いとこFizzBuzzできるようになりたいなあ。

今回内容が薄いのは今後に期待という感じでよろしくお願いします。

一応ここに、置いときますね。
https://github.com/guni973/soba

B3になったときのコンパイラの授業が楽しみでならない。
今後も機能追加、改善していくつもりなので、よろしくです。

参考リンク

まつもとゆきひろ 言語のしくみ

Flex

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の勉強用

環境

スペック

  • OS:ArchLinux 64bit
  • CPU:Xeon E5-2260 v3 2core
  • RAM:1GB
  • SSD 50GB
    f:id:guni1192:20161205152716p:plain

手順

必要なもの

  • PC
  • 630円以上のお金

サーバー起動まで

  1. ますConoHaに会員登録する
  2. 支払い方法(クレカ、銀行、PayPal、コンビニ)を決める
  3. サーバーを追加する
  4. スペック等の入力をする
  5. 構築するまで待って起動したらSSH接続してみる
  6. コントロールパネルで、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ディストリビューションです。有名なUbuntuCentOSはインストール後はある程度誰でも使えるようになっていますが、Archははじめからなんでも揃っているわけではないので使う人を選ぶと思います。

ArchLinuxのメリット・デメリット

メリット
  • パッケージが新しい
  • Wikiなどのコミュニティが充実している
  • 軽い
  • 余計なものが入っていない
  • PCの勉強になる
  • 基本的に作業はCUI(管理が楽)

デメリット

  • インストールがめんどくさい。
  • インストールしてもはじめはブラウザも日本語環境も何もない。
  • 安定性がない。

Archがどうしても敷居が高くて無理という方はUbuntuを使ってLinuxに慣れたり、ManjaroなどのArchベースのディストリビュージョン)を使って慣れておくと良いと思います。

必要なもの

  • USBメモリ (1GB以上)
  • インストールするPC(ThinkPad X250)
  • インストールメディアを作成する&SSHで繋いでコピペするPC(MacBookPro)

環境

今回はGPTで、パーティション分割にはgdiskを用います ブートローダBIOSUEFI両方に対応(インストール方法は違う)している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

ブートローダのインストールと設定

GRUBBIOSでも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が立ち上がれば成功です。

参考ページ

初投稿

ArchLinuxのカスタマイズや

Pythonで作ったもの、C++の勉強状況

Raspberry Pi 3で遊んだことなどを投稿していきます。