<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>rasefon (Raw)</title>
    <link>https://ruby-china.org/rasefon</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Ruby china 代码里面的一个问题。</title>
      <description>&lt;p&gt;请教各位一个问题。
最近看了下 ruby china 的源代码，有个叫做 Cpanel 的是用在哪里的啊？……&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Fri, 14 Aug 2015 10:33:19 +0800</pubDate>
      <link>https://ruby-china.org/topics/26923</link>
      <guid>https://ruby-china.org/topics/26923</guid>
    </item>
    <item>
      <title>云梯现在是不是挂了？</title>
      <description>&lt;p&gt;貌似始终连不上。。&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Mon, 27 Jul 2015 21:03:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/26666</link>
      <guid>https://ruby-china.org/topics/26666</guid>
    </item>
    <item>
      <title>uglifier 实在太慢了，建议大家用 closure-compiler</title>
      <description>&lt;p&gt;同样的 precompile, uglifier 花了 5 小时，closure 只花了一分钟！&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Thu, 09 Jul 2015 17:13:59 +0800</pubDate>
      <link>https://ruby-china.org/topics/26409</link>
      <guid>https://ruby-china.org/topics/26409</guid>
    </item>
    <item>
      <title>淫神好像把他的博客搬家到了简书了。。。</title>
      <description>&lt;p&gt;&lt;a href="http://www.yinwang.org/" rel="nofollow" target="_blank"&gt;http://www.yinwang.org/&lt;/a&gt;
有粉丝跟上么？&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Mon, 26 Jan 2015 17:18:34 +0800</pubDate>
      <link>https://ruby-china.org/topics/23951</link>
      <guid>https://ruby-china.org/topics/23951</guid>
    </item>
    <item>
      <title>好玩的遗传算法。</title>
      <description>&lt;p&gt;之前有位同学问了个问题，关于随机数生成的，我想了想觉得用遗传算法是很好玩的，具体题目请见：
&lt;a href="https://ruby-china.org/topics/23514" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/23514&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;如何实现，请看：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vg"&gt;$pm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;
&lt;span class="vg"&gt;$cluster_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="vg"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gen_rands&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;rands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rands&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;rands&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gen_rands_arr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr_num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;rands_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;arr_num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;rands_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;gen_rands&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;rands_arr&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_rands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;total_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
  &lt;span class="n"&gt;curr_p_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;all_rands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rands&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;curr_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;rands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;curr_p&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;curr_p&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="vg"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rands&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;curr_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;curr_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr_p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;
    &lt;span class="n"&gt;curr_p_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;curr_p&lt;/span&gt;
    &lt;span class="n"&gt;total_p&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;curr_p&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;fit_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;fit_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;curr_p_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;total_p&lt;/span&gt;
  &lt;span class="n"&gt;curr_p_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;fit_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;fit_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;curr_p_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;total_p&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;fit_arr&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ga&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;rands_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gen_rands_arr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$cluster_num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;fit_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="vg"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="n"&gt;fit_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="n"&gt;selector_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="vg"&gt;$cluster_num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;selector_arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;selected_rands_indexs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$cluster_num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;selector_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# binary search&lt;/span&gt;
      &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fit_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;
        &lt;span class="n"&gt;middle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fit_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
          &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;middle&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;middle&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;selected_rands_indexs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;next_gen_rands_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="vg"&gt;$cluster_num&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;selected_rands_indexs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;selected_rands_indexs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

      &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;selected_rands_indexs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$cluster_num&lt;/span&gt;
      &lt;span class="n"&gt;selected_rands_indexs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

      &lt;span class="n"&gt;next_gen_rands1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
      &lt;span class="n"&gt;next_gen_rands2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
      &lt;span class="c1"&gt;# 随机交叉点&lt;/span&gt;
      &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt;
        &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;
        &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt;
        &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt; 

      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;next_gen_rands1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;next_gen_rands2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;jj&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;next_gen_rands1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;next_gen_rands2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="c1"&gt;# 交换基因&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kk&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
        &lt;span class="n"&gt;next_gen_rands1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;next_gen_rands2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="c1"&gt;# 忽略修复重复基因&lt;/span&gt;

      &lt;span class="c1"&gt;#新种群&lt;/span&gt;
      &lt;span class="n"&gt;next_gen_rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_gen_rands1&lt;/span&gt;
      &lt;span class="n"&gt;next_gen_rands_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_gen_rands2&lt;/span&gt;
      &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;next_gen_rands_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;#突变&lt;/span&gt;
      &lt;span class="n"&gt;pm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pm&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="vg"&gt;$pm&lt;/span&gt;
        &lt;span class="c1"&gt;#发生突变&lt;/span&gt;
        &lt;span class="c1"&gt;#突变点&lt;/span&gt;
        &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;new_rand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lb&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_rand&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;rands_arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_gen_rands_arr&lt;/span&gt;

    &lt;span class="n"&gt;rands_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rands&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;curr_p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="n"&gt;rands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;curr_p&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;curr_p&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="vg"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rands&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;ga&lt;/span&gt; &lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1300&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="vg"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;</description>
      <author>rasefon</author>
      <pubDate>Sat, 10 Jan 2015 00:18:12 +0800</pubDate>
      <link>https://ruby-china.org/topics/23651</link>
      <guid>https://ruby-china.org/topics/23651</guid>
    </item>
    <item>
      <title>Rails 集成 ActiveX</title>
      <description>&lt;p&gt;各位有没有试过用 rails 做带 ActiveX 控件的 server？不知道可不可行。&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Sun, 04 Jan 2015 10:51:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/23525</link>
      <guid>https://ruby-china.org/topics/23525</guid>
    </item>
    <item>
      <title>变态版五子棋。</title>
      <description>&lt;p&gt;最近写了个变态版五子棋。规则如下：
每人走 2 步，两步不能走在相邻的位置，即第二步不能走在第一步周围 8 个格子。&lt;/p&gt;

&lt;p&gt;前端用 html5 canvas
后端 ror
ai 用 cpp，socket 和 ror 通信。&lt;/p&gt;

