【问题标题】:What are the principles of the Ruby parser?Ruby解析器的原理是什么?
【发布时间】:2013-06-24 21:51:32
【问题描述】:

我如何预测 Ruby 将如何解析事物?

我在尝试连接字符串时遇到了一个非常令人惊讶的 Ruby 解析错误。

> "every".capitalize +"thing"
=> NoMethodError: undefined method `+@' for "thing":String

当然,如果你把多余的空间放在它们里面,它会按预期工作;

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

如果我有anything.any_method +"any string",就会出现这个错误。 Ruby 所做的是假设我们已经省略了括号,并试图为该方法提供一个参数;

"every".capitalize( +"thing" )

它注意到我们没有在字符串上定义一元运算符+@,并抛出该错误。

我的问题是,我应该使用什么原则来预测 Ruby 解析器的行为?经过大量的谷歌搜索后,我才发现了这个错误。值得注意的是,.capitalize 从来没有接受过参数(甚至在 C 源代码中也没有)。如果您使用不适用于前一个对象的方法,它仍然会抛出 +@ 错误而不是 undefined method 'capitalize' for "every":String 错误。所以这个解析显然是高级别的。我没有足够的知识阅读 Matz 的parser.y。我遇到了其他类似的令人惊讶的错误。谁能告诉我 Ruby 的解析优先级?

【问题讨论】:

  • BNF 格式的Ruby grammar 也有,比 parser.y 文件的密度要小一些。

标签: ruby parsing lexical-analysis lexical-scope


【解决方案1】:

如果你想看看 ruby​​ 是如何解析你的代码的,你可以转储分析树,即

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: :+@
#         |   +- nd_recv:
#         |   |   @ NODE_STR (line: 1)
#         |   |   +- nd_lit: "thing"
#         |   +- nd_args:
#         |       (null node)
#         +- nd_next:
#             (null node)

我有时也喜欢使用explainruby,因为它对我来说更容易:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 2010-12-19
    • 2010-10-21
    • 2013-04-04
    相关资源
    最近更新 更多