Goでプログラミング言語
(の途中まで)を
作ろう
esehara shigeo
お前
誰だ
esehara shigeo
ただのWeb系プログラマー
(Python使い)
Webプログラマーに
ありがちな中二病
Lisp
※皆様がいるカンファレンスはGo Conです。安心してください。
Lispが持つ病
1. 関数型言語カッコイイ!
2. 関数型言語の元祖といえばLisp!カッ
コイイ!(括弧なだけに)
3. コンピューターサイエンス、Artifact
Intelligenceの分野でも活躍!
Awesome!
4. Lispが使いこなせると構文木も自由自
在!
Lispは
もっとも美しい
言語
※皆様がいるカンファレンスはGo Conです。安心してください。
全ての言語は
S式を
信じられない
人間によって作ら
れる
「Lispはエリート向けの言語」
LL系プログラマーに
ありがちな中二病
C言語
※皆様がいるカンファレンスはGo Conです。安心してください。
C言語が持つ病
1. 「Lightweight Languageって所詮富豪
プログラミングだよねー」
2. 「Lightweight Languageって所詮ポイ
ンタとかメモリアドレスとか知らないんで
しょ」
3. 「Lightweight Languageってコンパイル
のこととか所詮わからないんでしょ」
屈辱ッ!
でもC言語は
つらぽよ……
そんな貴方の
ための!!
Go
※皆様がいるカンファレンスはGo Conです。安心してください。
前置きは
ここまで
そもそもプログラミング言語
処理ってなに?
How to Create Your Own
Programming Language

http://createyourproglang.com/
“The book I want to read.”
プログラミング言語処理の流れ

『Create your own language』より
字句解析(Tokenize)
とは?
文字のカタマリ
によって
その文字が
何に属するのか
を分析する
例: Haskell 2010 Language Report
literal -> integer | float | char | string
digit -> ascDigit | uniDigit
ascDigit -> 0 | 1 | … | 9
uniDigit -> any Unicode descimal decit
decimal -> digit{digit}
integer -> decimal
Goで

字句解析器を作ろう
packageに
あるよ!
>
Tips: 困ったら公式のGoのpackageのソースを読みましょう
go/scanner
使える

http://www.oki-osk.jp/esc/golang/lisp.html
とはいえ、
このSourceを入れ替えて
使うのはつらいので
自動
生成
Ragel :: State Machine Compiler
Ragel compiles executable
finite state machines from
regular languages. Ragel
targets C, C++, ObjectiveC, C#, D, Java, Ruby,
OCaml and

Go.
そして
Rust班も頑張ってる(まだ非公式)
Ragelの書きかた
# ---- Literal ---string = ("'" . (any - "'")* . "'")
    |('"' . (any - '"')* . '"');
integer = digit+;
atom = (alpha (alpha | digit)* );
# ---- Operator ---operator = "+" | "-" | "*" | "/";
main := |*
atom => {
material := Ore{
Token: ATOM,
Value: data[ts:te],
}
material.Research()
ores = append(ores, material)
};

String => {
material := Ore{
Token: STRING,
Value: data[ts:te],
}
material.Research()
ores = append(ores, material)
};
….
二つの流れ

どの文字の規則を
トークンとして定義するか?
トークンをどのように
管理するか?
文字の規則とトークン
# ---- Literal ---string = ("'" . (any - "'")* . "'")
    |('"' . (any - '"')* . '"');
integer = digit+;
atom = (alpha (alpha | digit)* );
# ---- Operator ---operator = "+" | "-" | "*" | "/";
Ragelによる図式化
トークンの処理
main := |*
atom => {
material := Ore{
Token: ATOM,
Value: data[ts:te],
}
material.Research()
ores = append(ores, material)
};
トークンの管理方法

type Ore struct {
Token Token // int
Name string
}
トークンの定義
const(
//Special Token
ILLEGAL Token = iota
EOF
COMMENT
begin_define_literal
ATOM
STRING
INTEGER
end_define_literal
………
)

参考: go/token
このように作った
トークンの順序を
構文解析する
Goで

構文解析器を作ろう
toolに
あるよ!
>
go tool yacc
Yacc is a version of yacc for Go.
It is written in Go and generates parsers written in Go.
(公式より)
yaccとは?

Yet Another
Compiler Compiler
go yaccの書きかた
%type <val> ATOM, STRING, OPERATOR, BINDER, DEFINE
%type <val> ARG
%type <val> action, Expression
%type <values> StringExpression, AtomExpression
%%

%{
package casting
import (
"fmt"
"..
/miner"
)
%}
%union {
tok int
val interface{}
values Val
box Box
}
%token ATOM STRING
%token ARG
%token OPERATOR BINDER DEFINE
%token ROUNDPAREN_O ROUNDPAREN_C

action:
ATOM {
var v Value
v = Box{Type: ATOM, Value: $1,}
yylex.(*lex).NewBox(v)
}
| Expression {
if val, ok := $1.(Val); ok {
yylex.(*lex).root = val
}
}
...
何してるの?

トークンの順序を
解釈しやすいように再構築
利用するトークンの定義

%token ATOM STRING
%token ARG
%token OPERATOR
%token BINDER DEFINE
%token ROUNDPAREN_O
ROUNDPAREN_C
ここで一つ
問題が
Ragelで宣言したトークンと
go yaccで宣言したトークンは
お互いどういう対応に
なってるかを知らない
対応させましょう
var oretokens = [...]int {
miner.ATOM: ATOM,
miner.STRING: STRING,
miner.OPERATOR: OPERATOR,
miner.BINDER: BINDER,
miner.ROUNDPAREN_O: ROUNDPAREN_O,
miner.ROUNDPAREN_C: ROUNDPAREN_C,
}
func toToken(ore miner.Ore) int {
return oretokens[ore.Token]
}
もう一つ
問題が
Go yaccで宣言したトークンが
どのような型になってるべきか
を教えてないといけない
トークンの型定義
%union {
tok int
val interface{}
values Val
box Box
}
%type <val> ATOM, STRING, OPERATOR, BINDER,
DEFINE
%type <val> ARG
%type <val> action, Expression
%type <values> StringExpression, AtomExpression
あとは
抽象構文木を
作成しよう
抽象構文木とは

http://en.wikipedia.org/wiki/Abstract_syntax_tree
抽象構文木 =
Node =
配列の入れ子
例
Goで

抽象構文木を歩こう
packageに
あるよ!
>
Tips: 困ったら公式のGoのpackageのソースを読みましょう
go/ast
Package ast declares the types used to represent
syntax trees for Go packages. (公式より)
※実はPythonにも標準パッケージとしてあります
ネタが尽
きました
おまけ
関数宣言の
管理
関数宣言の管理とGlobal Environment

http://www-inst.eecs.berkeley.edu/~cs61a/sp12/book/
Global
Environment
は一つ
シングルトン
だ!
トークンの型定義
type Env interface{}
type envs []Env
var environment envs
type EnvValue struct {
Name string
Val Env
}
func AccessEnv() *envs {
return &environment
}
DEMO
Go languageで大切なこと
標準Package
の
ソースは
宝の山
さしずめこんな感じ
ご清聴
ありがとう
ございました
https://github.com/
esehara/Perid

Goで言語処理系(の途中まで)を作ろう