&lt;p&gt;代码：
&lt;a href="https://github.com/rasefon/gobang_server" rel="nofollow" target="_blank"&gt;https://github.com/rasefon/gobang_server&lt;/a&gt;
&lt;a href="https://github.com/rasefon/gobang" rel="nofollow" target="_blank"&gt;https://github.com/rasefon/gobang&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/2c4f384f57a02f2b3417b01987b14451.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Sun, 07 Dec 2014 11:01:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/23063</link>
      <guid>https://ruby-china.org/topics/23063</guid>
    </item>
    <item>
      <title>The unix-haters handbook</title>
      <description>&lt;p&gt;&lt;a href="http://web.mit.edu/~simsong/www/ugh.pdf" rel="nofollow" target="_blank"&gt;http://web.mit.edu/~simsong/www/ugh.pdf&lt;/a&gt;
挺有意的。&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Fri, 25 Jul 2014 12:46:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/20670</link>
      <guid>https://ruby-china.org/topics/20670</guid>
    </item>
    <item>
      <title>一个简易的读取文件字符的系统，可用于词法分析。</title>
      <description>&lt;p&gt;这里没有 C 语言节点，所以就放在 Go 下面了。（能加一个么？）
这个输入系统，主要是用于词法分析的读取，自己写一个是基于效率方面的考量，通常用流实现的的文件读取库，到了应用层，都会额外多一次字符拷贝的动作，比如 fopen 就会要求提供一个 char[] buf 作为输入参数，自己写的就可以避免这种浪费。
具体代码在这里：&lt;a href="https://github.com/rasefon/RWInputSys" rel="nofollow" target="_blank"&gt;https://github.com/rasefon/RWInputSys&lt;/a&gt;
另外程序还没仔细测试过，之后应该会把测试加上。&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Tue, 03 Jun 2014 13:47:12 +0800</pubDate>
      <link>https://ruby-china.org/topics/19696</link>
      <guid>https://ruby-china.org/topics/19696</guid>
    </item>
    <item>
      <title>如何自制正则表达式引擎 (一)</title>
      <description>&lt;p&gt;昨天发了个贴，讲 LL 预测分析表的自动生成（&lt;a href="http://ruby-china.org/topics/19459" rel="nofollow" target="_blank"&gt;http://ruby-china.org/topics/19459&lt;/a&gt;），正好借机说一说如何自己做一个正则表达式的引擎。
打算分以下几个篇章，理论结合实践，我会一步步用 ruby 来实现一个引擎：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;LL 预测分析表的生成&lt;/li&gt;
&lt;li&gt;NFA 构造&lt;/li&gt;
&lt;li&gt;NFA 转 DFA&lt;/li&gt;
&lt;li&gt;DFA 最小化&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;今天把 LL 预测分析表完成了，代码放在：&lt;a href="https://github.com/rasefon/LLTableGenerator" rel="nofollow" target="_blank"&gt;https://github.com/rasefon/LLTableGenerator&lt;/a&gt;
由于时间太晚要睡觉了，我会争取这两天把第一篇完成。&lt;/p&gt;
&lt;h2 id="分割线，今天先更新一部分，具体算法的详细解析放在下回。"&gt;分割线，今天先更新一部分，具体算法的详细解析放在下回。&lt;/h2&gt;
&lt;p&gt;正则表达式作为字符串解析利器，本身可以就是一个由 context free 语法构成的语法集合。本质上只有三条规则：连接（e1 e2），重复（e*），选择（e1|e2)。例如 [a-z]，\s，\t等。下面作为示例，给出一个简化的正则表达式的 BNF 范式：
Rule: Expr 
| ^Expr
| Expr$
Expr: Expr '|' Cat_Expr
| Cat_Expr
Cat_Expr:  Cat_Expr Factor
| Factor
Factor: Term *
| Term +
| Term ?
| Term
Term: [ String ]
| [^ String ]
| .  | Char  | '(' Expr ')'
String: #Set of ascii characters
Char: #Single ascii character
由此文法，即可创建基于 NFA 的表示正则表达式的内存模型，构造 NFA 的算法用 Thompson。
构造之前，先了解下如何解析上述文法，因为正则表达式通常都比较短，所以一般用递归下降的算法即可。所谓递归下降，即如下这种算法：
例如，有文法
T: F T1
T1: '*' F T1
| epsilon
F: '(' T ')'
| id
则递归下降算法形如如下所示：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;next_token&lt;/span&gt;
   &lt;span class="c1"&gt;# Get next token from lexema buffer.&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;T&lt;/span&gt;
   &lt;span class="no"&gt;F&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="no"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="c1"&gt;#do something&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;F&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;next_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;")"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;next_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="c1"&gt;# do something&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
         &lt;span class="c1"&gt;# Error!&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;next_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="c1"&gt;# do something&lt;/span&gt;
   &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="c1"&gt;# Error!&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;T1&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;next_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="no"&gt;F&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="no"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="c1"&gt;# do something&lt;/span&gt;
   &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="c1"&gt;# Error!&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Start parsing...&lt;/span&gt;
&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在"do something'处可以插入用于构造 NFA 模型的代码。注意此处文法都是右递归的，左递归的文法无法用于自顶向下的文法解析算法，所以要先把文法从左递归转成右递归。
递归下降算法优点是简单，缺点是有回溯，效率低，且不容易扩展变更。所以我们可以先做一个 LL 语法解析器的自动生成器，就像 yacc 那样（基于 LALR 算法）。这样生成一个 LL 预测分析表以后，我们就可以进行无回溯的文法解析。下面说下如何构造 LL 预测分析表.
构造预测表，首先我们需要读取语法描述文件，语法描述文件是我自定义的，这里给出一个例子：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;``&lt;/span&gt;
token: tPlus, tMul, tLp, tRp, tEnd
token: tId
&lt;span class="c"&gt;# nil is predefined keyword.&lt;/span&gt;
&lt;span class="sb"&gt;``&lt;/span&gt;
&lt;span class="nv"&gt;$Start&lt;/span&gt;: E
E:    T,E1
E1:   tPlus,T,E1
E1:   nil
T:    F,T1
T1:   tMul,F,T1
T1:   nil
F:    F1
F1:   tLp,E,tRp
F1:   tId
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;''如同 yacc 里的%%
第一部分是定义 token 集，第二部分是定义文法。在此给出解析此文件，并生成临时文法规则数据结构的简单算法：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vg"&gt;$start_lside_rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="vg"&gt;$token_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$gram_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$first_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$follow_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="c1"&gt;# For ll table construction&lt;/span&gt;
&lt;span class="vg"&gt;$nonterm_token_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;# [E, F, T, ...]&lt;/span&gt;
&lt;span class="vg"&gt;$single_gram_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;# [{T-&amp;gt;[E,tRp]}, ...]&lt;/span&gt;
&lt;span class="vg"&gt;$input_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="vg"&gt;$ll_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;construct_table_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
   &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="n"&gt;token_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
   &lt;span class="n"&gt;rule_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
   &lt;span class="c1"&gt;# temporarily record left side tokens and right tokens as string.&lt;/span&gt;
   &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# skip comment&lt;/span&gt;
      &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"#"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="c1"&gt;# Start token define phase.&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"``"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;token_def_phase&lt;/span&gt;
            &lt;span class="n"&gt;token_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;token_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
            &lt;span class="n"&gt;rule_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;next&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;token_def_phase&lt;/span&gt;
         &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;rule_def_phase&lt;/span&gt;
         &lt;span class="n"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"$Start"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="vg"&gt;$start_lside_rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
               &lt;span class="c1"&gt;# merge right side rule&lt;/span&gt;
               &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
               &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="vg"&gt;$input_tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个方法会生成一个全局的$token_list 集合，一个$input_tokens 的所有可能的输入 tokens 数组（即 token_list 加上终结符"$"），一个表示语法的$gram_list.&lt;/p&gt;

