<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yutaka HARA</title>
    <description>The latest articles on DEV Community by Yutaka HARA (@yhara).</description>
    <link>https://dev.to/yhara</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F41893%2F824c8daf-953c-4342-bcc6-794d511bce77.jpeg</url>
      <title>DEV Community: Yutaka HARA</title>
      <link>https://dev.to/yhara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yhara"/>
    <language>en</language>
    <item>
      <title>How CRuby decides an `if` is a modifier</title>
      <dc:creator>Yutaka HARA</dc:creator>
      <pubDate>Sat, 06 Feb 2021 16:27:15 +0000</pubDate>
      <link>https://dev.to/yhara/how-cruby-decides-an-if-is-a-modifier-2o5o</link>
      <guid>https://dev.to/yhara/how-cruby-decides-an-if-is-a-modifier-2o5o</guid>
      <description>&lt;p&gt;Ruby has two styles to write &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;if foo then bar end&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;foo if bar&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This reads natural to human, but not to machines. For example, can you tell if this code is valid or not?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ruby -e 'p if 1 then 2 else 3 end'
-e:1: syntax error, unexpected `then', expecting end-of-input
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the &lt;code&gt;if&lt;/code&gt; here is recognized as "modifier if", not "keyword if". So how does Ruby decides the type of &lt;code&gt;if&lt;/code&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  parse.y
&lt;/h2&gt;

&lt;p&gt;The answer should be in the &lt;a href="https://github.com/ruby/ruby/blob/94fb62e4a01975d61ad074f882068fdd7d6ed474/parse.y"&gt;parse.y&lt;/a&gt;, which defines Ruby's grammer.&lt;/p&gt;

&lt;p&gt;In the parse.y, you see &lt;a href="https://github.com/ruby/ruby/blob/94fb62e4a01975d61ad074f882068fdd7d6ed474/parse.y#L3241"&gt;keyword_if&lt;/a&gt; and &lt;a href="https://github.com/ruby/ruby/blob/94fb62e4a01975d61ad074f882068fdd7d6ed474/parse.y#L1481"&gt;modifier_if&lt;/a&gt;. It means the type of &lt;code&gt;if&lt;/code&gt; is decided by the lexer, not the parser.&lt;/p&gt;

&lt;h2&gt;
  
  
  lex.c.blt
&lt;/h2&gt;

&lt;p&gt;By grepping &lt;code&gt;modifier_if&lt;/code&gt;, you will find &lt;a href="https://github.com/ruby/ruby/blob/94fb62e4a01975d61ad074f882068fdd7d6ed474/lex.c.blt#L249"&gt;lex.c.blt&lt;/a&gt; has a table of keywords in the function &lt;code&gt;rb_reserved_word&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#line 31 "defs/keywords"
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;gperf_offsetof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stringpool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;keyword_if&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modifier_if&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;EXPR_VALUE&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  parse.y
&lt;/h2&gt;

&lt;p&gt;The lexer starts from &lt;a href="https://github.com/ruby/ruby/blob/94fb62e4a01975d61ad074f882068fdd7d6ed474/parse.y#L9784"&gt;yylex&lt;/a&gt;. It calls &lt;code&gt;parser_yylex&lt;/code&gt;, which handles the symbols like &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, etc. If the character is not a symbol, &lt;code&gt;parse_ident&lt;/code&gt; is called.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;parse_ident&lt;/code&gt; checks if a keyword begins from the current position with &lt;a href="https://github.com/ruby/ruby/blob/94fb62e4a01975d61ad074f882068fdd7d6ed474/parse.y#L9017"&gt;&lt;code&gt;rb_reserved_word&lt;/code&gt;&lt;/a&gt;. The returned &lt;code&gt;kw&lt;/code&gt; is a member of the table we've seen in &lt;code&gt;lex.c.blt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="cm"&gt;/* See if it is a reserved word.  */&lt;/span&gt;
    &lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_reserved_word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;toklen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of &lt;code&gt;if&lt;/code&gt; keyword, &lt;code&gt;kw-&amp;gt;id[0]&lt;/code&gt; corresponds to keyword_if and &lt;code&gt;kw-&amp;gt;id[1]&lt;/code&gt; corresponds to modifier_if.&lt;/p&gt;

&lt;p&gt;Actually &lt;code&gt;id&lt;/code&gt; has two values to distinguish keywords and modifiers. According to lex.c.blt, Ruby has five modifiers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x if y&lt;/li&gt;
&lt;li&gt;x unless y&lt;/li&gt;
&lt;li&gt;x while y&lt;/li&gt;
&lt;li&gt;x until y&lt;/li&gt;
&lt;li&gt;x rescue y&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When an &lt;code&gt;if&lt;/code&gt; is a modifier
&lt;/h2&gt;

&lt;p&gt;This is the condition that distinguishes keyword_if and modifier_if. In short, an &lt;code&gt;if&lt;/code&gt; is a keyword if the lexer state is &lt;code&gt;EXPR_BEG&lt;/code&gt;; otherwise, it is a modifier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IS_lex_state_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXPR_BEG&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;EXPR_LABELED&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;kw&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&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;kw&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&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;kw&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&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="n"&gt;SET_LEX_STATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXPR_BEG&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;EXPR_LABEL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;kw&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The lexer state
&lt;/h2&gt;

&lt;p&gt;Among the states of the lexer, EXPR_BEG, EXPR_END and EXPR_ARG are the most important. They decides operators like &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt; is unary or binary. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1 - 2&lt;/code&gt;: This is binary minus because the state is EXPR_END after the &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;foo(-1)&lt;/code&gt;: This is unary minus because the state is EXPR_BEG after the &lt;code&gt;(&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;EXPR_ARG is a bit tricky; On this state, the meaning of &lt;code&gt;-&lt;/code&gt; changes by the space after it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;foo - 1&lt;/code&gt;: binary minus&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;foo -1&lt;/code&gt;: unary minus&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is interesting is that this rule is not so difficult for humans. The former "looks like" binary and the latter "looks like" unary. So you will actually never be bothered by this, unless you are implementing the parser.&lt;/p&gt;

&lt;h2&gt;
  
  
  keyword if and modifier if
&lt;/h2&gt;

&lt;p&gt;Now you can tell an &lt;code&gt;if&lt;/code&gt; is a keyword or modifier by checking the lexer state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;foo() if ...&lt;/code&gt;: This is modifier_if because the state is EXPR_END after the &lt;code&gt;)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;foo(if ...)&lt;/code&gt;: This is keyword_if because the state is EXPR_BEG after the &lt;code&gt;(&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;foo if ...&lt;/code&gt;: This is modifier_if because the state is EXPR_ARG after the &lt;code&gt;&lt;/code&gt; before &lt;code&gt;if&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters to me
&lt;/h2&gt;

&lt;p&gt;I think most Rubyists does not care about corner cases like this; However I needed to figure out this because I'm making my original programming language &lt;a href="https://github.com/yhara/shiika"&gt;Shiika&lt;/a&gt; which has Ruby-like syntax.&lt;/p&gt;

&lt;p&gt;As you've seen, parsing Ruby-like syntax is not easy, especially parsing method calls without parentheses. I'm happy if this entry helps someone who want to make a Rubyish language.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>parser</category>
    </item>
    <item>
      <title>Automatically prepare windows at tmux startup</title>
      <dc:creator>Yutaka HARA</dc:creator>
      <pubDate>Wed, 06 Mar 2019 17:33:12 +0000</pubDate>
      <link>https://dev.to/yhara/automatically-prepare-windows-at-tmux-startup-4c6</link>
      <guid>https://dev.to/yhara/automatically-prepare-windows-at-tmux-startup-4c6</guid>
      <description>&lt;p&gt;Do you have a rule for tmux windows? For example, on which window do you start your editor? Here is my rule.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Window 0: &lt;a href="https://github.com/yhara/reposh"&gt;reposh&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Window 1: vim&lt;/li&gt;
&lt;li&gt;Window 2: zsh&lt;/li&gt;
&lt;li&gt;Window 3: Server process (i.e. &lt;code&gt;rails server&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It means that everytime I start tmux, I open 4 windows and run these. Today I learned to do it automatically.&lt;/p&gt;

&lt;h1&gt;
  
  
  Command file
&lt;/h1&gt;

&lt;p&gt;The first step is to write a tmux command file. This is a list of tmux commands that I want to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat ~/proj/dotfiles/tools/tmux_multi
new-window
new-window
new-window
select-window -t 0
send-keys 'reposh' Enter
select-window -t 1
send-keys 'vim' Enter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then you can load this file at tmux startup by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ tmux new-session ";" source-file ~/proj/dotfiles/tools/tmux_multi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Alias
&lt;/h1&gt;

&lt;p&gt;Of course this is too long to remember. So I added an alias to my &lt;code&gt;.zshrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias tmux!='tmux new-session ";" source-file ~/proj/dotfiles/tools/tmux_multi'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now my tmux sets up the 4 windows by &lt;code&gt;tmux!&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips: setting iTerm2 tab title
&lt;/h2&gt;

&lt;p&gt;If you are using iTerm2 on Mac, it is useful to set the tab title before starting tmux.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias tmux!='TAB_NAME=`ruby -e "print Dir.pwd.split(\"/\").last"`; echo -ne "\e]1;$TAB_NAME\a"; tmux new-session ";" source-file ~/proj/dotfiles/tools/tmux_multi'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>tmux</category>
    </item>
  </channel>
</rss>
