2013-06-24 28 views
2

如何預測Ruby如何解析事物?Ruby解析器的原理是什麼?

在嘗試連接字符串時,我遇到了一個非常令人驚訝的Ruby解析錯誤。

> "every".capitalize +"thing" 
=> NoMethodError: undefined method `[email protected]' for "thing":String 

當然,如果你把額外的空間在他們的,它按預期工作;如果我有anything.any_method +"any string"會發生

> "every".capitalize + "thing" 
=> "Everything" 

此錯誤。 Ruby所做的是假設我們有一個簡化的括號,並且試圖爲這個方法提供一個參數。

"every".capitalize(+"thing") 

它注意到,我們還沒有確定對字符串的一元運算符[email protected],並拋出這個錯誤。

我的問題是,我應該使用什麼原則來預測Ruby解析器的行爲?我經過大量的搜索後才發現這個錯誤。值得注意的是,.capitalize沒有參數(即使在C源代碼中也沒有)。如果您使用的方法不適用於上一個對象,它仍會拋出[email protected]錯誤而不是undefined method 'capitalize' for "every":String錯誤。所以這個解析顯然是高層次的。我沒有足夠的知識來閱讀Matz的parser.y。我遇到了其他類似的令人驚訝的錯誤。任何人都可以告訴我Ruby的解析優先級?

+0

還有BNF形式的[Ruby語法](http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/yacc.html),它比解析器的密度稍小.y文件。 – squiguy

回答

3

如果你想看到的紅寶石是如何分析你的代碼,你可以轉儲分析樹,即

ruby -e '"every".capitalize +"thing"' --dump parsetree

# @ NODE_SCOPE (line: 1) 
# +- nd_tbl: (empty) 
# +- nd_args: 
# | (null node) 
# +- nd_body: 
#  @ NODE_CALL (line: 1) 
#  +- nd_mid: :capitalize 
#  +- nd_recv: 
#  | @ NODE_STR (line: 1) 
#  | +- nd_lit: "every" 
#  +- nd_args: 
#   @ NODE_ARRAY (line: 1) 
#   +- nd_alen: 1 
#   +- nd_head: 
#   | @ NODE_CALL (line: 1) 
#   | +- nd_mid: :[email protected] 
#   | +- nd_recv: 
#   | | @ NODE_STR (line: 1) 
#   | | +- nd_lit: "thing" 
#   | +- nd_args: 
#   |  (null node) 
#   +- nd_next: 
#    (null node) 

我喜歡用explainruby有時太,因爲它是在我的眼睛更容易:)