&lt;p&gt;LL 预测分析表需要两个集合，一个是 First 集合，一个是 Follow 集合，首先给出构造这两者的算法，然后再说明这两个集合的用处，以及具体的构造步骤：
First 集合：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;construct_first_set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="c1"&gt;#first to add all the terminal and 'nil' into the FIRST set.&lt;/span&gt;
   &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
            &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="c1"&gt;# loop computing first set until no new item is added.&lt;/span&gt;
   &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
   &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
      &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="c1"&gt;# If the first item of the rhs token is terminal or 'nil', just skip it because the token had already been&lt;/span&gt;
            &lt;span class="c1"&gt;# added in previous loop.&lt;/span&gt;
            &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs_term&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
               &lt;span class="c1"&gt;# If 'nil' is contained in FIRST set of rhs_term, skip to the next term.&lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs_term&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                  &lt;span class="k"&gt;next&lt;/span&gt;
               &lt;span class="k"&gt;else&lt;/span&gt;
                  &lt;span class="c1"&gt;# merge the FIRST SET of rhs token with the lhs if necessary.&lt;/span&gt;
                  &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs_term&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                     &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;break&lt;/span&gt;
               &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="c1"&gt;# check if all the rhs tokens produce nil, if so add nil to the lhs FIRST set.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
               &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First 集合的结果会放在全局变量$first_set 中，同样的对于 follow set，构造算法如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;construct_follow_set&lt;/span&gt;
   &lt;span class="c1"&gt;# Initialize FOLLOW set and add '$' into the FOLLOW set of start tokens.&lt;/span&gt;
   &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_key&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
      &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$start_lside_rule&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;

   &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
   &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
      &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
               &lt;span class="c1"&gt;# skip the nil and terminal token.&lt;/span&gt;
               &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;'nil'&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

               &lt;span class="c1"&gt;# case 1, the current rhs term is the last one. &lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; 
                  &lt;span class="c1"&gt;# Union the FOLLOW set of the rhs into the current rhs term.&lt;/span&gt;
                  &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                     &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                        &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
               &lt;span class="k"&gt;else&lt;/span&gt;
                  &lt;span class="c1"&gt;# First union the FIRST set of the follow rhs token into the current rhs token.&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                           &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                           &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="k"&gt;else&lt;/span&gt;
                        &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
                              &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                              &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                           &lt;span class="k"&gt;end&lt;/span&gt;
                        &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="c1"&gt;# If the follow rhs tokens produces a 'nil' chain, union the FOLLOW set of lhs into the current rhs token.&lt;/span&gt;
                  &lt;span class="n"&gt;all_nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                  &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="c1"&gt;# If there is any terminal, break.&lt;/span&gt;
                     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="n"&gt;all_nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;

                     &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;all_nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;all_nil&lt;/span&gt;
                     &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                        &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                           &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                           &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
               &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果放在$follow_set.&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Thu, 22 May 2014 23:02:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/19483</link>
      <guid>https://ruby-china.org/topics/19483</guid>
    </item>
    <item>
      <title>LL (1) 预测分析表生成器。</title>
      <description>&lt;p&gt;最近在看编译器的前段，大部分人都是用现有工具去实现，例如经典的 Lex/yacc。很少有人会从头自己去手写 parser，或者做个 parser 解析器。看理论不实践，总觉得不踏实，所以我找了些现有的词法分析生成器源码看了看，里面对正则表达式解析器本身的处理，多数都是用了最直观的右递归递归下降算法，也就是说是有回溯的算法。故此我便想用脚本，读取一些简单的自定义语法文本，来自动生成 LL 预测分析表，现在已经把 First 集合和 Follow 集合计算完毕，过两天把分析表输出成 c 语言的头文件就算大功告成。&lt;/p&gt;

&lt;p&gt;Repo 地址：&lt;a href="https://github.com/rasefon/LLTableGenerator" rel="nofollow" target="_blank"&gt;https://github.com/rasefon/LLTableGenerator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;简单的文法文本如下：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;``&lt;/span&gt;
token: tPlus, tMul, tLp, tRp, tEnd
token: tId
&lt;span class="c"&gt;# nil is predefined keyword.&lt;/span&gt;
&lt;span class="sb"&gt;``&lt;/span&gt;
&lt;span class="nv"&gt;$Start&lt;/span&gt;: E
E:    T,E1
E1:   tPlus,T,E1
E1:   nil
T:    F,T1
T1:   tMul,F,T1
T1:   nil
F:    F1
F1:   tLp,E,tRp
F1:   tId
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;脚本用的是 ruby，代码如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'set'&lt;/span&gt;

&lt;span class="c1"&gt;# 'nil' and '$' are predefined terminal token, 'nil' means empty action and '$' is the end flag of parsing.&lt;/span&gt;

