2013-06-24 4 views
2

Как я могу предсказать, как Ruby будет разбирать вещи?Каковы принципы анализатора Ruby?

Я столкнулся с действительно удивительной ошибкой разбора в Ruby, пытаясь объединить строки.

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

Конечно, если вы разместите дополнительное пространство в своем, оно работает по назначению;

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

Эта ошибка возникает, если у меня есть anything.any_method +"any string". То, что Ruby делает, предполагает, что мы выделили круглые скобки и пытаемся дать аргумент методу;

"every".capitalize(+"thing") 

Он замечает, что мы не определили унарный оператор [email protected] на строки, и бросает эту ошибку.

Вопрос, какие принципы следует использовать для прогнозирования поведения анализатора Ruby? Я только вычислил эту ошибку после множества поисковых запросов. Примечательно, что .capitalize не принимает никаких параметров (даже в исходном коде C). Если вы используете метод, который не применяется к предыдущему объекту, он по-прежнему выдает ошибку [email protected] вместо ошибки undefined method 'capitalize' for "every":String. Таким образом, этот синтаксический анализ, очевидно, является высокоуровневым. Я недостаточно осведомлен, чтобы прочесть Matz's parser.y. Я столкнулся с другими подобными неожиданными ошибками. Может ли кто-нибудь сказать мне приоритет разбора Ruby?

+0

Существует также [Ruby grammar] (http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/yacc.html) в форме BNF, которая немного менее плотная, чем синтаксический анализатор .y файл. – squiguy

ответ

3

Если вы хотите увидеть, как рубин разбора кода, вы можете сбросить parsetree, т.е.

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 иногда тоже, потому что это намного легче на моих глазах :)