Sendai Hackathon#0
今日は、片平さんのオフィスにお邪魔させてもらい、勉強会をしてきました。
で、名前を勝手にSendai hackathon#0 とすることにしました。ということで、
Sedai Hackathon#0終了です。
14時〜21時の7時間、しりをたたき、たたきたたかれつつおのおの作りたいものを作りました。
途中で一度、ドイツビールのお祭りやってるのでのみに行って、ワインも飲んだりしました。
非常に楽しかったです。
わがまま、言いまくって、申し訳ない気もしますが、ま、いいや。(w
自分は簡単なプログラミング言語の作り方を書きたいので、片平さんに説明しつつ、難しいところはどこなのかを
聞いて、自分の経験とあわせつつ、難しく感じる部分は取っ払っおうという結論になりました。
まず、字句解析は配列を作ってしまうのがやっぱりわかりいい。細々読み込みは難しいし、先読み機構も最初はわかりずらい。
だんだん分かってくればいいんだろうけど。という話で、自分も昔はそう思ってたのでそう直すことにしました。
あと、優先順位をつける構文解析まで一気に理解するのも、理解するのも難しいだろうということで、
優先順位無しでまず説明することにしました。
ということで、今日作ったプログラムはこれです。
ならべて、phpバージョンもこれから作ります。
説明はまた、あとで書きます。(w
いろいろ話を聞いてもらって、自分が作ろうとしているのは教育用言語で、
限りなく簡単だけど十分な表現能力を持っている言語を作ろうとしていることがわかりました。
それで、書籍になるレベルまでレベルUPさせていくのが目標と。
ライブラリを作るのが大変なんじゃ?
とか、何人かに聞かれたのだけどそうじゃないんだよなぁっと。
そりゃライブラリ作りは大変だけど、その前に誰でも簡単に言語処理系を作れるようにすることがもっと難しいんです。
というのがあるので、それが実現されることがまず、大きな目標なのです。
誰でも作れるくらい簡単だから、美しい言語なのだといいたいのです。
それって結局教育用言語ってことになるのかなと。
でも、そのくらい簡単なので、自分でもさくさく作れるようになるはずで、
本当に、さくさく作れるようになってしまえば、あとはライブラリを書くだけです。
class Lexer def initialize src @src = src end def lex case @src when /^[\r\n\t ]*([0-9]+)(.*$)/ when /^[\r\n\t ]*([+*\-\/()])(.*$)/ when /^[\r\n\t ]*(.*)(.*$)/ return nil end @src = $2 $1 end def tokens ts = [] while (token = lex) != nil ts.push(token) end ts end end class Parser def parse(src) @lexer = Lexer.new(src) tokens = @lexer.tokens # p tokens t = tokens.shift.to_i while tokens.first == "+" || tokens.first == "-" || tokens.first == "*" || tokens.first == "/" op = tokens.shift t = [op, t, tokens.shift.to_i] end t end end class Calc def initialize @parser = Parser.new end def eval src tree = @parser.parse(src) # p tree exp tree end def exp tree if tree.instance_of?(Array) case tree[0] when "+" exp(tree[1]) + exp(tree[2]) when "-" exp(tree[1]) - exp(tree[2]) when "*" exp(tree[1]) * exp(tree[2]) when "/" exp(tree[1]) / exp(tree[2]) end else tree end end end calc = Calc.new p calc.eval("1+2*3")
このプログラムは優先順位がないので、((1+2)*3)を計算します。結果として9が返ります。
ざっくりした説明だけ書いておきますと、Lexerというのが文字列をトークンの列に分解します。
Parserがトークン列を木構造にします。
そして、Calcが木構造を計算して結果を返します。
というようなつくりになっております。