&lt;span class="vg"&gt;$start_lside_rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="vg"&gt;$token_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$gram_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$first_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$follow_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;construct_table_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
   &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chomp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="n"&gt;token_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
   &lt;span class="n"&gt;rule_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
   &lt;span class="c1"&gt;# temporarily record left side tokens and right tokens as string.&lt;/span&gt;
   &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# skip comment&lt;/span&gt;
      &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"#"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="c1"&gt;# Start token define phase.&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"``"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;token_def_phase&lt;/span&gt;
            &lt;span class="n"&gt;token_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;token_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
            &lt;span class="n"&gt;rule_def_phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;next&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;token_def_phase&lt;/span&gt;
         &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;rule_def_phase&lt;/span&gt;
         &lt;span class="n"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"$Start"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="vg"&gt;$start_lside_rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;rhs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
               &lt;span class="c1"&gt;# merge right side rule&lt;/span&gt;
               &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
               &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;construct_first_set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="c1"&gt;#first to add all the terminal and 'nil' into the FIRST set.&lt;/span&gt;
   &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has_key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
            &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="c1"&gt;# loop computing first set until no new item is added.&lt;/span&gt;
   &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
   &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
      &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="c1"&gt;# If the first item of the rhs token is terminal or 'nil', just skip it because the token had already been&lt;/span&gt;
            &lt;span class="c1"&gt;# added in previous loop.&lt;/span&gt;
            &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs_term&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
               &lt;span class="c1"&gt;# If 'nil' is contained in FIRST set of rhs_term, skip to the next term.&lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs_term&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                  &lt;span class="k"&gt;next&lt;/span&gt;
               &lt;span class="k"&gt;else&lt;/span&gt;
                  &lt;span class="c1"&gt;# merge the FIRST SET of rhs token with the lhs if necessary.&lt;/span&gt;
                  &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs_term&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                     &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;break&lt;/span&gt;
               &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="c1"&gt;# check if all the rhs tokens produce nil, if so add nil to the lhs FIRST set.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;
               &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;construct_follow_set&lt;/span&gt;
   &lt;span class="c1"&gt;# Initialize FOLLOW set and add '$' into the FOLLOW set of start tokens.&lt;/span&gt;
   &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_key&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
      &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lhs&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$start_lside_rule&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;

   &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
   &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
      &lt;span class="vg"&gt;$gram_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
         &lt;span class="n"&gt;rhs_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
               &lt;span class="c1"&gt;# skip the nil and terminal token.&lt;/span&gt;
               &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;'nil'&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

               &lt;span class="c1"&gt;# case 1, the current rhs term is the last one. &lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; 
                  &lt;span class="c1"&gt;# Union the FOLLOW set of the rhs into the current rhs term.&lt;/span&gt;
                  &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                     &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                        &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
               &lt;span class="k"&gt;else&lt;/span&gt;
                  &lt;span class="c1"&gt;# First union the FIRST set of the follow rhs token into the current rhs token.&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                           &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                           &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="k"&gt;else&lt;/span&gt;
                        &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
                              &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                              &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                           &lt;span class="k"&gt;end&lt;/span&gt;
                        &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="c1"&gt;# If the follow rhs tokens produces a 'nil' chain, union the FOLLOW set of lhs into the current rhs token.&lt;/span&gt;
                  &lt;span class="n"&gt;all_nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                  &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="c1"&gt;# If there is any terminal, break.&lt;/span&gt;
                     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"nil"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="vg"&gt;$token_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                        &lt;span class="n"&gt;all_nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;

                     &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;all_nil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;all_nil&lt;/span&gt;
                     &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lhs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
                        &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                           &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
                           &lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rhs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;end&lt;/span&gt;
                     &lt;span class="k"&gt;end&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
               &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
         &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;construct_table_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;construct_first_set&lt;/span&gt;
&lt;span class="n"&gt;construct_follow_set&lt;/span&gt;

&lt;span class="c1"&gt;#puts $start_lside_rule&lt;/span&gt;
&lt;span class="c1"&gt;#puts "" &lt;/span&gt;
&lt;span class="c1"&gt;#puts $gram_list &lt;/span&gt;
&lt;span class="c1"&gt;#puts ""&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"FIRST SET: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vg"&gt;$first_set&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"FOLLOW SET: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vg"&gt;$follow_set&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>rasefon</author>
      <pubDate>Wed, 21 May 2014 21:42:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/19459</link>
      <guid>https://ruby-china.org/topics/19459</guid>
    </item>
    <item>
      <title>恒大威武！！！</title>
      <description>&lt;p&gt;！！！&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Sat, 09 Nov 2013 21:59:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/15424</link>
      <guid>https://ruby-china.org/topics/15424</guid>
    </item>
    <item>
      <title>傅立叶变化的完美解释。</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/3ffb1959a473f0d143dac5fad552d04c.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Thu, 31 Oct 2013 16:42:48 +0800</pubDate>
      <link>https://ruby-china.org/topics/15190</link>
      <guid>https://ruby-china.org/topics/15190</guid>
    </item>
    <item>
      <title>相似图比较算法。</title>
      <description>&lt;p&gt;最近要人肉比较图片，太痛苦，不能逐像素点比较，这样容错率太低，看了篇网上的文章，照着实现了一下，感觉还不错，代码放在这里：
&lt;a href="https://gist.github.com/rasefon/7227972" rel="nofollow" target="_blank"&gt;https://gist.github.com/rasefon/7227972&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;算法介绍：
&lt;a href="http://www.labbookpages.co.uk/software/imgProc/otsuThreshold.html" rel="nofollow" target="_blank"&gt;http://www.labbookpages.co.uk/software/imgProc/otsuThreshold.html&lt;/a&gt;&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Wed, 30 Oct 2013 14:31:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/15155</link>
      <guid>https://ruby-china.org/topics/15155</guid>
    </item>
    <item>
      <title>关于 C++，关于 gc 的一些东西</title>
      <description>&lt;p&gt;昨天没事又翻出了 Coders at Work 这本书看看，看到 Ken Thompson 对 C++ 和 GC 的评论，觉得很有意思，也很赞同，关于 C++ 的原文：
Seibel: You were at AT&amp;amp;T with Bjarne Stroustrup. Were you involved at
all in the development of C++?&lt;/p&gt;

&lt;p&gt;Thompson: I’m gonna get in trouble.&lt;/p&gt;

&lt;p&gt;Seibel: That’s fine.&lt;/p&gt;

