Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Taipei.rb 寫一個送禮自用兩相宜的 Compiler
蒼時弦や
February 14, 2018
Programming
1
110
Taipei.rb 寫一個送禮自用兩相宜的 Compiler
蒼時弦や
February 14, 2018
Tweet
Share
More Decks by 蒼時弦や
See All by 蒼時弦や
elct9620
0
37
elct9620
0
47
elct9620
1
370
elct9620
1
250
elct9620
1
38
elct9620
0
32
elct9620
0
160
elct9620
0
53
elct9620
0
140
Other Decks in Programming
See All in Programming
grapecity_dev
0
170
grapecity_dev
0
190
mihyaeru21
0
360
alperhankendi
1
140
bells17
0
360
bkuhlmann
4
270
rarous
0
170
tarugoconf
1
1.5k
line_developers_tw2
0
270
masui_masanori
1
250
lovee
2
140
grapecity_dev
0
170
Featured
See All Featured
bryan
100
11k
marcelosomers
220
15k
myddelton
109
11k
trallard
14
710
searls
205
36k
aarron
257
36k
notwaldorf
15
1.8k
samlambert
237
10k
hatefulcrawdad
257
17k
skipperchong
8
710
sugarenia
233
850k
michaelherold
224
8.5k
Transcript
用 Ruby 寫一個送禮自用 兩相宜的 Compiler
襟 儘 䓛⛳ @elct9620 WEB DEVELOPER GAME DEVELOPER
None
None
#I_feel_border ⼤大家都在寫 Compier 作業
C4 不夠⽤用就⽤用 C5 啊! https://github.com/elct9620/5compiler Demo First Talk
Lexer Tokenizer Parser Source Code AST
簡單說就是照規則把字串串切開來來 Lexer
Lexer.new("count = 1 if reset") # ['count', '=', '1', 'if',
'reset'] Lexer
class Lexer < Array KEYWORDS = %w[if else end puts].freeze
KEYWORD_RULE = /(?<keyword>#{KEYWORDS.join('|')})/ end Lexer
RULE = Regexp.union( LINEFEED_RULE, SYMBOL_RULE, KEYWORD_RULE, STRING_RULE, NUMBER_RULE, WORD_RULE )
Lexer
script.scan(RULE).flatten.compact # ['count', '=', '1', 'if', 'reset'] Lexer
把 Lexer 切好的⽂文字片段做簡單的分類 Tokenizer
Tokeinzer.new(['if', 'reset']) # [ # <Token @type=“keyword” # @value="if"> #
<Token @type=“identifier" # @value="reset"> # ] Tokenizer
MATCH_RULES.each do |type, rule| if word.match?(rule) return Token.new(type, word) end
end Token.new(:literal, word) Tokenizer
class Token # ... def symbol? type == :symbol end
# ... end Tokenizer
依照 Token 的狀狀況轉換成⽤用樹狀狀的⽅方式表⽰示程式運作 Parser
IF TRUE FALSE BLOCK BLOCK
class Parser def parse tokens = @tokenizer.to_enum @context = Node::Context.new(tokens)
@ast = context.ast end end Parser
loop do break if t.peek.else? || #... #… if t.peek.fn?
next @ast << Node::Function.new(t) end #... end Parser
Context Parser Function Enter Context State Exit State Next token
is ‘else’ Enter Function State Exit State Next token is ‘end’
基於 Parser ⽣生成的 Abstract Syntax Tree 執⾏行行程式 Virtual Machine
將 AST 轉換為機器碼或者 VM 可以直接讀取的規格 Bytecode
借⽤用 Ruby VM 直接執⾏行行 `Kernel.send(‘puts’, ‘Hello World’)` 5Compiler’s VM
在 Router 中可以⽤用來來判斷⽬目前請求的網址對應的 Controller Rails’s AST
在 ActiveRecord (Arel) 可以⽤用來來組成 SQL 語法 Rails’s AST
⽤用來來動態執⾏行行 ActiveRecord 相關的動作 Ex. JSON Query, Update … Tamashii::TLang’s AST
很可惜困難的是 VM 怎麼動起來來喔⋯⋯ 聽起來來好像很簡單,對吧?
None