03 Ruby是這樣“理解”你給它的程序文本的

Ruby是這樣“理解”你給它的程序文本的

*.rb => 分詞 => 解析 => 編譯 => YARV指令

  1. 程序文本轉換爲一系列的詞條
  2. LALR解析器把詞條輸入流轉換爲AST的數據結構
  3. 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

參考

  1. 《Ruby 原理剖析》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章