&lt;p&gt;Thompson: I would try out the language as it was being developed and
make comments on it. It was part of the work atmosphere there. And you’d
write something and then the next day it wouldn’t work because the
language changed. It was very unstable for a very long period of time. At
some point I said, no, no more.
In an interview I said exactly that, that I didn’t use it just because it wouldn’t
stay still for two days in a row. When Stroustrup read the interview he
came screaming into my room about how I was undermining him and what I
said mattered and I said it was a bad language. I never said it was a bad
language. On and on and on. Since then I kind of avoid that kind of stuff.&lt;/p&gt;

&lt;p&gt;Seibel: Can you say now whether you think it’s a good or bad language?
Thompson: It certainly has its good points. But by and large I think it’s a
bad language. It does a lot of things half well and it’s just a garbage heap of
ideas that are mutually exclusive. Everybody I know, whether it’s personal
or corporate, selects a subset and these subsets are different. So it’s not a
good language to transport an algorithm—to say, “I wrote it; here, take it.”
It’s way too big, way too complex. And it’s obviously built by a committee.
Stroustrup campaigned for years and years and years, way beyond any sort
of technical contributions he made to the language, to get it adopted and
used. And he sort of ran all the standards committees with a whip and a
chair. And he said “no” to no one. He put every feature in that language
that ever existed. It wasn’t cleanly designed—it was just the union of
everything that came along. And I think it suffered drastically from that.&lt;/p&gt;

&lt;p&gt;Seibel: Do you think that was just because he likes all ideas or was it a way
to get the language adopted, by giving everyone what they wanted?&lt;/p&gt;

&lt;p&gt;Thompson: I think it’s more the latter than the former.
关于 GC 的原文：
Seibel: On a somewhat related note, what about garbage collection? With
Java, GC has finally made it into the mainstream. As Dennis Ritchie once
said, C is actively hostile to garbage collection. Is it good that folks are
moving toward garbage-collected languages—is it a technology that
deserves to finally be in mainstream use?&lt;/p&gt;

&lt;p&gt;Thompson: I don’t know. I’m schizophrenic on the subject. If you’re
writing an operating system or a C compiler or something that’s used by
lots and lots of people, I think garbage collection is a mistake, almost. It’s a
cheat for you where you can do it by hand and do it better—much better.
What you’re doing is your sloughing your task, your job, making it slower
for your users. So I think it’s a mistake in an operating system. It almost just
doesn’t fit in an operating system. But if you are writing a hack program to
do a job, get an answer and then throw the program away, it’s beautiful. It
takes a layer of stuff you don’t want to think about, at a cost you can afford,
because computers are so fast, and it’s nothing but a win-win-win position.
So I’m really schizophrenic on this subject.
Part of the problem is there are different garbage-collection algorithms and
they have different properties—massively different properties. So you’re
writing some really general-purpose thing like an operating system—if
you’re going to write it in a language that garbage-collects underneath, you
don’t even have the choice of the algorithm for the operating systems.
Suppose that you just can’t stand big real-time gaps and you have a garbage
collector that runs up to some threshold and then does mark and sweep.
You’re screwed before you start.
So if you’re doing some general-purpose task that you don’t know who your
real users are, you just can’t do that. Plus, garbage collection fights cache
coherency massively. And there’s no garbage-collection algorithm that is
right for all machines. There are machines where you can speed it up by a
factor of five or more by messing around with the cache. They should be
tied to the machine much more than they are. Usually they treat them as
separate algorithms that have nothing to do with machines, but the cache
coherency is very important for garbage-collection algorithms.&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Mon, 28 Oct 2013 09:50:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/15080</link>
      <guid>https://ruby-china.org/topics/15080</guid>
    </item>
    <item>
      <title>分享一首非常赞的歌和歌词。</title>
      <description>&lt;p&gt;Stevie Wonder 的 Black man，歌词太赞了！
First man to die
For the flag we now hold high [Crispus Attucks]
Was a black man&lt;/p&gt;

&lt;p&gt;The ground were we stand
With the flag held in our hand
Was first the red man's&lt;/p&gt;

&lt;p&gt;Guide of a ship
On the first Columbus trip [Pedro Alonzo Nino]
Was a brown man&lt;/p&gt;

&lt;p&gt;The railroads for trains
Came on tracking that was laid
By the yellow man&lt;/p&gt;

&lt;p&gt;We pledge allegiance
All our lives
To the magic colors
Red, blue and white
But we all must be given
The liberty that we defend
For with justice not for all men
History will repeat again
It's time we learned
This World Was Made For All Men&lt;/p&gt;

&lt;p&gt;Heart surgery
Was first done successfully
By a black man [Dr Daniel Hale Williams]&lt;/p&gt;

&lt;p&gt;Friendly man who died
But helped the pilgrims to survive [Squanto]
Was a red man&lt;/p&gt;

&lt;p&gt;Farm workers rights
Were lifted to new heights [Caesar Chavez]
By a brown man&lt;/p&gt;

&lt;p&gt;Incandescent light
Was invented to give sight [Thomas Edison]
By the white man&lt;/p&gt;

&lt;p&gt;We pledge allegiance
All our lives
To the magic colors
Red, blue and white
But we all must be given
The liberty that we defend
For with justice not for all men
History will repeat again
It's time we learned
This World Was Made For All Men&lt;/p&gt;

&lt;p&gt;Hear me out...&lt;/p&gt;

&lt;p&gt;Now I know the birthday of a nation
Is a time when a country celebrates
But as your hand touches your heart
Remember we all played a part in America
To help that banner wave&lt;/p&gt;

&lt;p&gt;First clock to be made
In America was created
By a black man [Benjamin Banneker]&lt;/p&gt;

&lt;p&gt;Scout who used no chart
Helped lead Lewis and Clark
Was a red man [Sacagawea]&lt;/p&gt;

&lt;p&gt;Use of martial arts
In our country got its start
By a yellow man&lt;/p&gt;

&lt;p&gt;And the leader with a pen
Signed his name to free all men
Was a white man [Abraham Lincoln]&lt;/p&gt;

&lt;p&gt;We pledge allegiance
All our lives
To the magic colors
Red, blue and white
But we all must be given
The liberty that we defend
For with justice not for all men
History will repeat again
It's time we learned
This World Was Made For All Men&lt;/p&gt;

