Ruby是這樣“理解”你給它的程序文本的
*.rb => 分詞 => 解析 => 編譯 => YARV指令
- 程序文本轉換爲一系列的詞條
- LALR解析器把詞條輸入流轉換爲AST的數據結構
- AST數據結構轉換爲字節碼指令
分詞
依 print("hello world")
爲例:
require 'ripper'
require 'pp'
pp Ripper.lex <<CODE
print("hello world")
CODE
print("hello world")
CODE
輸出:
[[[1, 0], :on_ident, "print", CMDARG],
[[1, 5], :on_lparen, "(", BEG|LABEL],
[[1, 6], :on_tstring_beg, "\"", BEG|LABEL],
[[1, 7], :on_tstring_content, "hello world", BEG|LABEL],
[[1, 18], :on_tstring_end, "\"", END],
[[1, 19], :on_rparen, ")", ENDFN],
[[1, 20], :on_nl, "\n", BEG]]
語法解析
Bison
parse.y 中定義了 Ruby 代碼必須遵守的語法規則。
AST
require 'ripper'
require 'pp'
code = <<CODE
10.times do |n|
puts n
end
CODE
pp code
pp Ripper.sexp(code)
10.times do |n|
puts n
end
CODE
pp code
pp Ripper.sexp(code)
輸出:
"10.times do |n|\n" + " puts n\n" + "end\n"
[:program,
[[:method_add_block,
[:call,
[:@int, "10", [1, 0]],
[:@period, ".", [1, 2]],
[:@ident, "times", [1, 3]]],
[:do_block,
[:block_var,
[:params, [[:@ident, "n", [1, 13]]], nil, nil, nil, nil, nil, nil],
false],
[:bodystmt,
[[:command,
[:@ident, "puts", [2, 2]],
[:args_add_block, [[:var_ref, [:@ident, "n", [2, 7]]]], false]]],
nil,
nil,
nil]]]]]
Process finished with exit code 0
顯示有關 AST 節點的結構信息
a = 1;
執行:
ruby --dump parsetree demo.rb
輸出:
###########################################################
## Do NOT use this node dump for any purpose other than ##
## debug and research. Compatibility is not guaranteed. ##
###########################################################
# @ NODE_SCOPE (line: 1, location: (1,0)-(1,6))
# +- nd_tbl: :a
# +- nd_args:
# | (null node)
# +- nd_body:
# @ NODE_LASGN (line: 1, location: (1,0)-(1,5))*
# +- nd_vid: :a
# +- nd_value:
# @ NODE_LIT (line: 1, location: (1,4)-(1,5))
# +- nd_lit: 1
參考
- 《Ruby 原理剖析》