I thought it would be fun to take a break from practical, useful content to show you a neat Ruby party trick.
Before Ruby runs your program it has to parse it. The parser is a kind of a state machine. And there is a little-known command line flag that you can use to make Ruby log everything the state machine does.
Take the following example:
a = 1 + 2
If I run this using the
-y flag, I get the following output:
$ ruby -y sample.rb Starting parse Entering state 0 Reducing stack by rule 1 (line 903): -> $$ = nterm $@1 () Stack now 0 Entering state 2 Reading a token: Next token is token tIDENTIFIER () Shifting token tIDENTIFIER () Entering state 35 Reading a token: Next token is token '=' () Reducing stack by rule 509 (line 4417): $1 = token tIDENTIFIER () -> $$ = nterm user_variable () Stack now 0 2 Entering state 113 Next token is token '=' () Reducing stack by rule 100 (line 1764): $1 = nterm user_variable () -> $$ = nterm lhs () Stack now 0 2 ... 140 more lines
What we're seeing here is the Ruby parser cycling through each token in the file and performing the following operations:
- Add the token to a stack
- Compare the stack to a list of rules
- If the token matches a rule, do a state transition
- If no match, add another token to the stack and try again.
All of the states and rules are defined in parse.y a file that is processed by the bison parser generator to generate the actual parser which is in C.