&lt;p&gt;This world was made for all men
This world was made for all men
This world was made for all men
God saved His world for all men
All people
All babies
All children
All colors
All races
This world's for you
and me
This world
My world
Your world
Everybody's world
This world
Their world
Our world
This world was made for all men&lt;/p&gt;

&lt;p&gt;Hear me out...&lt;/p&gt;

&lt;p&gt;Who was the first man to set foot on the North Pole?
Matthew Henson - a black man&lt;/p&gt;

&lt;p&gt;Who was the first american to show the Pilgrims at Plymouth the secrets of survival in the new world?
Squanto - a red man&lt;/p&gt;

&lt;p&gt;Who was the soldier of Company G who won high honors for his courage and heroism in World War 1?
Sing Kee - a yellow man&lt;/p&gt;

&lt;p&gt;Who was the leader of united farm workers and helped farm workers maintain dignity and respect?
Caesar Chavez - a brown man&lt;/p&gt;

&lt;p&gt;Who was the founder of blood plasma and the director of the Red Cross blood bank?
Dr. Charles Drew - a black man&lt;/p&gt;

&lt;p&gt;Who was the first American heroine who aided the Lewis and Clark expedition?
Sacajewa - a red woman&lt;/p&gt;

&lt;p&gt;Who was the famous educator and semanticist who made outstanding contributions to education in America?
Hayakawa - a yellow man&lt;/p&gt;

&lt;p&gt;Who invented the world's first stop light and the gas mask?
Garrett Morgan - a black man&lt;/p&gt;

&lt;p&gt;Who was the American surgeon who was one of the founders of neurosurgery?
Harvey Williams Cushing - a white man&lt;/p&gt;

&lt;p&gt;Who was the man who helped design the nation's capitol, made the first clock to give time in America and wrote the first almanac?
Benjamin Banneker - a black man&lt;/p&gt;

&lt;p&gt;Who was the legendary hero who helped establish the League of Iroquois?
Hiawatha - a red man&lt;/p&gt;

&lt;p&gt;Who was the leader of the first microbiotic center in America?
Micho Kushi - a yellow man&lt;/p&gt;

&lt;p&gt;Who was the founder of the city of Chicago in 1772?
Jean Baptiste - a black man&lt;/p&gt;

&lt;p&gt;Who was one of the organizers of the American Indian Movement?
Denis Banks - a red man&lt;/p&gt;

&lt;p&gt;Who was the Jewish financier who raised founds to sponsor Cristopher Columbus' voyage to America?
Lewis D. Santangel - a white man&lt;/p&gt;

&lt;p&gt;Who was the woman who led countless slaves to freedom on the underground rairoad?
Harriet Tubman - a black woman&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Wed, 16 Oct 2013 22:20:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/14802</link>
      <guid>https://ruby-china.org/topics/14802</guid>
    </item>
    <item>
      <title>发个很好的 Ruby VM 的学习资料</title>
      <description>&lt;p&gt;英文版：
&lt;a href="http://edwinmeyer.com/Integrated_RHG.html" rel="nofollow" target="_blank"&gt;http://edwinmeyer.com/Integrated_RHG.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;日文版：
&lt;a href="http://i.loveruby.net/ja/rhg/book/" rel="nofollow" target="_blank"&gt;http://i.loveruby.net/ja/rhg/book/&lt;/a&gt;&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Thu, 29 Aug 2013 13:22:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/13721</link>
      <guid>https://ruby-china.org/topics/13721</guid>
    </item>
    <item>
      <title>无意中找了 ruby 语法的伪 BNF 范式，发出来给大家参考一下。</title>
      <description>&lt;p&gt;Pseudo BNF Syntax of Ruby&lt;/p&gt;

&lt;p&gt;Here is the syntax of Ruby in pseudo BNF. For more detail, see parse.y in Ruby distribution.&lt;/p&gt;

&lt;p&gt;PROGRAM     : COMPSTMT&lt;/p&gt;

&lt;p&gt;COMPSTMT    : STMT (TERM EXPR)* [TERM]&lt;/p&gt;

