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

79
Goでプログラミング言語 (の途中まで)を 作ろう esehara shigeo

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

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 | stringdigit -> ascDigit | uniDigitascDigit -> 0 | 1 | … | 9uniDigit -> any Unicode descimal decitdecimal -> 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++, Objective-

C, 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 yaccYacc 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の書きかた

%{package casting

import ("fmt"

"../miner")%}%union {tok intval interface{}values Valbox Box}

%token ATOM STRING%token ARG%token OPERATOR BINDER DEFINE%token ROUNDPAREN_O ROUNDPAREN_C

%type <val> ATOM, STRING, OPERATOR, BINDER, DEFINE%type <val> ARG%type <val> action, Expression%type <values> StringExpression, AtomExpression%%

action:ATOM {var v Valuev = 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 intval interface{}values Valbox 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/astPackage 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 []Envvar environment envs

type EnvValue struct {Name stringVal Env}

func AccessEnv() *envs {return &environment}

DEMO

Go languageで大切なこと

標準Packageの

ソースは

宝の山

さしずめこんな感じ

ご清聴ありがとう

ございました