-
Notifications
You must be signed in to change notification settings - Fork 1
Syntax Grammar
The MRI syntax grammar doesn't lend itself to precise formal documentation in the typical fashion for programming languages, because the parsing process is implemented in a fairly complicated way that can occasionally be inconsistent and/or buggy, and to fully describe what the permitted syntax is would require a myriad of detailed rules for exceptional circumstances that wouldn't be much use to anyone.
However, this is not a problem, because we can easily describe the syntax of Ruby by showing all the important elements, but point out where odd, but harmless, exceptional behaviours can occur, and leave these behaviours undefined. This way gives the intent of the syntax grammar without getting bogged down in implementation limitations.
I've described the grammar of specific syntax elements in other sections - this page explains the rules for combining expressions together.
#Statements
A statement is any Ruby expression terminated either by ; or a newline character, within the context of a block of statements. A block of statements is executed iteratively in the typical fashion. A block of statements is permitted as part of various other expressions e.g. def, class, module, if, rescue etc.
A block of statements can be nested within another Ruby expression by enclosing it within ( and ), or by using a begin/end expression (i.e. enclosing between begin and end, note that begin/end expressions also have some other specific behaviours). The return value of a block of statements is the return value of the last statement in the block.
A Ruby sourcefile is a block of statements.
##Newline terminators Statements can be made to run across multiple lines of code for code readability purposes - if a newline character occurs mid-statement and it can't possibly be the end of a statement, Ruby will often ignore the newline.
However, the Ruby implementation of this is fairly simplistic, based on what the last token before the newline was and without taking into account the broader context of how the newline is nested and what's on the following line. Therefore, there are scenarios where Ruby will not ignore the newline even though it probably should. For example, Ruby won't necessarily know to ignore a newline in the following places:
- In the middle of an argument list which is inside parentheses/brackets/braces, unless the line ends in
,or some other token that makes it obvious the statement has not finished (e.g. operators, opening parentheses/brackets/braces) - Exception: Ruby will generally ignore a newline that occurs just before closing parentheses/brackets/braces
- If the code on the next line can't possibly be a new statement or other valid syntax (and so must be part of the current line's statement)
- Exception: if the next line begins (after whitespace) with a
., Ruby will ignore the newline, so you can chain method calls and insert a newline before the. - Exception: In the ternary
?:operator, Ruby will ignore a newline directly before the:
#Control transfer expression restrictions
Ruby will generally raise a compile error if you use a control transfer expression (return/break/next/redo/retry) in a place which requires a value and it doesn't really make sense to transfer control (e.g. assignment expressions, operator expressions, conditional expressions, call arguments, explicitly scoped method calls/constant references). The main exception is that you can use a control transfer instruction on the right hand side of logical and/or operators, in order to take advantage of the short-circuiting feature.
#Hierarchy of expressions In general I've simplified and said that any Ruby expression can be used at any time,
command call brace args, do blocks, and chains
Operator conflict resolution Do/brace/bracket/paren conflict resolution
Character processing details - newlines, eof reserved words
A Ruby Language Reference
Copyright © by Michael Hore, 2016.
Introduction to This Document
Ruby Elements
- Classes and Modules
- Methods
- Blocks, Procs and Lambdas
- Execution Context and Closures
- Variables, Constants and Namespaces
- Types and Literals
- Ruby Expressions
- Operators
Syntax Grammar
Exceptions and Throw
Ruby Sourcefiles and Libraries
Multi Threading
Execution and Lifecycle