&lt;p&gt;STMT        : CALL do [&lt;code&gt;|' [BLOCK_VAR]&lt;/code&gt;|'] COMPSTMT end
                | undef FNAME
        | alias FNAME FNAME
        | STMT if EXPR
        | STMT while EXPR
        | STMT unless EXPR
        | STMT until EXPR
                | &lt;code&gt;BEGIN'&lt;/code&gt;{' COMPSTMT &lt;code&gt;}'
                |&lt;/code&gt;END' &lt;code&gt;{' COMPSTMT&lt;/code&gt;}'
                | LHS &lt;code&gt;=' COMMAND [do [&lt;/code&gt;|' [BLOCK_VAR] `|'] COMPSTMT end]
        | EXPR&lt;/p&gt;

&lt;p&gt;EXPR        : MLHS &lt;code&gt;=' MRHS
        | return CALL_ARGS
        | yield CALL_ARGS
        | EXPR and EXPR
        | EXPR or EXPR
        | not EXPR
        | COMMAND
        |&lt;/code&gt;!' COMMAND
        | ARG&lt;/p&gt;

&lt;p&gt;CALL        : FUNCTION
                | COMMAND&lt;/p&gt;

&lt;p&gt;COMMAND     : OPERATION CALL_ARGS
        | PRIMARY &lt;code&gt;.' OPERATION CALL_ARGS
        | PRIMARY&lt;/code&gt;::' OPERATION CALL_ARGS
        | super CALL_ARGS&lt;/p&gt;

&lt;p&gt;FUNCTION        : OPERATION [&lt;code&gt;(' [CALL_ARGS]&lt;/code&gt;)']
        | PRIMARY &lt;code&gt;.' OPERATION&lt;/code&gt;(' [CALL_ARGS] &lt;code&gt;)'
        | PRIMARY&lt;/code&gt;::' OPERATION &lt;code&gt;(' [CALL_ARGS]&lt;/code&gt;)'
        | PRIMARY &lt;code&gt;.' OPERATION
        | PRIMARY&lt;/code&gt;::' OPERATION
        | super &lt;code&gt;(' [CALL_ARGS]&lt;/code&gt;)'
        | super&lt;/p&gt;

&lt;p&gt;ARG     : LHS &lt;code&gt;=' ARG
        | LHS OP_ASGN ARG
        | ARG&lt;/code&gt;..' ARG
        | ARG &lt;code&gt;...' ARG
        | ARG&lt;/code&gt;+' ARG
        | ARG &lt;code&gt;-' ARG
        | ARG&lt;/code&gt;&lt;em&gt;' ARG
        | ARG &lt;code&gt;/' ARG
        | ARG&lt;/code&gt;%' ARG
        | ARG `&lt;/em&gt;*' ARG
        | &lt;code&gt;+' ARG
        |&lt;/code&gt;-' ARG
        | ARG &lt;code&gt;|' ARG
        | ARG&lt;/code&gt;^' ARG
        | ARG &lt;code&gt;&amp;amp;' ARG
        | ARG&lt;/code&gt;&amp;lt;=&amp;gt;' ARG
        | ARG &lt;code&gt;&amp;gt;' ARG
        | ARG&lt;/code&gt;&amp;gt;=' ARG
        | ARG &lt;code&gt;&amp;lt;' ARG
        | ARG&lt;/code&gt;&amp;lt;=' ARG
        | ARG &lt;code&gt;==' ARG
        | ARG&lt;/code&gt;===' ARG
        | ARG &lt;code&gt;!=' ARG
        | ARG&lt;/code&gt;=~' ARG
        | ARG &lt;code&gt;!~' ARG
        |&lt;/code&gt;!' ARG
        | &lt;code&gt;~' ARG
        | ARG&lt;/code&gt;&amp;lt;&amp;lt;' ARG
        | ARG &lt;code&gt;&amp;gt;&amp;gt;' ARG
        | ARG&lt;/code&gt;&amp;amp;&amp;amp;' ARG
        | ARG `||' ARG
        | defined? ARG
        | PRIMARY&lt;/p&gt;

&lt;p&gt;PRIMARY     : &lt;code&gt;(' COMPSTMT&lt;/code&gt;)'
        | LITERAL
        | VARIABLE
        | PRIMARY &lt;code&gt;::' IDENTIFIER
        |&lt;/code&gt;::' IDENTIFIER
        | PRIMARY &lt;code&gt;[' [ARGS]&lt;/code&gt;]'
        | &lt;code&gt;[' [ARGS [&lt;/code&gt;,']] &lt;code&gt;]'
        |&lt;/code&gt;{' [(ARGS|ASSOCS) [&lt;code&gt;,']]&lt;/code&gt;}'
        | return [&lt;code&gt;(' [CALL_ARGS]&lt;/code&gt;)']
        | yield [&lt;code&gt;(' [CALL_ARGS]&lt;/code&gt;)']
        | defined? &lt;code&gt;(' ARG&lt;/code&gt;)'
                | FUNCTION
        | FUNCTION &lt;code&gt;{' [&lt;/code&gt;|' [BLOCK_VAR] &lt;code&gt;|'] COMPSTMT&lt;/code&gt;}'
        | if EXPR THEN
          COMPSTMT
          (elsif EXPR THEN COMPSTMT)*
          [else COMPSTMT]
          end
        | unless EXPR THEN
          COMPSTMT
          [else COMPSTMT]
          end
        | while EXPR DO COMPSTMT end
        | until EXPR DO COMPSTMT end
        | case COMPSTMT
          (when WHEN_ARGS THEN COMPSTMT)+
          [else COMPSTMT]
          end
        | for BLOCK_VAR in EXPR DO
          COMPSTMT
          end
        | begin
          COMPSTMT
          [rescue [ARGS] DO COMPSTMT]+
          [else COMPSTMT]
          [ensure COMPSTMT]
          end
        | class IDENTIFIER [&lt;code&gt;&amp;lt;' IDENTIFIER]
          COMPSTMT
          end
        | module IDENTIFIER
          COMPSTMT
          end
        | def FNAME ARGDECL
          COMPSTMT
          end
        | def SINGLETON (&lt;/code&gt;.'|`::') FNAME ARGDECL
          COMPSTMT
          end&lt;/p&gt;

&lt;p&gt;WHEN_ARGS   : ARGS [&lt;code&gt;,'&lt;/code&gt;&lt;em&gt;' ARG]
        | `&lt;/em&gt;' ARG&lt;/p&gt;

&lt;p&gt;THEN        : TERM
        | then
        | TERM then&lt;/p&gt;

&lt;p&gt;DO      : TERM
        | do
        | TERM do&lt;/p&gt;

&lt;p&gt;BLOCK_VAR   : LHS
        | MLHS&lt;/p&gt;

&lt;p&gt;MLHS        : MLHS_ITEM &lt;code&gt;,' [MLHS_ITEM (&lt;/code&gt;,' MLHS_ITEM)&lt;em&gt;] [`&lt;/em&gt;' [LHS]]
                | `*' LHS&lt;/p&gt;

&lt;p&gt;MLHS_ITEM   : LHS
        | '(' MLHS ')'&lt;/p&gt;

&lt;p&gt;LHS     : VARIABLE
        | PRIMARY &lt;code&gt;[' [ARGS]&lt;/code&gt;]'
        | PRIMARY `.' IDENTIFIER&lt;/p&gt;

&lt;p&gt;MRHS        : ARGS [&lt;code&gt;,'&lt;/code&gt;&lt;em&gt;' ARG]
        | `&lt;/em&gt;' ARG&lt;/p&gt;

&lt;p&gt;CALL_ARGS   : ARGS
        | ARGS [&lt;code&gt;,' ASSOCS] [&lt;/code&gt;,' &lt;code&gt;*' ARG] [&lt;/code&gt;,' &lt;code&gt;&amp;amp;' ARG]
        | ASSOCS [&lt;/code&gt;,' &lt;code&gt;*' ARG] [&lt;/code&gt;,' &lt;code&gt;&amp;amp;' ARG]
        |&lt;/code&gt;*' ARG [&lt;code&gt;,'&lt;/code&gt;&amp;amp;' ARG]
        | `&amp;amp;' ARG
        | COMMAND&lt;/p&gt;

