<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Corgi Lab. ～備忘録のための技術ブログ～</title>
	<atom:link href="https://corgi-lab.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://corgi-lab.com</link>
	<description></description>
	<lastBuildDate>Sun, 05 May 2024 00:18:42 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://corgi-lab.com/blog/wp-content/uploads/2016/08/cropped-logo-32x32.jpg</url>
	<title>Corgi Lab. ～備忘録のための技術ブログ～</title>
	<link>https://corgi-lab.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://corgi-lab.com/feed/"/>
	<item>
		<title>wordleもどきのCUIアプリをつくってみた</title>
		<link>https://corgi-lab.com/linux/cwordl/</link>
					<comments>https://corgi-lab.com/linux/cwordl/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Sun, 14 Aug 2022 02:46:13 +0000</pubDate>
				<category><![CDATA[C言語]]></category>
		<category><![CDATA[自作物]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2590</guid>

					<description><![CDATA[最近、wordleという英単語当てゲームで遊んでいます。シンプルなゲームながら、通勤時間の暇つぶしや友人とのスコア比べなど意外と中毒性があり面白いです。 普通に英単語の勉強にもなるので、もっとたくさん ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[<p>最近、<a href="https://www.nytimes.com/games/wordle/index.html" target="_blank" rel="noopener">wordle</a>という英単語当てゲームで遊んでいます。シンプルなゲームながら、通勤時間の暇つぶしや友人とのスコア比べなど意外と中毒性があり面白いです。</p>
<p>普通に英単語の勉強にもなるので、もっとたくさん遊びたいのですが、本家は1日1単語に制限されているのがちょっと残念。そこで、今回はCUIでwordleもどきのアプリを作ってみました。</p>
<h2>つくったアプリ</h2>
<p>今回つくったアプリは、C言語の「C」・CUIの「C」を頭に付けて「cwordle」という名前にしました。</p>
<div class="linkcard"><div class="lkc-external-wrap"><a class="lkc-link no_icon" href="https://github.com/corgi0901/cwordle" data-lkc-id="285711" target="_blank" rel="external noopener"><div class="lkc-card"><div class="lkc-info"><div class="lkc-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=github.com" alt="" width="16" height="16" /></div><div class="lkc-domain">GitHub</div></div><div class="lkc-content"><figure class="lkc-thumbnail"><img decoding="async" class="lkc-thumbnail-img" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fgithub.com%2Fcorgi0901%2Fcwordle?w=100" width="100px" height="108px" alt="" /></figure><div class="lkc-title">GitHub - corgi0901/cwordle</div><div class="lkc-excerpt">Contribute to corgi0901/cwordle development by creating an account on GitHub.</div></div><div class="clear"></div></div></a></div></div>
<p>プレイ中の画面はこんな感じ。C言語がコンパイルできて、コンソールから実行できる環境であれば大体動くとは思います。</p>
<p><a href="https://corgi-lab.com/blog/wp-content/uploads/2022/08/cwordl.png"><img fetchpriority="high" decoding="async" class="aligncenter size-full wp-image-2595" src="https://corgi-lab.com/blog/wp-content/uploads/2022/08/cwordl.png" alt="" width="721" height="239" srcset="https://corgi-lab.com/blog/wp-content/uploads/2022/08/cwordl.png 721w, https://corgi-lab.com/blog/wp-content/uploads/2022/08/cwordl-300x99.png 300w" sizes="(max-width: 721px) 100vw, 721px" /></a></p>
<p>今回は勉強がてら、ncurseを使って実装しているので、割とちゃんとしたゲームっぽく動きます。出題される英単語も毎回ランダムで変わるので、一日に何度でも遊べます。</p>
<p>出題される英単語のデータは<a href="https://kujirahand.com/web-tools/EJDictFreeDL.php" target="_blank" rel="noopener">パブリックドメインの辞書データ</a>を利用しているのですが、本家のwordleよりもずっと難しい気がします（汗。本家は出題される単語を絞っているだと思いますが、その基準も不明なのでとりあえずそのままに…。</p>
<p>CUIであれば、仕事しているフリして遊ぶことも可能です。<br />
ちょっとした暇つぶしツールをお探しの方はよければ遊んでみてください。</p>
<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/linux/cwordl/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi4＋Ubuntu ServerでGitLabを動かしてみる</title>
		<link>https://corgi-lab.com/linux/raspberrypi4-gitlab/</link>
					<comments>https://corgi-lab.com/linux/raspberrypi4-gitlab/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Sat, 22 Jan 2022 06:32:12 +0000</pubDate>
				<category><![CDATA[RaspberryPi]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2554</guid>

					<description><![CDATA[お仕事でGitLabに触れる機会があったので、学習用に自宅にもGitLabが欲しくなりました。 手元にあるRaspberry Pi4＋Dockerならお手軽に立ち上げられるはずと着手したものの、意外と ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[<p>お仕事でGitLabに触れる機会があったので、学習用に自宅にもGitLabが欲しくなりました。</p>
<p>手元にあるRaspberry Pi4＋Dockerならお手軽に立ち上げられるはずと着手したものの、意外とハマって大変だったので備忘録をまとめておきます。</p>
<h2>環境</h2>
<p>今回の環境は以下の構成になります。</p>
<ul>
<li>ハード：Raspberry Pi4 MobelB</li>
<li>OS：Ubuntu Server 20.04</li>
</ul>
<p>ラズパイへのUbuntu Serverのインストール方法は以下の記事にまとめています。<br />
<div class="linkcard"><div class="lkc-internal-wrap"><a class="lkc-link no_icon" href="https://corgi-lab.com/linux/rpi4-ubuntu-server-2004" data-lkc-id="139130"><div class="lkc-card"><div class="lkc-info"><div class="lkc-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=corgi-lab.com" alt="" width="16" height="16" /></div><div class="lkc-domain">Corgi Lab. ～備忘録のための技術ブログ～</div><div class="lkc-share"> <div class="lkc-sns-po">4 Pockets</div></div></div><div class="lkc-content"><figure class="lkc-thumbnail"><img decoding="async" class="lkc-thumbnail-img" src="//corgi-lab.com/blog/wp-content/uploads/2020/05/raspi4_body-150x150.jpg" width="100px" height="108px" alt="" /></figure><div class="lkc-title">RaspberryPi4でUbuntu Server 20.04を動かしてみた</div><div class="lkc-excerpt">新しい遊び道具として、RaspberryPi4（ModelB 4GBメモリ）を買いました。前モデルと比べて大幅に性能アップしているということで、学習用のLinux環境としても実用的なものになりそうです。ということで、今回はRaspbian（ラズパイの標準OS）ではなく、Ubuntu Serverをインストールして使ってみたいと思います(･∀･)OSイメージのダウンロードまずはUbuntu Serverのラズパイ用イメージを以下のページからダウンロードします。32bitと64bit両方のイメージが用意されていますが、特にこだわりがなければ64bit版で大丈夫です。2020/05/02時点...</div></div><div class="clear"></div></div></a></div></div></p>
<h2>Dockerのインストール</h2>
<p>まずはDockerをインストールします。以下のコマンドを叩くだけです。</p>
<div class="graybox command">$ sudo apt install docker<br />
$ sudo apt install docker-compose</div>
<h2>GitLabの立ち上げ</h2>
<p>Docker上にGitLabを立ち上げます。まずは下準備として、GitLabの各種ファイルを保存するためのディレクトリを掘ります。ここでは例として、<code>/var/docker/gitlab</code>というディレクトリを掘りました。</p>
<div class="graybox command">$ sudo mkdir -p /var/docker/gitlab</div>
<p>続いて、以下のコマンドでGitLabのインスタンスを立ち上げます。<code>GITLAB_HOME</code>には先で作成したディレクトリのパスを指定しましょう。</p>
<div class="graybox command">$ export GITLAB_HOME=/var/docker/gitlab<br />
$ sudo docker run &#8211;detach \<br />
&#8211;hostname gitlab.example.com \<br />
&#8211;publish 444:443 &#8211;publish 81:80 \<br />
&#8211;name gitlab \<br />
&#8211;restart always \<br />
&#8211;volume $GITLAB_HOME/config:/etc/gitlab \<br />
&#8211;volume $GITLAB_HOME/logs:/var/log/gitlab \<br />
&#8211;volume $GITLAB_HOME/data:/var/opt/gitlab \<br />
&#8211;shm-size 256m \<br />
yrzr/gitlab-ce-arm64v8:latest</div>
<p>基本は<a href="https://docs.gitlab.com/ee/install/docker.html" rel="noopener" target="_blank">GitLabの公式リファレンス</a>に記載されている方法と同じですが、GitLab本体のイメージにサードパーティのものを使います。</p>
<p>というのも、ラズパイ4はCPUのアーキテクチャがARMなので、GitLabの公式イメージは動かすことができないためです。サードパーティー製なので<span class="hutoaka">あくまでも自己責任での使用になります</span>が、個人の学習用としては必要十分だと思います。</p>
<p>初回起動時は内部であれこれと処理が走るので、すぐにはアクセスできません。しばらく時間が経った後、ラズパイのIPアドレスにアクセスし、以下の画面が出れば起動は成功です。</p>
<p><a href="https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab.png"><img decoding="async" src="https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab.png" alt="" width="1042" height="548" class="aligncenter size-full wp-image-2560" srcset="https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab.png 1042w, https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-300x158.png 300w, https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-1024x539.png 1024w, https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-768x404.png 768w" sizes="(max-width: 1042px) 100vw, 1042px" /></a></p>
<h2>管理者パスワードのリセット</h2>
<p>本来であれば、初回起動時は管理者パスワードのリセットを求められるのですが、今回はそれが出ませんでした(´・ω・)</p>
<p>このままでは管理者ユーザーのパスワードが分からずにログインすることができません。そこで管理者パスワードを強制的にリセットします。</p>
<p>まずは、以下のコマンドでDocker上のGitLabコンテナに入ります。</p>
<div class="graybox command">
$ sudo docker exec -it gitlab /bin/bash</div>
<p>コンテナ内に入れたら、以下を実行してrailsのコンソールを開きます。（すこし時間がかかります）</p>
<div class="graybox command">
# gitlab-rails console -e production<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 Ruby:         ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [aarch64-linux]<br />
 GitLab:       14.6.2 (0a901d60f8a) FOSS<br />
 GitLab Shell: 13.22.1<br />
 PostgreSQL:   12.7<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Loading production environment (Rails 6.1.4.1)<br />
irb(main):001:0>
</div>
<p>上記のようなコンソールが開いたら、まずは管理者ユーザーを取得します。管理者ユーザー=最初に登録されているユーザーです。</p>
<div class="graybox command">
irb(main):001:0> user = User.find(1)<br />
=> #&lt;User id:1 @root&gt;
</div>
<p>続いて、パスワードを上書きします。以下は<code>password</code>としていますが、お好みのものをどうぞ。</p>
<div class="graybox command">
irb(main):002:0> user.password = &#8216;password&#8217;<br />
=> &#8220;password&#8221;
</div>
<p>再確認用のパスワードも入力しておきます。</p>
<div class="graybox command">
irb(main):003:0> user.password_confirmation=&#8217;password&#8217;<br />
=> &#8220;password&#8221;
</div>
<p>最後にパスワードを保存すれば完了です。</p>
<div class="graybox command">
irb(main):004:0> user.save!<br />
=> true
</div>
<p>これでGitLabにもログインできるようになりました。ユーザー名に<code>root</code>、パスワードに先で設定したものを入れてログインできれば成功です！</p>
<p><a href="https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-top.png"><img decoding="async" src="https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-top.png" alt="" width="1536" height="359" class="aligncenter size-full wp-image-2572" srcset="https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-top.png 1536w, https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-top-300x70.png 300w, https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-top-1024x239.png 1024w, https://corgi-lab.com/blog/wp-content/uploads/2022/01/gitlab-top-768x180.png 768w" sizes="(max-width: 1536px) 100vw, 1536px" /></a></p>
<p>いろいろハマるところがあって大変でしたが、なんとかGitLabを立ち上げることができました。興味のある方は試してみてはいかがでしょう？</p>
<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/linux/raspberrypi4-gitlab/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Flutter】アプリ内の設定値を実装する方法</title>
		<link>https://corgi-lab.com/programming/shared-preference/</link>
					<comments>https://corgi-lab.com/programming/shared-preference/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Mon, 02 Aug 2021 00:32:23 +0000</pubDate>
				<category><![CDATA[Flutter]]></category>
		<category><![CDATA[プログラミング]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2471</guid>

					<description><![CDATA[アプリ内で独自の設定を作る場合、そのデータを保持する方法を考える必要があります。 SQL、テキストファイルなど選択肢は多々ありますが、shared_preferencesというパッケージを使えば簡単に ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[
<p>アプリ内で独自の設定を作る場合、そのデータを保持する方法を考える必要があります。</p>



<p>SQL、テキストファイルなど選択肢は多々ありますが、<code>shared_preferences</code>というパッケージを使えば簡単に実装することができます。</p>


<div class="linkcard"><div class="lkc-external-wrap"><a class="lkc-link no_icon" href="https://pub.dev/packages/shared_preferences" data-lkc-id="110009" target="_blank" rel="external noopener"><div class="lkc-card"><div class="lkc-info"><div class="lkc-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=pub.dev" alt="" width="16" height="16" /></div><div class="lkc-domain">Dart packages</div><div class="lkc-share"> <div class="lkc-sns-hb">2 Users</div> <div class="lkc-sns-po">65 Pockets</div></div></div><div class="lkc-content"><figure class="lkc-thumbnail"><img decoding="async" class="lkc-thumbnail-img" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fpub.dev%2Fpackages%2Fshared_preferences?w=100" width="100px" height="108px" alt="" /></figure><div class="lkc-title">shared_preferences | Flutter Package</div><div class="lkc-excerpt">Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android.</div></div><div class="clear"></div></div></a></div></div>



<h2 class="wp-block-heading">下準備</h2>



<p>まずは<code>pubspec.yaml</code>の<code>dependencies</code>に<code>shared_preferences</code>のパッケージを追加します。この記事を書いている時点での最新は2.0.6でした。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="dependencies:
  shared_preferences: ^2.0.6" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">dependencies:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  shared_preferences: ^2.0.6</span></span></code></pre></div>



<p>下準備はたったこれだけです。以降、アプリへの組み込みをしていきます。</p>



<h2 class="wp-block-heading">アプリに組み込んでみる</h2>



<h3 class="wp-block-heading">インスタンスの取得</h3>



<p>値を読み書きは<code>SharedPreferences</code>のインスタンスを介して行います。インスタンスの取得処理は以下の通りです。ちなみに非同期関数になります。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="SharedPreferences prefs = await SharedPreferences.getInstance();" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #8FBCBB">SharedPreferences</span><span style="color: #D8DEE9FF"> prefs </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SharedPreferences</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getInstance</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<h3 class="wp-block-heading">値の読み書き</h3>



<p>取得したインスタンスに対しては、値の型に応じたsetter/getterのAPIを使って中身にアクセスすることができます。Ver2.0.6時点では以下の型に対応しています。</p>



<div class="graybox">・Int（整数）<br>・Double（小数）<br>・Bool（真偽値）<br>・String（文字列）<br>・List（文字列リスト）</div>



<p>内部的にはKey-Valueの形式で保存されているため、各APIはキーと値を指定する形になります。Intの場合、setter/getterはそれぞれ以下のように定義されています。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// Setter
Future setInt( String key, int value )

// Getter
int? getInt( String key )" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// Setter</span></span>
<span class="line"><span style="color: #8FBCBB">Future</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">setInt</span><span style="color: #D8DEE9FF">( </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> key</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">int</span><span style="color: #D8DEE9FF"> value )</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// Getter</span></span>
<span class="line"><span style="color: #8FBCBB">int</span><span style="color: #81A1C1">?</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">getInt</span><span style="color: #D8DEE9FF">( </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> key )</span></span></code></pre></div>



<h3 class="wp-block-heading">実装してみる</h3>



<p>これらを使って、実装してみるとこんな感じになります。このようにAPIをラップしてあげると使い勝手がよく便利です。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="import 'package:shared_preferences/shared_preferences.dart';

const String _KEY_HOGE = &quot;hogehoge&quot;;

Future&lt;int&gt; getHoge() async {
	SharedPreferences prefs = await SharedPreferences.getInstance();
	int ret = prefs.getInt(_KEY_HOGE ) ?? 0;
	return ret;
}

void setHoge(int value) async {
	final SharedPreferences prefs = await SharedPreferences.getInstance();
	await prefs.setInt(_KEY_HOGE, value);
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">&#39;package:shared_preferences/shared_preferences.dart&#39;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">String</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">_KEY_HOGE</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">&quot;hogehoge&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">Future</span><span style="color: #D8DEE9FF">&lt;</span><span style="color: #8FBCBB">int</span><span style="color: #D8DEE9FF">&gt; </span><span style="color: #88C0D0">getHoge</span><span style="color: #D8DEE9FF">() </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> {</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #8FBCBB">SharedPreferences</span><span style="color: #D8DEE9FF"> prefs </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SharedPreferences</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getInstance</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #8FBCBB">int</span><span style="color: #D8DEE9FF"> ret </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> prefs</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getInt</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">_KEY_HOGE</span><span style="color: #D8DEE9FF"> ) </span><span style="color: #81A1C1">??</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> ret</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">setHoge</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">int</span><span style="color: #D8DEE9FF"> value) </span><span style="color: #81A1C1">async</span><span style="color: #D8DEE9FF"> {</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">final</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SharedPreferences</span><span style="color: #D8DEE9FF"> prefs </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">SharedPreferences</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getInstance</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">await</span><span style="color: #D8DEE9FF"> prefs</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">setInt</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">_KEY_HOGE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> value)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span></code></pre></div>



<p>これでアプリ内に設定値を保存できるようになりました。複雑なデータは保存できないものの、オン/オフや数値などの簡単なデータであればとても楽に扱うことができます。</p>



<p>自作アプリに設定値を作りたい方はぜひ試してみてはいかがでしょうか？</p>



<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/programming/shared-preference/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>YoctoでRaspberryPi4のイメージをビルドしてみた</title>
		<link>https://corgi-lab.com/linux/yocto-raspberrypi4/</link>
					<comments>https://corgi-lab.com/linux/yocto-raspberrypi4/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Sun, 18 Apr 2021 02:12:31 +0000</pubDate>
				<category><![CDATA[RaspberryPi]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2439</guid>

					<description><![CDATA[昨今、様々なデバイスでLinuxが動くようになっている中、組み込みLinuxのデファクトスタンダードとなりつつあるのが「Yocto」と呼ばれるビルドシステムです。 組み込みの現場ではその名前を聞くこと ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[<p>昨今、様々なデバイスでLinuxが動くようになっている中、組み込みLinuxのデファクトスタンダードとなりつつあるのが「Yocto」と呼ばれるビルドシステムです。</p>
<p>組み込みの現場ではその名前を聞くことが増えましたが、まだまだ日本ではドキュメントも乏しくイマイチ掴み所がありません。そこで、まずは使ってみようということでRaspberry Pi4のイメージをビルドしてみることにしました。</p>
<h2>Yoctoとは？</h2>
<p>まず、Yoctoって何？というお話しですが、簡単に言うと「オリジナルのディストリビューションを作れる仕組み」です。カーネルからユーザーランドに至るまで、Linux全体をカスタマイズしてビルドすることができます。</p>
<p>以下は<a href="https://www.yoctoproject.org/software-overview/" target="_blank" rel="noopener">Yoctoの公式サイト</a>から引用したワークフローの図です。</p>
<p><a href="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yp-how-it-works-new-diagram.png"><img decoding="async" class="aligncenter size-full wp-image-2440" src="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yp-how-it-works-new-diagram.png" alt="" width="800" height="372" srcset="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yp-how-it-works-new-diagram.png 800w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yp-how-it-works-new-diagram-300x140.png 300w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yp-how-it-works-new-diagram-768x357.png 768w" sizes="(max-width: 800px) 100vw, 800px" /></a></p>
<p>Build System（背景が水色のブロック）がYocto内部で実行される処理フローを表しています。ソースの取得→パッチ適用→ビルド→パッケージ化→イメージ作成という風に、必要なソースを外部から取得してビルドすることで柔軟なイメージ作成が可能になっています。</p>
<h2>Raspberry Pi4のイメージを作ってみる</h2>
<p>さっそくYoctoを試してみましょう。今回は、手元にある組み込みLinuxボードとしてRaspberry Pi4をターゲットとします。</p>
<h3>下準備</h3>
<p>ホスト環境はUbuntu18.04を使います。2021/4/18時点で、以下のOSがホスト環境として利用できるようです。</p>
<ul>
<li style="list-style-type: none;">
<ul>
<li>Ubuntu 16.04 (LTS) / 18.04 (LTS) / 20.04</li>
<li>Fedora 30 / 31 / 32</li>
<li>CentOS 7.x / 8.x</li>
<li>Debian GNU/Linux 8.x (Jessie) / 9.x (Stretch) / 10.x (Buster)</li>
<li>openSUSE Leap 15.1</li>
</ul>
</li>
</ul>
<p>Yoctoを動かす事前準備として、必要なパッケージをインストールします。<a href="https://docs.yoctoproject.org/ref-manual/system-requirements.html#required-packages-for-the-build-host" target="_blank" rel="noopener">Yoctoの公式マニュアル</a>にOSごとのインストールコマンドが記載されているため、素直にそれに従います。</p>
<div class="graybox command">$ sudo apt-get install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm python3-subunit mesa-common-dev</div>
<h3>Yocto本体＋ラズパイ向け設定の取得</h3>
<p>続いて、Yocto本体（poky）を取得します。</p>
<div class="graybox command">$ git clone git://git.yoctoproject.org/poky</div>
<p>pokyだけではラズパイ向けイメージのビルドに対応していません。そこで、ラズパイ向けのレイヤー（設定の集まりみたいなもの）を取り込みます。</p>
<div class="graybox command">$ cd poky<br />
$ git clone https://github.com/agherzan/meta-raspberrypi.git</div>
<h3>ビルド前設定</h3>
<p>レイヤーの取り込みができたら、いよいよビルドに入ります。</p>
<p>まずは以下のコマンドでpokyをセットアップします。このコマンドを実行すると、カレントディレクトリが<code>poky/build</code>に移動します。</p>
<div class="graybox command">$ source oe-init-build-env</div>
<p>ここからは下準備として、各種設定ファイルの書き換えをします。まずは<code>conf/bblayers.conf</code>にラズパイ用レイヤー（赤字部分）を追加します。</p>
<div class="graybox command">$ sudo vi conf/bblayers.conf<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
BBLAYERS ?= &#8221; \<br />
/home/ryo/workspace/poky/meta \<br />
/home/ryo/workspace/poky/meta-poky \<br />
/home/ryo/workspace/poky/meta-yocto-bsp \<br />
<span class="st-aka">/home/ryo/workspace/poky/meta-raspberrypi \</span><br />
&#8221;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</div>
<p>続いて、ビルドターゲットをラズパイに変更します。<code>conf/local.conf</code>にターゲットの設定（赤字部分）を追加します。</p>
<div class="graybox command">$ sudo vi conf/local.conf<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
# There are also the following hardware board target machines included for<br />
# demonstration purposes:<br />
#<br />
#MACHINE ?= &#8220;beaglebone-yocto&#8221;<br />
#MACHINE ?= &#8220;genericx86&#8221;<br />
#MACHINE ?= &#8220;genericx86-64&#8221;<br />
#MACHINE ?= &#8220;edgerouter&#8221;<br />
#<br />
# This sets the default machine to be qemux86-64 if no other machine is selected:<br />
MACHINE ??= &#8220;qemux86-64&#8221;<br />
<span class="st-aka">MACHINE ?= &#8220;raspberrypi4-64&#8221;</span><br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</div>
<p>ここまでで下準備は完了です。あとはビルドを始めるだけ！</p>
<h3>ビルド実行</h3>
<p>以下のコマンドでビルドを開始します。必要最小限の機能のみをビルドする場合は<code>core-image-minimal</code>を指定すると良いようです。</p>
<div class="graybox command">$ bitbake core-image-minimal</div>
<p>ここからはひたすら待ちます。CPU4コア・メモリ4GBのマシンで約4時間近くかかりました。</p>
<p>コンソールを見ていると、次々にパッケージがビルドされていく様子を見れて面白いです。先述したワークフローに従ってビルドが進行されていくのが分かります。</p>
<p><a href="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto.png"><img decoding="async" class="aligncenter size-full wp-image-2449" src="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto.png" alt="" width="1305" height="601" srcset="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto.png 1305w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto-300x138.png 300w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto-1024x472.png 1024w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto-768x354.png 768w" sizes="(max-width: 1305px) 100vw, 1305px" /></a></p>
<h2>完成したイメージをラズパイで動かす</h2>
<p>できあがったイメージをラズパイ本体で動かしてみます。</p>
<p>ビルドされたイメージは<code>poky/build/tmp/deploy/images/raspberrypi4-64</code>下にあります。拡張子がwic.bz2のファイルがそれです。</p>
<div class="graybox">core-image-minimal-raspberrypi4-64-20210417040438.rootfs.wic.bz2</div>
<p>このファイルを取り出して展開すると、拡張子がwicのファイルが出てきます。これをEtcherなどの書き込みツールでSDカードに書き込むだけです。</p>
<p><a href="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto2.png"><img decoding="async" class="aligncenter size-full wp-image-2451" src="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto2.png" alt="" width="796" height="478" srcset="https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto2.png 796w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto2-300x180.png 300w, https://corgi-lab.com/blog/wp-content/uploads/2021/04/yocto2-768x461.png 768w" sizes="(max-width: 796px) 100vw, 796px" /></a></p>
<p>あとは書き込んだSDカードをラズパイに挿して起動できれば大成功です。</p>
<h2>まとめ</h2>
<p>今回はただ動かしただけですが、イチからLinux全体をビルドできたと考えるとちょっと面白いですね！Yoctoの神髄であるオリジナルのディストリビューション作成については、今後挑戦してみたいと思います。</p>
<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/linux/yocto-raspberrypi4/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>言語処理系をつくろう（第7回）：比較演算子を実装する</title>
		<link>https://corgi-lab.com/self-made/lang-processor-7/</link>
					<comments>https://corgi-lab.com/self-made/lang-processor-7/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Fri, 14 Aug 2020 02:27:10 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[自作物]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2394</guid>

					<description><![CDATA[自作の言語処理系開発日記の第7回です。前回までで変数の実装が終わったので、ここからはいよいよ制御構文を実装…と思ったのですが、制御のためには比較演算子を実装する必要がありました。 ということで、今回は ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[
<p>自作の言語処理系開発日記の第7回です。<a href="https://corgi-lab.com/self-made/lang-processor-6/">前回</a>までで変数の実装が終わったので、ここからはいよいよ制御構文を実装…と思ったのですが、制御のためには比較演算子を実装する必要がありました。</p>



<p>ということで、今回は比較演算子を実装していきます。基本的には四則演算と変わりないのであまり難しくはありません。</p>



<h2 class="wp-block-heading">比較演算子の仕様</h2>



<p>比較演算子を実装する前に、その仕様について少し考えておきます。</p>



<p>比較演算子の結果は真偽の2値ですが、データ上は真を1、偽を0で表すこととします。こうした理由は特にないのですが、一番直感的に分かりやすい形にしました。処理系の中で統一されていれば問題ないので、0/1でなくてもOKです。</p>



<h2 class="wp-block-heading">実装してみる</h2>



<h3 class="wp-block-heading">トークナイザ</h3>



<p>トークナイズの処理はこれまでと変わらずですが、<code>==</code>（等価）や<code>&lt;=</code>（以下）は2文字で1つの演算子になるので、<code>＝</code>（代入）や<code>&lt;</code>（未満）と間違えて解釈されないように注意します。</p>



<p>この場合、最長一致で見つけていくのが良いので、以下のように処理の順番を1文字の演算子よりも先に持ってくるようにします。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="〜省略〜

else if(strncmp(input, &quot;&lt;=&quot;, 2) == 0){
	Token token = { TK_RESERVED, input, 2 };
	tokens.push_back(token);
	input += 2;
}
else if(strncmp(input, &quot;&lt;&quot;, 1) == 0){
	Token token = { TK_RESERVED, input, 1 };
	tokens.push_back(token);
	input++;
}

〜省略〜" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">〜省略〜</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">strncmp</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">input</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	Token token </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> TK_RESERVED</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> input</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">tokens</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">token</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	input </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">strncmp</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">input</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	Token token </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> TK_RESERVED</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> input</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">tokens</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">token</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	input</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">〜省略〜</span></span></code></pre></div>



<h3 class="wp-block-heading">構文解析器</h3>



<p>新しい演算子を追加するので、生成規則にもそれらを追加します。修正後の生成規則はこんな感じです。</p>



<div class="graybox">program = expr (&#8220;,&#8221; expr | &#8220;\n&#8221; expr)*<br>expr = ident &#8220;=&#8221; <span style="color: #ff0000;">compare</span> | <span style="color: #ff0000;">compare</span><br><span style="color: #ff0000;">compare = add | add (&#8220;==&#8221; | &#8220;!=&#8221; | &#8220;&lt;&#8221; | &#8220;&lt;=&#8221; | &#8220;&gt;&#8221; | &#8220;&gt;=&#8221;) add</span><br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = unary (&#8220;*&#8221; unary | &#8220;/&#8221; unary)*<br>unary = (&#8220;+&#8221; | &#8220;-&#8220;)? primary<br>primary = ident | num | &#8220;(&#8221; <span style="color: #ff0000;">compare</span> &#8220;)&#8221;</div>



<p>新しい生成規則として<code>compare</code>を追加し、これまでの規則中の<code>add</code>をそれに置き換えています。というのも、比較演算子の優先順位は四則演算よりも低いので、構文解析時には優先的に展開される必要があるためです。これにより、<code>1+2&lt;1+3</code>のような式も正しく処理することができます。</p>



<p>続いて実装ですが、ノード種別の追加は<code>==</code>、<code>!=</code>、<code>&lt;</code>、<code>&lt;=</code>だけで十分です。<code>></code>と><code>=</code>については、<code>&lt;</code>と<code>&lt;=</code>の左辺と右辺を入れ替えて評価するだけでよいためです。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// ノード関連の定義
typedef enum {
	ND_NUM,			// 数値
	〜省略〜
	ND_EQ,			// ==
	ND_NEQ,			// !=
	ND_LESS,		// &lt;
	ND_EQLESS,		// &lt;=
} NodeKind;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// ノード関連の定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_NUM</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 数値</span></span>
<span class="line"><span style="color: #D8DEE9FF">	〜省略〜</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_EQ</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// ==</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_NEQ</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// !=</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_LESS</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// &lt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_EQLESS</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// &lt;=</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> NodeKind</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>構文木を作る処理もこの通り、左辺と右辺の入れ替えで対応します。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="〜省略〜

else if(consume(&quot;&lt;&quot;)){
	node = new Node{ ND_LESS, addNode, add()};
}
else if(consume(&quot;&lt;=&quot;)){
	node = new Node{ ND_EQLESS, addNode, add()};
}
else if(consume(&quot;&gt;&quot;)){
	node = new Node{ ND_LESS, add(), addNode}; // 右左辺を入れ替え
}
else if(consume(&quot;&gt;=&quot;)){
	node = new Node{ ND_EQLESS, add(), addNode}; // 右左辺を入れ替え
}

〜省略〜" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">〜省略〜</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_LESS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> addNode</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">()}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_EQLESS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> addNode</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">()}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&gt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_LESS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> addNode</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span><span style="color: #616E88"> // 右左辺を入れ替え</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&gt;=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_EQLESS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">(),</span><span style="color: #D8DEE9FF"> addNode</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span><span style="color: #616E88"> // 右左辺を入れ替え</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">〜省略〜</span></span></code></pre></div>



<h3 class="wp-block-heading">コード生成器</h3>



<p>コード生成についても構文解析と同じく、<code>==</code>、<code>!=</code>、<code>&lt;</code>、<code>&lt;=</code>に対応した各命令を新たに定義します。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// 命令関連の定義
typedef enum {
	〜省略〜
	OP_EQ,			// ==
	OP_NEQ,			// !=
	OP_LESS,		// &lt;
	OP_EQLESS,		// &lt;=
	〜省略〜
} OP_CODE;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// 命令関連の定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	〜省略〜</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_EQ</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// ==</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_NEQ</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// !=</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_LESS</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// &lt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_EQLESS</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// &lt;=</span></span>
<span class="line"><span style="color: #D8DEE9FF">	〜省略〜</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> OP_CODE</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<h3 class="wp-block-heading">実行系（仮想マシン）</h3>



<p>仮想マシンについては、新規追加した各命令に対する実処理を実装するだけです。特に四則演算と変わりません。比較結果がスタックにPushされます。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="〜省略〜

case OP_EQ:
{
	push(reg[op-&gt;operand] == reg[op-&gt;operand2]);
	break;
}
case OP_NEQ:
{
	push(reg[op-&gt;operand] != reg[op-&gt;operand2]);
	break;
}
case OP_LESS:
{
	push(reg[op-&gt;operand] &lt; reg[op-&gt;operand2]);
	break;
}
case OP_EQLESS:
{
	push(reg[op-&gt;operand] &lt;= reg[op-&gt;operand2]);
	break;
}

〜省略〜" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">〜省略〜</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> OP_EQ:</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">push</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand2</span><span style="color: #ECEFF4">])</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> OP_NEQ:</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">push</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand2</span><span style="color: #ECEFF4">])</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> OP_LESS:</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">push</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand2</span><span style="color: #ECEFF4">])</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> OP_EQLESS:</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">push</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand2</span><span style="color: #ECEFF4">])</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">〜省略〜</span></span></code></pre></div>



<p>これで比較演算子を扱えるようになりました。今はまだ使いどころがないですが、次回以降で制御構文を実装すると、これらの演算子が活きてくることになります。</p>



<p>今回の実装は以下のコミットです。全コードはこちらをご覧くださいm(_ _)m</p>



<p><a href="https://github.com/corgi0901/rook/commit/112716a9fd02b4e527da7fc95c3e4f91b787f178" target="_blank" rel="noopener noreferrer">比較演算子を実装（112716a）</a></p>



<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/self-made/lang-processor-7/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>言語処理系をつくろう（第6回）：変数を実装する</title>
		<link>https://corgi-lab.com/self-made/lang-processor-6/</link>
					<comments>https://corgi-lab.com/self-made/lang-processor-6/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Tue, 11 Aug 2020 00:59:12 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[自作物]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2382</guid>

					<description><![CDATA[自作の言語処理系開発日記、第6回です。 これまでは四則演算など、電卓レベルの機能実装に取り組んでいましたが、いよいよ変数を扱えるようにしていきたいと思います。これでかなりプログラミング言語っぽくなるか ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[
<p>自作の言語処理系開発日記、第6回です。</p>



<p>これまでは四則演算など、電卓レベルの機能実装に取り組んでいましたが、いよいよ変数を扱えるようにしていきたいと思います。これでかなりプログラミング言語っぽくなるかも(・∀・)</p>



<p>今回は新しい仕組みを入れたりと、割と修正がごちゃごちゃしてしまったので、うまくまとめきれていません。ごめんなさい…。</p>



<h2 class="wp-block-heading">変数の実装について</h2>



<p>これまでは即値しか扱っていなかったので、「値が登場すればそれをスタックに積む」という単純な仕組みで事足りていました。しかし、変数を扱うためには、どこかに値を覚えておいて、それを読み書きする仕組みが必要になります。</p>



<p>まず、変数の保存場所ですが、今回はスタックを使います。ただ、変数自体をPush/Popするのではなく、スタックの先頭領域を変数置き場として間借りします（下図）。</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://corgi-lab.com/blog/wp-content/uploads/2020/08/stack_variable.png"><img decoding="async" width="300" height="174" src="https://corgi-lab.com/blog/wp-content/uploads/2020/08/stack_variable.png" alt="" class="wp-image-2383"/></a></figure>
</div>


<p>「C言語のローカル変数はスタックにある」なんていう話を聞きますが、それとほぼ同等の仕組みです。読み書きについては、各変数のスタック中のアドレスに対して行うようにします。</p>



<h2 class="wp-block-heading">実装してみる</h2>



<h3 class="wp-block-heading">トークナイザ</h3>



<p>この処理系では、変数名のルールを以下のようにします。</p>



<ul class="wp-block-list">
<li>開始文字がa~z, A~Z, _のいずれかであること</li>



<li>途中の文字はa~z, A~Z, 0~9, _のいずれかであること</li>



<li>他の予約語と一致しないこと</li>
</ul>



<p>実装自体は難しくないので割愛します。「他の予約語と一致しないこと」というルールがあるので、変数は最後にトークナイズするように注意します。</p>



<h3 class="wp-block-heading">構文解析器</h3>



<p>今回は変数の宣言と代入を実現したいので、生成規則は以下のようにしました。</p>



<div class="graybox">program = expr (&#8220;,&#8221; expr | &#8220;\n&#8221; expr)*<br>expr = ident &#8220;=&#8221; add | add<br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = unary (&#8220;*&#8221; unary | &#8220;/&#8221; unary)*<br>unary = (&#8220;+&#8221; | &#8220;-&#8220;)? primary<br>primary = ident | num | &#8220;(&#8221; add &#8220;)&#8221;</div>



<p>変数を表す<code>ident</code>という記号を定義して、<code>expr</code>という新しい生成規則を追加しました。これで、<code>変数＝式</code>という代入式を扱えるようになります。</p>



<p>実装としては、変数そのものを表すノード（<code>ND_IDENT</code>）と、代入を表すノード（<code>ND_ASSIGN</code>）の2つを新規に定義します。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// ノード関連の定義
typedef enum {
	ND_NUM,			// 数値
	ND_ADD,			// +
	ND_SUB,			// -
	ND_MUL,			// *
	ND_DIV,			// /
	ND_ASSIGN,		// =
	ND_IDENT,		// 識別子
} NodeKind;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// ノード関連の定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_NUM</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 数値</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_ADD</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// +</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_SUB</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// -</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_MUL</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// *</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_DIV</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// /</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_ASSIGN</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// =</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_IDENT</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// 識別子</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> NodeKind</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>あとは生成規則に従って解析処理を実装すればOK。ここまでは割と単純です。</p>



<h3 class="wp-block-heading">コード生成器</h3>



<p>コード生成に関しては、変数の扱いがややこしいです。というのも、変数は置き場所（式の左辺 or 右辺）や、前後の文脈次第でその意味が変わります。</p>



<p>例えば、<code>num=1</code>という式の場合、<code>num</code>は代入先として解釈されるので、その評価値はアドレスです。一方、<code>ret = num+1</code>という式の場合は、<code>num</code>の評価値はそれが保持する値になります。</p>



<p>いま現在の生成規則では、代入式の左辺に来たときだけ変数をアドレスとして解釈すれば良さそうです。それ以外は全て値として解釈します。</p>



<p>ここからは実装です。まず、変数を表す構造体を以下のように定義します。変数名とその長さに加え、その変数のスタック上での位置（アドレス相当）を持たせました。そして、同一変数に対しては同じアドレスでアクセスできるように、変数のリストも定義しておきます。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// 変数定義
typedef struct {
	char* name;		// 変数名
	int len;		// 名前長
	int	offset;		// データ格納先のオフセット
} Variable;

vector vars;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// 変数定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">char*</span><span style="color: #D8DEE9FF"> name</span><span style="color: #81A1C1">;</span><span style="color: #616E88">		// 変数名</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF"> len</span><span style="color: #81A1C1">;</span><span style="color: #616E88">		// 名前長</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">int</span><span style="color: #D8DEE9FF">	offset</span><span style="color: #81A1C1">;</span><span style="color: #616E88">		// データ格納先のオフセット</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> Variable</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">vector vars</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>また、変数に対する読み書きを実現するために、新しい命令としてLOADとSTOREを定義します。LOADはメモリ（スタック中）からレジスタへの値コピー、STOREはその逆です。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="typedef enum {
	OP_PUSH,		// Push（レジスタ値）
	OP_PUSH_I,		// Push（即値）
	OP_POP,			// Pop
	OP_ADD,			// 加算
	OP_SUB,			// 減算
	OP_MUL,			// 乗算
	OP_DIV,			// 除算
	OP_STORE,		// レジスタ→メモリへの書き込み
	OP_LOAD,		// メモリ→レジスタへの読み込み
} OP_CODE;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_PUSH</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// Push（レジスタ値）</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_PUSH_I</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// Push（即値）</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// Pop</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_ADD</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 加算</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_SUB</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 減算</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_MUL</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 乗算</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_DIV</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 除算</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_STORE</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// レジスタ→メモリへの書き込み</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_LOAD</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// メモリ→レジスタへの読み込み</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> OP_CODE</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>そして、代入と識別子に対するコード生成を抜き出すと以下のようになります。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="case ND_ASSIGN:
	gen_var(node-&gt;left);
	gen(node-&gt;right);

	operations.push_back( Operation{ OP_POP, REG_GR1 } );
	operations.push_back( Operation{ OP_POP, REG_GR0 } );
	operations.push_back( Operation{ OP_STORE, REG_GR0, REG_GR1 } );
	operations.push_back( Operation{ OP_PUSH, REG_GR1 } );

	break;

case ND_IDENT:
	gen_var(node);

	operations.push_back( Operation{ OP_POP, REG_GR0 } );
	operations.push_back( Operation{ OP_LOAD, REG_GR1, REG_GR0 } );
	operations.push_back( Operation{ OP_PUSH, REG_GR1 } );

	break;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> ND_ASSIGN:</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">gen_var</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">node</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">left</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">gen</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">node</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">right</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_STORE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_PUSH</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> ND_IDENT:</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">gen_var</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">node</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_LOAD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_PUSH</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span></code></pre></div>



<p>途中に登場する<code>gen_var</code>という関数は識別子ノード専用の関数です。そのノードが示す変数のアドレスをスタックに積みます。</p>



<p>それ以降は、代入式であればアドレスに対するSTORE、それ以外であればアドレスからの値のLOADという形で命令列を出力します。</p>



<h3 class="wp-block-heading">実行系（仮想マシン）</h3>



<p>最後に実行系ですが、今回はスタックを変数領域とそれ以外で分けることにしたので、その境目を示す値が必要です。そこで、その値をベースポインタという名前で扱うことにし、いまは固定でスタックの先頭から16個先としました。つまり、使える変数は最大で16個までです。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="DWORD* bp;					// ベースポインタ
sp = &amp;stack[16];" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">DWORD</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> bp</span><span style="color: #81A1C1">;</span><span style="color: #616E88">					// ベースポインタ</span></span>
<span class="line"><span style="color: #D8DEE9FF">sp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">stack</span><span style="color: #ECEFF4">[</span><span style="color: #B48EAD">16</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>途中、解説をかなり端折ったところもありますが、これで変数を扱うことができるようになりました。まだまだ実装は粗いですが、これで1つのチェックポイントは通過できたかなと思います。</p>



<p>今回の実装は以下のコミットになります。コード全体はこちらをご覧くださいm(_ _)m</p>



<p><a href="https://github.com/corgi0901/rook/commit/dd7ed9e85654f6fa2e48e11afadd4f0c366a8305" target="_blank" rel="noopener noreferrer">変数の実装（dd7ed9e）</a></p>



<p>次回以降は制御構文の実装を視野に機能を追加していく予定です。</p>



<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/self-made/lang-processor-6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>言語処理系をつくろう（第5回）：連続した式の実行</title>
		<link>https://corgi-lab.com/self-made/lang-processor-5/</link>
					<comments>https://corgi-lab.com/self-made/lang-processor-5/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Mon, 10 Aug 2020 09:14:01 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[自作物]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2375</guid>

					<description><![CDATA[自作の言語処理系開発日記の第5回です。 前回までで括弧を含んだ四則演算ができるようになりましたが、このままでは単なる電卓止まりです。ということで、今回は複数の式を連続して実行できる仕組みを実装していき ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[
<p>自作の言語処理系開発日記の第5回です。</p>



<p><a href="https://corgi-lab.com/self-made/lang-processor-4/">前回</a>までで括弧を含んだ四則演算ができるようになりましたが、このままでは単なる電卓止まりです。ということで、今回は複数の式を連続して実行できる仕組みを実装していきたいと思います。</p>



<h2 class="wp-block-heading">生成規則を考える</h2>



<p>これまでは入力全体を1つの式として解釈していましたが、今回は式の区切りを定義して複数の式として解釈できるようにします。</p>



<p>C言語だと「;」や「,」が区切り文字として使われますが、開発中の言語（rook）では「,」と「\n（改行）」を区切り文字とします。それを踏まえて生成規則を考えると、こんな感じになります。</p>



<div class="graybox">program = add (&#8220;,&#8221; add | &#8220;\n&#8221; add)*<br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = unary (&#8220;*&#8221; unary | &#8220;/&#8221; unary)*<br>unary = (&#8220;+&#8221; | &#8220;-&#8220;)? primary<br>primary = num | &#8220;(&#8221; add &#8220;)&#8221;</div>



<p><code>program</code>の生成規則を修正しただけです。<code>add</code>が「,」または「\n」区切りで連続して現れる形にしています。</p>



<h2 class="wp-block-heading">実装してみる</h2>



<p>入力が複数の式になったので、実装も各所を修正する必要があります。具体的には、</p>



<ul class="wp-block-list">
<li>構文解析の結果はノードのリストとする</li>



<li>コード生成は各ノードに対して順に生成するようにする</li>
</ul>



<p>という修正が必要です。</p>



<h3 class="wp-block-heading">構文解析器</h3>



<p>構文解析器は、先述したようにノードのリストとして解析結果を返すようにします。<code>program</code>の生成規則に対応した処理の中で、解析結果を詰めていくようにすればOKです。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="vector&lt;Node*&gt; Parser::program(void)
{
	vector&lt;Node*&gt; nodes;

	nodes.push_back(add());

	while(consume(&quot;,&quot;) || consume(&quot;\n&quot;)){
		nodes.push_back(add());
	}

	return nodes;
};" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">vector</span><span style="color: #ECEFF4">&lt;</span><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> Parser</span><span style="color: #ECEFF4">::</span><span style="color: #88C0D0">program</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">void</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	vector</span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*&gt;</span><span style="color: #D8DEE9FF"> nodes</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">nodes</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">while</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #D8DEE9">nodes</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> nodes</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<h3 class="wp-block-heading">コード生成</h3>



<p>コード生成は構文解析器の結果（ノード）を1つ1つ処理していけばよいだけですが、1つだけ注意が必要なことがあります。</p>



<p>スタックマシンでは、1つの式の評価結果がスタックトップに残されます。そのため、複数の式を連続して実行したときには、その分だけスタックに評価結果が残されてしまいます。</p>



<p>これを避けるために、1つの式（ノード）に対応した命令列の最後に、スタックから値をポップする命令を追加するようにします（下記コードの8行目）。今回は汎用レジスタ（GR0）に結果を退避するようにしました。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="vector&lt;Operation&gt; Generator::codegen(vector&lt;Node*&gt; &amp;nodes)
{
	vector&lt;Node*&gt;::iterator node;

	for(node = nodes.begin(); node != nodes.end(); node++){
		gen(*node);
		operations.push_back( Operation{ OP_POP, REG_GR0 } );
	}

	return operations;
};" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">vector</span><span style="color: #ECEFF4">&lt;</span><span style="color: #D8DEE9FF">Operation</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> Generator</span><span style="color: #ECEFF4">::</span><span style="color: #88C0D0">codegen</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">vector</span><span style="color: #ECEFF4">&lt;</span><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">nodes</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	vector</span><span style="color: #ECEFF4">&lt;</span><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #ECEFF4">&gt;::</span><span style="color: #D8DEE9FF">iterator node</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">for</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">nodes</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">begin</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> node </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">nodes</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">end</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> node</span><span style="color: #81A1C1">++</span><span style="color: #ECEFF4">){</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #88C0D0">gen</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">node</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> operations</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>これで連続した式を実行できるようになったため、</p>



<div class="graybox">1+1, 2+2, 3+3</div>



<p>のようなカンマ区切りの式や</p>



<div class="graybox">1+1<br />2+2<br />3+3</div>



<p>のような改行区切りの入力が扱えるようになりました。まだ変数が扱えないのでプログラムっぽくはないですが、電卓止まりからちょっとステップアップしましたね(・∀・)。今回の実装のコミットは以下になります。</p>



<p><a href="https://github.com/corgi0901/rook/commit/95c14f73571c8f2cedeaf89a23548a6bd5f4dcf7" target="_blank" rel="noopener noreferrer">連続した式の実行に対応（95c14f7）</a></p>



<p>いよいよ、次回は変数に対応させていきたいと思います。</p>



<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/self-made/lang-processor-5/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>言語処理系をつくろう（第4回）：括弧付き計算と単項演算子</title>
		<link>https://corgi-lab.com/self-made/lang-processor-4/</link>
					<comments>https://corgi-lab.com/self-made/lang-processor-4/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Mon, 03 Aug 2020 14:27:18 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[自作物]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2363</guid>

					<description><![CDATA[自作の言語処理系開発日記の第4回です。前回までで乗除算を実装できたので、この調子でもう少し複雑な計算に対応したいと思います。今回はそれぞれの実装が少ないので、一気に2つのステップを進めます。 括弧を含 ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[
<p>自作の言語処理系開発日記の第4回です。<a href="https://corgi-lab.com/self-made/lang-processor-3/">前回</a>までで乗除算を実装できたので、この調子でもう少し複雑な計算に対応したいと思います。今回はそれぞれの実装が少ないので、一気に2つのステップを進めます。</p>



<h2 class="wp-block-heading">括弧を含む計算</h2>



<p>これまでの実装では、乗除算は必ず加減算に先立って実行されます。しかし、それでは不十分なので、括弧を含む計算（例：<code>（1+2)*3</code>）を実行できるようにします。</p>



<h3 class="wp-block-heading">生成規則をいじる</h3>



<p>今回も構文解析器の生成規則を修正することで、括弧付きの計算に対応させます。前回の乗除算を実装した際には、乗除算が加減算より深くで展開されるように生成規則を変えることで、計算の優先順位を表現しました。今回も考え方は同じです。</p>



<p>まず、前回までの生成規則はこちら。</p>



<div class="graybox">program = add program = add<br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = num (&#8220;*&#8221; num | &#8220;/&#8221; num)*</div>



<p>そして、括弧付きの計算に対応した生成規則が以下になります。</p>



<div class="graybox">program = add<br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = primary (&#8220;*&#8221; primary | &#8220;/&#8221; primary)*<br><span class="st-aka">primary = num | &#8220;(&#8221; add &#8220;)&#8221;</span></div>



<p><code>primary</code>という新しい生成規則を定義し、<code>mul</code>の中にあった<code>num</code>をそれに置き換えています。<code>primary</code>は<code>num</code>と並列で括弧付きの<code>add</code>を定義しているため、「括弧付きの計算が一番深い＝一番優先度が高い」という規則になっています。</p>



<p>実装はこれまでと変わらずなので割愛しますが、気になる方は以下のコミットをご覧ください。</p>



<p><a href="https://github.com/corgi0901/rook/commit/47d1b06e1be1dca01c11f18a73e6a47590603963" target="_blank" rel="noopener noreferrer">括弧付きの計算に対応（47d1b06）</a></p>



<h2 class="wp-block-heading">単項演算子（+と-）</h2>



<p>括弧付きの計算は実行できるようになりましたが、これだけでは<code>-5+3</code>や<code>1++3</code>のような式が計算できません。これらを扱うためには単項演算子としての<code>+</code>と<code>-</code>を実装する必要があります。</p>



<h3 class="wp-block-heading">生成規則をいじる</h3>



<p>こちらも生成規則をいじることで解決したいのですが、ややこしいのが加減算の<code>+</code>と<code>-</code>との棲み分けです。文字は同じでも、式中の位置や文脈によって解釈が変わるので、それを上手に生成規則に落とし込む必要があります。</p>



<p>最初はこんな規則を考えましたが、結論から言うとダメでした。</p>



<div class="graybox">program = add<br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = primary (&#8220;*&#8221; primary | &#8220;/&#8221; primary)*<br>primary = num | &#8220;+&#8221; num | &#8220;-&#8221; num | &#8220;(&#8221; add &#8220;)&#8221;</div>



<p>括弧付きの計算で作った<code>primary</code>の規則中、<code>+</code>付きの<code>num</code>と<code>-</code>付きの<code>num</code>を入れることでパッと見うまくいっていたのですが、<code>-(1+3)</code>のような式がパースできないことに気づき、ボツになりました(´・ω・)</p>



<p>括弧付きの計算にも対応しようと思うと、primaryの定義を</p>



<div class="graybox">primary = num | &#8220;+&#8221; num | &#8220;-&#8221; num | &#8220;(&#8221; add &#8220;)&#8221; | &#8220;+(&#8221; add &#8220;)&#8221; | &#8220;-(&#8221; add &#8220;)&#8221;</div>



<p>とすれば良いのですが、ちょっと冗長です。そこで、<code>unary</code>という定義を追加して以下のようにするとすっきりします。</p>



<div class="graybox">program = add<br>add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br>mul = unary (&#8220;*&#8221; unary | &#8220;/&#8221; unary)*<br>unary = (&#8220;+&#8221; | &#8220;-&#8220;)? primary<br>primary = num | &#8220;(&#8221; add &#8220;)&#8221;</div>



<p>生成規則中の<code>？</code>は、直前の項目が0回または1回登場するという意味です。<code>unary</code>だけを抜き出すと、実装はこんな感じになりました。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Node* Parser::unary(void)
{
	if(consume(&quot;+&quot;)){
		return primary();
	}
	else if(consume(&quot;-&quot;)){
		Node* zero = new Node();
		zero-&gt;kind = ND_NUM;
		zero-&gt;val = 0;
		Node* node = new Node{ ND_SUB, zero, primary() };
		return node;
	}
	else{
		return primary();
	}
};" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> Parser</span><span style="color: #ECEFF4">::</span><span style="color: #88C0D0">unary</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">void</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">+</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">primary</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">		Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> zero </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Node</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #D8DEE9">zero</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">kind</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> ND_NUM</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #D8DEE9">zero</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">val</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_SUB</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> zero</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">primary</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> node</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">else</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">primary</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p><code>+</code>については特に何もしなくてOKですが、<code>-</code>については0からの引き算として実装しています。全実装は以下をご覧ください。</p>



<p><a href="https://github.com/corgi0901/rook/compare/8d3a65224e377f80916f6a463bfdff31dd47cdca...master" target="_blank" rel="noopener noreferrer">単項演算子の実装</a></p>



<p>これで、整数レベルの四則演算はすべてカバーできるようになりました。簡単な電卓レベルまで進化したことになるので、ちょっと嬉しいですね。</p>



<p>次回からはもう少し言語処理系っぽい機能を入れ込んでいこうと思います。</p>



<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/self-made/lang-processor-4/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>言語処理系をつくろう（第3回）：乗除算を実装する</title>
		<link>https://corgi-lab.com/self-made/lang-processor-3/</link>
					<comments>https://corgi-lab.com/self-made/lang-processor-3/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Sun, 02 Aug 2020 08:09:57 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[自作物]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2354</guid>

					<description><![CDATA[自作の言語処理系開発日記の第3回です。前回は加減算を実装したので、今回は乗除算の実装にチャレンジしていきます。 実装してみる 今回の実装において、トークナイザ・コード生成器・実行系（仮想マシン）につい ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[<p>自作の言語処理系開発日記の第3回です。<a href="https://corgi-lab.com/self-made/lang-processor-2/">前回</a>は加減算を実装したので、今回は乗除算の実装にチャレンジしていきます。</p>
<h2>実装してみる</h2>
<p>今回の実装において、トークナイザ・コード生成器・実行系（仮想マシン）については加減算のときと変わりません。単純に各種定義を追加して、それを扱えるようにしてあげるだけです。</p>
<p>一方、構文解析器についてはちょっとややこしいので、そこだけ解説します。</p>
<h3>構文解析器</h3>
<p>加減算では演算の優先順位がなかったので、単純に左結合（＝左から順に計算していく）で処理していけばOKでした。しかし、乗除算が入ると演算の優先順位が生まれるので、これを上手くさばくには工夫が必要です。</p>
<p>今回は優先度を考慮した生成規則を考えることで、これを解決していきます。前回までの生成規則は以下の通りです。</p>
<div class="graybox">program = add<br />
add = num (&#8220;+&#8221; num | &#8220;-&#8221; num)*</div>
<p>この定義に従って構文木を展開する順序と、実行時の処理順（評価順）を比較すると、以下のような感じになります。</p>
<ul>
<li>構文木の展開順：program → add → num</li>
<li>実行時の処理順：num → add → program</li>
</ul>
<p>このように、両者の順序は真逆になります。つまり、生成規則上で深くにあればあるほど、実行時には優先的に評価されます。この考え方を使えば、生成規則を以下のようにすることで、乗除算は実現可能です。</p>
<div class="graybox">program = add<br />
add = mul (&#8220;+&#8221; mul | &#8220;-&#8221; mul)*<br />
mul = num (&#8220;*&#8221; num | &#8220;/&#8221; num)*</div>
<p>新たに<code>mul</code>という乗除算の規則を追加し、<code>add</code>中の<code>num</code>を<code>mul</code>に置き換えました。こうすることで、加減算よりも深くで乗除算が展開されるため、実行時の優先度は乗除算の方が高くなります。</p>
<p>コードはこれまで通り、ノード種別の追加と上記の生成規則に対応した処理を実装するだけなので割愛します。</p>
<p>これで、乗除算を含んだ式を扱えるようになりました。以前に言語処理系の自作にチャレンジしたときは、この優先度にとても悩まされたのですが、生成規則でそれを解決するという方法にちょっと感動してしまいました。当時はそんなことは知らなかったので思いつきもしませんでしたが、やっぱり勉強は大事ですね…。</p>
<p>今回の実装のコミットは以下です。コード全体はこちらをご覧くださいm(_ _)m</p>
<p><a href="https://github.com/corgi0901/rook/commit/3862655790f17ec6e8c34b9bcb0f8a2bda57a022" target="_blank" rel="noopener noreferrer">乗除算の実装（3862655）</a></p>
<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/self-made/lang-processor-3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>言語処理系をつくろう（第2回）：加減算を実装する</title>
		<link>https://corgi-lab.com/self-made/lang-processor-2/</link>
					<comments>https://corgi-lab.com/self-made/lang-processor-2/#respond</comments>
		
		<dc:creator><![CDATA[Ryo Yoneyama]]></dc:creator>
		<pubDate>Sat, 01 Aug 2020 12:53:16 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[自作物]]></category>
		<guid isPermaLink="false">https://corgi-lab.com/?p=2342</guid>

					<description><![CDATA[自作の言語処理系開発日記の第2回です。前回は処理系全体の骨格と、数値の読み込みを実装しました。今回は次のステップとして、加減算を扱えるようにしたいと思います。 実装してみる トークナイザ 前回までのト ... <p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></description>
										<content:encoded><![CDATA[
<p>自作の言語処理系開発日記の第2回です。<a href="https://corgi-lab.com/self-made/lang-processor-1/">前回</a>は処理系全体の骨格と、数値の読み込みを実装しました。今回は次のステップとして、加減算を扱えるようにしたいと思います。</p>



<h2 class="wp-block-heading">実装してみる</h2>



<h3 class="wp-block-heading">トークナイザ</h3>



<p>前回までのトークナイザでは数値しか扱うことができないので、「＋」や「-」などの記号をトークン化できるようにします。</p>



<p>まずは、トークン定義を追加します。加算と減算それぞれで追加しても良いのですが、後段の構文解析で特に区別する必要がないので、演算子という形で一括りにします。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// トークン関連の定義
typedef enum {
	TK_NUM,			// 数値
	TK_OP,			// 演算子
	TK_EOF,			// 終端
} TokenKind;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// トークン関連の定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">TK_NUM</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 数値</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">TK_OP</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 演算子</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">TK_EOF</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 終端</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> TokenKind</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>続いて、トークナイズの実処理です。「＋」や「-」などの記号を見つけたらそこでトークン化するだけなので、以下のようなコードを追加します。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="if(strncmp(input, &quot;+&quot;, 1) == 0){
	Token token = { TK_OP, input, 1 };
	tokens.push_back(token);
	input++;
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">strncmp</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">input</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">+</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">){</span></span>
<span class="line"><span style="color: #D8DEE9FF">	Token token </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> TK_OP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> input</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">tokens</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">token</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	input</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<h3 class="wp-block-heading">構文解析器</h3>



<p>次は構文解析です。ここも前回は数値1つだけでしたが、今回は左辺と右辺を持った木構造を作る必要があります。</p>



<p>まずは、加減算を考慮した生成規則を考えます。BNF（っぽいもの）を使って書くとこんな感じです。</p>



<div class="graybox">program = add<br>add = num (&#8220;+&#8221; num | &#8220;-&#8221; num)*</div>



<p>今回は新たに<code>add</code>という規則を追加しました。定義の中に出てくる<code>｜</code>は「OR」の意味、<code>＊</code>は0回以上の繰り返しの意味です。加減算を含む式は、「数値＋数値」か「数値-数値」が連続している形になるので、この定義で表現できることになります。</p>



<p>このあたりの考え方は、私が参考にしているオンラインブック「<a href="https://www.sigbus.info/compilerbook#%E6%96%87%E6%B3%95%E3%81%AE%E8%A8%98%E8%BF%B0%E6%96%B9%E6%B3%95%E3%81%A8%E5%86%8D%E5%B8%B0%E4%B8%8B%E9%99%8D%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90" target="_blank" rel="noopener noreferrer">低レイヤを知りたい人のためのCコンパイラ作成入門</a>」がとてもわかりやすいので、ぜひ読んでみてください。</p>



<p>生成規則が定義できたら、それに従ってトークン列をパースする処理を実装します。まずはノードとして、加算・減算それぞれの定義を追加します。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// ノード関連の定義
typedef enum {
	ND_NUM,			// 数値
	ND_ADD,			// +
	ND_SUB,			// -
} NodeKind;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// ノード関連の定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_NUM</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 数値</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_ADD</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// +</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">ND_SUB</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// -</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> NodeKind</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>続いてパース処理です。前回同様、生成規則をそのまま落とし込む形で実装します。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Node* Parser::program(void)
{
	return add();
};

Node* Parser::num(void)
{
	Node* node = new Node();
	node-&gt;kind = ND_NUM;
	node-&gt;val = atoi(token-&gt;str);
	token++;
	return node;
};

Node* Parser::add(void)
{
	Node* node = num();

	while(1){
		if(consume(&quot;+&quot;)){
			node = new Node{ ND_ADD, node, num() };
		}
		else if(consume(&quot;-&quot;)){
			node = new Node{ ND_SUB, node, num() };
		}
		else{
			return node;
		}
	}
};" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> Parser</span><span style="color: #ECEFF4">::</span><span style="color: #88C0D0">program</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">void</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> Parser</span><span style="color: #ECEFF4">::</span><span style="color: #88C0D0">num</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">void</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Node</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">node</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">kind</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> ND_NUM</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">node</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">val</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">atoi</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">token</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">str</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	token</span><span style="color: #81A1C1">++;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> node</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> Parser</span><span style="color: #ECEFF4">::</span><span style="color: #88C0D0">add</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">void</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	Node</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">num</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">while</span><span style="color: #ECEFF4">(</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">){</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">+</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">			node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_ADD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> node</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">num</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">consume</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)){</span></span>
<span class="line"><span style="color: #D8DEE9FF">			node </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> Node</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> ND_SUB</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> node</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">num</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #81A1C1">else</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">			</span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> node</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">		</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>正直なところ、ここも先述したオンラインブックの実装を参考（というか、ほぼ丸パクリ）にしました。</p>



<p>どうしてこの実装で構文木が作れるのかしばらく分からなかったのですが、「左結合＝左の枝が深くなっていくように木を伸ばす」という視点で見たら、なんとなく納得がいきました。う〜ん、難しい…。</p>



<h3 class="wp-block-heading">コード生成器＋実行系（仮想マシン）</h3>



<p>次はコード生成と実行系（仮想マシン）です。スタックマシンにおいて加減算は、</p>



<ul class="wp-block-list">
<li>スタックの上から2つ値を取り出す（ポップする）</li>



<li>取り出した値を加算・減算した結果をスタックに積む</li>
</ul>



<p>という流れで処理されます。前回まではスタックに積む（プッシュ）しか実装していないので、ポップ・加算・減算の3つを新規に実装する必要があります。</p>



<p>まず、仮想マシンに新しい仕組みを実装します。先述したように、加減算は「スタックからデータを取り出す」という処理が入るので、取り出した値を記憶する仕組みが必要です。</p>



<p>実際のCPUでは、こうした用途のために汎用レジスタというものがあります。そこで、今回は仮想マシンに汎用レジスタを実装します。いまのところ、加減算の左辺用と右辺用の2つがあれば良いので、以下のようなレジスタ定義を追加しておきます。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// レジスタ関連定義
typedef enum {
	REG_GR0 = 0,
	REG_GR1,
	REG_NUM,		// レジスタ数
} REG_NAME;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// レジスタ関連定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">REG_GR0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">REG_GR1</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">REG_NUM</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// レジスタ数</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> REG_NAME</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>そして、仮想マシン内に汎用レジスタとして使える領域を実装すれば準備OKです。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="DWORD reg[REG_NUM];	// レジスタ" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">DWORD </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">REG_NUM</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">;</span><span style="color: #616E88">	// レジスタ</span></span></code></pre></div>



<p>続いて命令まわりです。命令定義の追加に加えて、命令そのものに第2のオペランドを追加します。加減算の右辺値を指定するためです。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="// 命令関連の定義
typedef enum {
	OP_PUSH,		// Push
	OP_POP,			// Pop
	OP_ADD,			// 加算
	OP_SUB,			// 減算
} OP_CODE;

typedef struct {
	BYTE opcode;	// オペコード
	DWORD operand;	// オペランド
	DWORD operand2;	// 第2オペランド
} Operation;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// 命令関連の定義</span></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_PUSH</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">		// Push</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// Pop</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_ADD</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 加算</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">OP_SUB</span><span style="color: #ECEFF4">,</span><span style="color: #616E88">			// 減算</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> OP_CODE</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	BYTE opcode</span><span style="color: #81A1C1">;</span><span style="color: #616E88">	// オペコード</span></span>
<span class="line"><span style="color: #D8DEE9FF">	DWORD operand</span><span style="color: #81A1C1">;</span><span style="color: #616E88">	// オペランド</span></span>
<span class="line"><span style="color: #D8DEE9FF">	DWORD operand2</span><span style="color: #81A1C1">;</span><span style="color: #616E88">	// 第2オペランド</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> Operation</span><span style="color: #81A1C1">;</span></span></code></pre></div>



<p>これを踏まえての命令生成処理ですが、加算の場合は以下のような実装を追加すればOKです。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="case ND_ADD:
	codegen(node-&gt;left);
	codegen(node-&gt;right);

	operations.push_back( Operation{ OP_POP, REG_GR0 } );
	operations.push_back( Operation{ OP_POP, REG_GR1 } );
	operations.push_back( Operation{ OP_ADD, REG_GR0, REG_GR1 } );

	break;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> ND_ADD:</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">codegen</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">node</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">left</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">codegen</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">node</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">right</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_POP</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #D8DEE9">operations</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">push_back</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF"> Operation{ OP_ADD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> REG_GR1 } </span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span></code></pre></div>



<p>ノードの左辺値と右辺値を先に展開することがポイントです。こうすることで、実行時にスタックに左辺値と右辺値の評価結果が積まれている状態にできるので、あとはポップ命令と加算命令を出力すればOKです。</p>



<p>最後に仮想マシン内で、追加した命令に対する実処理を実装します。例えば、加算は以下のような感じです。オペランドで指定された2つのレジスタを足してスタックに積みます。</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-Roboto-Mono.ttf" style="font-size:.875rem;font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:4;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="case OP_ADD:
{
	push(reg[op-&gt;operand] + reg[op-&gt;operand2]);
	break;
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">case</span><span style="color: #D8DEE9FF"> OP_ADD:</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #88C0D0">push</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9">op</span><span style="color: #ECEFF4">-&gt;</span><span style="color: #D8DEE9">operand2</span><span style="color: #ECEFF4">])</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #81A1C1">break;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p>これで加減算を処理できるようになりました。ちょっとは言語処理系っぽくなったかなと思います。</p>



<p>今回のコードのコミットは以下です。コード全体はこちらをご覧くださいm(_ _)m</p>



<p><a href="https://github.com/corgi0901/rook/commit/5be1d9702002a5726179c69e815d5646fb38f77e" target="_blank" rel="noopener noreferrer">加減算を実装（5be1d97）</a></p>



<p>ではでは</p>
<p>Copyright &copy; 2026 <a href="https://corgi-lab.com">Corgi Lab. ～備忘録のための技術ブログ～</a> All Rights Reserved.</p>]]></content:encoded>
					
					<wfw:commentRss>https://corgi-lab.com/self-made/lang-processor-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
