2013-06-24 29 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有时太,因为它是在我的眼睛更容易:)