&lt;p&gt;ARGS        : ARG (`,' ARG)*&lt;/p&gt;

&lt;p&gt;ARGDECL     : &lt;code&gt;(' ARGLIST&lt;/code&gt;)'
        | ARGLIST TERM&lt;/p&gt;

&lt;p&gt;ARGLIST     : IDENTIFIER(&lt;code&gt;,'IDENTIFIER)*[&lt;/code&gt;,'&lt;code&gt;*'[IDENTIFIER]][&lt;/code&gt;,'&lt;code&gt;&amp;amp;'IDENTIFIER]
        |&lt;/code&gt;*'IDENTIFIER[&lt;code&gt;,'&lt;/code&gt;&amp;amp;'IDENTIFIER]
        | [`&amp;amp;'IDENTIFIER]&lt;/p&gt;

&lt;p&gt;SINGLETON   : VARIABLE
        | &lt;code&gt;(' EXPR&lt;/code&gt;)'&lt;/p&gt;

&lt;p&gt;ASSOCS      : ASSOC (`,' ASSOC)*&lt;/p&gt;

&lt;p&gt;ASSOC       : ARG `=&amp;gt;' ARG&lt;/p&gt;

&lt;p&gt;VARIABLE    : VARNAME
        | nil
        | self&lt;/p&gt;

&lt;p&gt;LITERAL     : numeric
        | SYMBOL
        | STRING
        | STRING2
        | HERE_DOC
        | REGEXP&lt;/p&gt;

&lt;p&gt;TERM        : &lt;code&gt;;'
        |&lt;/code&gt;\n'&lt;/p&gt;

&lt;p&gt;The followings are recognized by lexical analizer.&lt;/p&gt;

&lt;p&gt;OP_ASGN     : &lt;code&gt;+=' |&lt;/code&gt;-=' | &lt;code&gt;*=' |&lt;/code&gt;/=' | &lt;code&gt;%=' |&lt;/code&gt;**='
        | &lt;code&gt;&amp;amp;=' |&lt;/code&gt;|=' | &lt;code&gt;^=' |&lt;/code&gt;&amp;lt;&amp;lt;=' | &lt;code&gt;&amp;gt;&amp;gt;='
        |&lt;/code&gt;&amp;amp;&amp;amp;=' | `||='&lt;/p&gt;

&lt;p&gt;SYMBOL      : &lt;code&gt;:'FNAME
        |&lt;/code&gt;:'VARNAME&lt;/p&gt;

&lt;p&gt;FNAME       : IDENTIFIER | &lt;code&gt;..' |&lt;/code&gt;|' | &lt;code&gt;^' |&lt;/code&gt;&amp;amp;'
        | &lt;code&gt;&amp;lt;=&amp;gt;' |&lt;/code&gt;==' | &lt;code&gt;===' |&lt;/code&gt;=~'
                | &lt;code&gt;&amp;gt;' |&lt;/code&gt;&amp;gt;=' | &lt;code&gt;&amp;lt;' |&lt;/code&gt;&amp;lt;='
        | &lt;code&gt;+' |&lt;/code&gt;-' | &lt;code&gt;*' |&lt;/code&gt;/' | &lt;code&gt;%' |&lt;/code&gt;**'
        | &lt;code&gt;&amp;lt;&amp;lt;' |&lt;/code&gt;&amp;gt;&amp;gt;' | &lt;code&gt;~'
                |&lt;/code&gt;+@' | &lt;code&gt;-@' |&lt;/code&gt;[]' | `[]='&lt;/p&gt;

&lt;p&gt;OPERATION       : IDENTIFIER
                | IDENTIFIER'!'
                | IDENTIFIER'?'&lt;/p&gt;

&lt;p&gt;VARNAME     : GLOBAL
        | `@'IDENTIFIER
        | IDENTIFIER&lt;/p&gt;

&lt;p&gt;GLOBAL      : &lt;code&gt;$'IDENTIFIER
        |&lt;/code&gt;$'any_char
        | `$''-'any_char&lt;/p&gt;

&lt;p&gt;STRING      : &lt;code&gt;"' any_char*&lt;/code&gt;"'
        | &lt;code&gt;'' any_char*&lt;/code&gt;''
        | &lt;code&gt;' any_char*&lt;/code&gt;'&lt;/p&gt;

&lt;p&gt;STRING2     : &lt;code&gt;%'(&lt;/code&gt;Q'|&lt;code&gt;q'|&lt;/code&gt;x')char any_char* char&lt;/p&gt;

&lt;p&gt;HERE_DOC        : `&amp;lt;&amp;lt;'(IDENTIFIER|STRING)
                  any_char*
                  IDENTIFIER&lt;/p&gt;

&lt;p&gt;REGEXP      : &lt;code&gt;/' any_char*&lt;/code&gt;/'[&lt;code&gt;i'|&lt;/code&gt;o'|&lt;code&gt;p']
        |&lt;/code&gt;%'`r' char any_char* char&lt;/p&gt;

&lt;p&gt;IDENTIFIER is the sqeunce of characters in the pattern of /[a-zA-Z_][a-zA-Z0-9_]*/.&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Thu, 29 Aug 2013 11:04:47 +0800</pubDate>
      <link>https://ruby-china.org/topics/13716</link>
      <guid>https://ruby-china.org/topics/13716</guid>
    </item>
    <item>
      <title>2.0 respond_to?(x,x) 坑死人！</title>
      <description>&lt;p&gt;原来正常的代码，升级到 2.0 就不正常了，查了半天发觉这个 method 语义变了！非 public 方法默认返回假！&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Wed, 10 Jul 2013 14:55:56 +0800</pubDate>
      <link>https://ruby-china.org/topics/12396</link>
      <guid>https://ruby-china.org/topics/12396</guid>
    </item>
    <item>
      <title>最近想到一个关于上传图片的问题。</title>
      <description>&lt;p&gt;我发现当发一个带图片的帖子的时候，或者说带上传文件的帖子的时候。
如果你已经把附件上传到服务器了，但是最后并没有发表帖子，会导致这些附件成为类似于内存泄露一样的野指针。没有任何对象会引用它们，不能被编辑，也不能删除，一直存在与服务器上面。&lt;/p&gt;

&lt;p&gt;目前发现很多论坛都有这类问题。不知道有没有好的解决方法？&lt;/p&gt;</description>
      <author>rasefon</author>
      <pubDate>Sun, 12 Aug 2012 00:56:38 +0800</pubDate>
      <link>https://ruby-china.org/topics/4881</link>
      <guid>https://ruby-china.org/topics/4881</guid>
    </item>
  </channel>
</rss>
