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.