<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Binray</title>
  
  <subtitle>二进制蕾伊</subtitle>
  <link href="https://blog.reilkay.com/atom.xml" rel="self"/>
  
  <link href="https://blog.reilkay.com/"/>
  <updated>2022-04-08T13:30:08.000Z</updated>
  <id>https://blog.reilkay.com/</id>
  
  <author>
    <name>Ray</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>在腾讯桌面整理上使用Python遇到的坑</title>
    <link href="https://blog.reilkay.com/PythonErrorInDeskGo/"/>
    <id>https://blog.reilkay.com/PythonErrorInDeskGo/</id>
    <published>2022-04-08T13:30:08.000Z</published>
    <updated>2022-04-08T13:30:08.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近用Python写了个小的GUI程序，用<code>Pyinstaller</code>打包之后，准备拖到桌面试用，结果竟然抛了异常，顿时感到很奇怪。因为按道理来说这个异常已经在代码里处理过了，于是开始排查问题。</p><span id="more"></span><h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>这段时间疯狂在网上看剧，下载的剧名总是乱七八糟的，而我使用的播放器又只会将名字大致相同的视频一同加入播放列表。为了能方便自动播放下一集，同时也方便做归档，于是便有了批量将文件改名的需求。</p><p>由于系统自带的批量重命名实在不尽如人意，具体表现为文件名后的序号会自带括号，非常有碍观瞻（强迫症了属于是），所以又去网上找了一下现成的，要么界面过于复杂，要么就是缺少所需的功能，于是自己用Python整了一个。</p><p>根据之前的经验，如果使用自带的<code>tkinter</code>库制作图形界面会相当丑，于是选用了<code>PySide6</code>进行GUI的制作。</p><p>偷偷打个广告：<a href="https://github.com/Reilkay/file-rename-gui">批量重命名助手-项目地址-Github</a></p><h2 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h2><p>如同前言中所说，在桌面双击打开该程序时，程序抛出了异常，报错信息如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Traceback (most recent call last):</span><br><span class="line">  File <span class="string">&quot;utils\config.py&quot;</span>, line 17, <span class="keyword">in</span> get</span><br><span class="line">  File <span class="string">&quot;toml\decoder.py&quot;</span>, line 133, <span class="keyword">in</span> load</span><br><span class="line">FileNotFoundError: [Errno 2] No such file or directory: <span class="string">&#x27;./config.toml&#x27;</span></span><br><span class="line"></span><br><span class="line">During handling of the above exception, another exception occurred:</span><br><span class="line"></span><br><span class="line">Traceback (most recent call last):</span><br><span class="line">  File <span class="string">&quot;main.py&quot;</span>, line 7, <span class="keyword">in</span> &lt;module&gt;</span><br><span class="line">  File <span class="string">&quot;window\main_window.py&quot;</span>, line 28, <span class="keyword">in</span> __init__</span><br><span class="line">  File <span class="string">&quot;utils\config.py&quot;</span>, line 20, <span class="keyword">in</span> get</span><br><span class="line">  File <span class="string">&quot;utils\config.py&quot;</span>, line 39, <span class="keyword">in</span> init_config_file</span><br><span class="line">PermissionError: [Errno 13] Permission denied: <span class="string">&#x27;./config.toml&#x27;</span></span><br></pre></td></tr></table></figure><p>然而，我是处理过这个异常的（事实上相当于我是在故意利用程序抛出的异常，来检测是否有配置文件存在，然后对配置文件进行一个初始化），该部分代码如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get</span>(<span class="params">self</span>) -&gt; dict:</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">    config = toml.load(self.__path)</span><br><span class="line">    <span class="keyword">except</span> FileNotFoundError:</span><br><span class="line">    self.init_config_file()</span><br><span class="line">    config = toml.load(self.__path)</span><br><span class="line">    <span class="keyword">return</span> config</span><br></pre></td></tr></table></figure><p>于是我重新看了下程序抛出的异常，发现了下面这个部分：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">During handling of the above exception, another exception occurred:</span><br><span class="line"></span><br><span class="line">Traceback (most recent call last):</span><br><span class="line">  File <span class="string">&quot;main.py&quot;</span>, line 7, <span class="keyword">in</span> &lt;module&gt;</span><br><span class="line">  File <span class="string">&quot;window\main_window.py&quot;</span>, line 28, <span class="keyword">in</span> __init__</span><br><span class="line">  File <span class="string">&quot;utils\config.py&quot;</span>, line 20, <span class="keyword">in</span> get</span><br><span class="line">  File <span class="string">&quot;utils\config.py&quot;</span>, line 39, <span class="keyword">in</span> init_config_file</span><br><span class="line">PermissionError: [Errno 13] Permission denied: <span class="string">&#x27;./config.toml&#x27;</span></span><br></pre></td></tr></table></figure><p>原来是处理异常的过程中又抛出了<code>PermissionError</code>的异常，那么为什么明明是在桌面上还会有没有权限的错误呢？</p><h2 id="问题原因探索"><a href="#问题原因探索" class="headerlink" title="问题原因探索"></a>问题原因探索</h2><p>经过长时间的百思不得其解之后，我偶然在文件资源管理器中打开了桌面的路径，并在此处执行了打包生成的<code>.exe</code>文件。</p><p>震惊！并没有出现任何错误，配置文件也十分正常的生成了。</p><p>这时我才终于意识到是我先前为了整理桌面安装的“腾讯桌面整理”导致的问题，随后我又使用该软件的文件映射功能，将D盘上的一个文件夹（D:/test）映射到桌面上进行测试。结果在同样的路径下，用腾讯桌面整理打开该程序则会抛出<code>PermissionError</code>的异常，而在文件夹中打开则不会有问题。终于发现了导致这个问题的元凶就是腾讯桌面整理，那么为什么会出现这种问题呢？我又接着写了一个小程序来探究。</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MainWindow</span>(<span class="params">QMainWindow, Ui_MainWindow</span>):</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, parent=<span class="literal">None</span></span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__(parent)</span><br><span class="line">        self.setupUi(self)</span><br><span class="line"></span><br><span class="line">        self.setWindowTitle(<span class="string">&#x27;测试&#x27;</span>)</span><br><span class="line">        self.argv.setText(sys.argv[<span class="number">0</span>])</span><br><span class="line">        self.cwd.setText(os.getcwd())</span><br><span class="line">        self.abspath.setText(os.path.abspath(<span class="string">&#x27;.&#x27;</span>))</span><br></pre></td></tr></table></figure><p>这里分别使用了三种方式来获取当前程序运行的路径，最终得到的结果如下：</p><ul><li><p>正常在文件夹中开启</p><p><img src="https://s2.loli.net/2022/04/08/ROQcXiu8KTrE1CU.png" alt="image.png"></p></li><li><p>在腾讯桌面整理中打开</p><p><img src="https://s2.loli.net/2022/04/08/sUxNSLHD7EYTZQh.png" alt="image.png"></p></li></ul><p>使用<code>Process Expolorer</code>查看该测试程序（在腾讯桌面整理中打开）的路径，也得出同样的结果，如下图所示：</p><p><img src="https://s2.loli.net/2022/04/08/9fA6JSqdTYWPcQz.png" alt="image.png"></p><p>顺着当前路径，最终是找到了腾讯桌面整理的安装路径下。至此，就可以理解出错的原因，由于程序的当前工作路径在<code>C:\Program Files (x86)</code>下，所以并没有新建文件的权限。</p><h2 id="具体原因分析"><a href="#具体原因分析" class="headerlink" title="具体原因分析"></a>具体原因分析</h2><p>这里也想了很久也不明白为什么，腾讯桌面整理的原理到底是什么？在网上查了查后，我大致猜想如下：</p><p>腾讯桌面整理劫持了系统自带的桌面（或在上方覆盖了一层？），当我在桌面上双击打开应用是，是由腾讯桌面整理的程序启动了我要打开的程序。这样就导致了程序的当前路径和启动路径不一致（例如：由<code>SOME PATH/A/a.exe</code>启动了<code>SOME PATH/B/b.exe</code>，那么，<code>b.exe</code>的当前路径就为<code>SOME PATH/A</code>，但启动路径仍为<code>SOME PATH/B</code>）</p><p>所以总结来说，在应用编写时，更好的选择是使用程序的启动路径，以避免在相互调用时出现的”灵异现象“。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;最近用Python写了个小的GUI程序，用&lt;code&gt;Pyinstaller&lt;/code&gt;打包之后，准备拖到桌面试用，结果竟然抛了异常，顿时感到很奇怪。因为按道理来说这个异常已经在代码里处理过了，于是开始排查问题。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Python" scheme="https://blog.reilkay.com/tags/Python/"/>
    
    <category term="程序开发" scheme="https://blog.reilkay.com/tags/%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91/"/>
    
  </entry>
  
  <entry>
    <title>Windows Terminal美化</title>
    <link href="https://blog.reilkay.com/BeautifyWindowsTerminal/"/>
    <id>https://blog.reilkay.com/BeautifyWindowsTerminal/</id>
    <published>2021-03-19T08:34:00.000Z</published>
    <updated>2021-03-19T08:34:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>由于去年使用过一段时间的ArchLinux，让我对Linux系统的自由度有了很深的认识，从桌面到系统的各项配置，都可以按照自己的喜好进行配置，像是桌面的各种工具，图标排列，动画，开机界面等等。这次因为一些原因需要在Windows上完成一些工作，恰好又重装了系统，于是就捣鼓了一下Win下的命令行，让它也美观起来~</p><span id="more"></span><h2 id="预览"><a href="#预览" class="headerlink" title="预览"></a>预览</h2><p><img src="https://www.picbed.cn/images/2021/03/23/preview.webp" alt="myWinTerminal"> </p><h2 id="安装Windows-Terminal"><a href="#安装Windows-Terminal" class="headerlink" title="安装Windows Terminal"></a>安装Windows Terminal</h2><p>在官方 <a href="https://github.com/microsoft/terminal">README</a> 中，安装Windows Terminal有如下方法：</p><ul><li>Microsoft Store（推荐）</li><li>Github</li><li>winget</li><li>Chocolatey</li><li>Scoop</li></ul><p>最简单的方法就是直接打开Store，下载并安装Windows Terminal了。</p><h2 id="Windows-Terminal美化"><a href="#Windows-Terminal美化" class="headerlink" title="Windows Terminal美化"></a>Windows Terminal美化</h2><h3 id="主题美化"><a href="#主题美化" class="headerlink" title="主题美化"></a>主题美化</h3><p>打开Windows Terminal，在最上方一列点击向下的箭头，点击设置。</p><blockquote><p>这里推荐安装vscode用于配置文件的编辑，当然使用自己习惯的编辑器也可。</p></blockquote><p>将主题配置置于”schemes“中：</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Add custom color schemes to this array.</span></span><br><span class="line">    <span class="comment">// To learn more about color schemes, visit https://aka.ms/terminal-color-schemes</span></span><br><span class="line">&quot;schemes&quot;: []</span><br></pre></td></tr></table></figure><p>这里分享几个主题网站：</p><ul><li><a href="https://windowsterminalthemes.dev/">Windows Terminal Themes</a> </li><li><a href="https://terminalsplash.com/">TerminalSplash</a> </li></ul><p>再分享一下自己用的主题：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;Night Owlish Light&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;background&quot;</span>: <span class="string">&quot;#FFFFFF&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;black&quot;</span>: <span class="string">&quot;#011627&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;blue&quot;</span>: <span class="string">&quot;#4876D6&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightBlack&quot;</span>: <span class="string">&quot;#7A8181&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightBlue&quot;</span>: <span class="string">&quot;#5CA7E4&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightCyan&quot;</span>: <span class="string">&quot;#00C990&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightGreen&quot;</span>: <span class="string">&quot;#49D0C5&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightPurple&quot;</span>: <span class="string">&quot;#697098&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightRed&quot;</span>: <span class="string">&quot;#F76E6E&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightWhite&quot;</span>: <span class="string">&quot;#989FB1&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;brightYellow&quot;</span>: <span class="string">&quot;#ca9e00&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;cyan&quot;</span>: <span class="string">&quot;#08916A&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;foreground&quot;</span>: <span class="string">&quot;#403F53&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;green&quot;</span>: <span class="string">&quot;#2AA298&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;purple&quot;</span>: <span class="string">&quot;#403F53&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;red&quot;</span>: <span class="string">&quot;#D3423E&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;white&quot;</span>: <span class="string">&quot;#7A8181&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;yellow&quot;</span>: <span class="string">&quot;#9c6c03&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>添加完主题后，在”profiles“项下，将<code>&quot;colorScheme&quot;: &quot;Night Owlish Light&quot;</code> 置于”defaults“中（应用于全局）</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&quot;defaults&quot;: &#123;</span><br><span class="line">            <span class="comment">// Put settings here that you want to apply to all profiles.</span></span><br><span class="line">            &quot;colorScheme&quot;: &quot;Night Owlish Light&quot;,</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure><p>或置于”list“下包含”Windows PowerShell“的块中（应用于PowerShell）即可。</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&quot;list&quot;: [</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// Make changes here to the powershell.exe profile.</span></span><br><span class="line">                <span class="attr">&quot;guid&quot;</span>: <span class="string">&quot;&#123;61c54bbd-c2c6-5271-96e7-009a87ff44bf&#125;&quot;</span>,</span><br><span class="line">                <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;Windows PowerShell&quot;</span>,</span><br><span class="line">                <span class="attr">&quot;commandline&quot;</span>: <span class="string">&quot;powershell.exe&quot;</span>,</span><br><span class="line">                <span class="attr">&quot;hidden&quot;</span>: <span class="literal">false</span>,</span><br><span class="line"><span class="attr">&quot;colorScheme&quot;</span>: <span class="string">&quot;Night Owlish Light&quot;</span>,</span><br><span class="line">            &#125;,</span><br></pre></td></tr></table></figure><h3 id="其他设置"><a href="#其他设置" class="headerlink" title="其他设置"></a>其他设置</h3><blockquote><p>注意：如果设置透明不生效，可能需要到 Windows 设置-&gt;个性化-&gt;颜色 中打开 <code>透明效果</code> 开关。</p></blockquote><p>同时还可以在这两处配置其他设置，如：</p><ul><li>字体(下文配置oh-my-posh需要powerline字体)：<code>&quot;fontFace&quot;: &quot;MesloLGMDZ Nerd Font Mono&quot;</code></li><li>亚克力效果(半透明)：<code>&quot;useAcrylic&quot;: true</code></li><li>透明度：<code>&quot;acrylicOpacity&quot;: 0.6</code></li><li>光标样式：<code>&quot;cursorShape&quot;: &quot;bar&quot;</code> </li><li>光标颜色：<code>&quot;cursorColor&quot; : &quot;#000000&quot;</code></li><li>背景图片：<code>&quot;backgroundImage&quot; : &quot;Image-Path/image.png&quot;</code></li></ul><p>更多设置可以参考<a href="https://docs.microsoft.com/en-us/windows/terminal/customize-settings/profile-general">官方文档</a> 。</p><h2 id="PowerShell-美化"><a href="#PowerShell-美化" class="headerlink" title="PowerShell 美化"></a>PowerShell 美化</h2><p>在PowerShell美化中，我使用了<code>oh-my-posh</code>这个主题框架，它可以提供丰富的样式以供选择，感受还是相当不错的。</p><h3 id="安装-oh-my-posh"><a href="#安装-oh-my-posh" class="headerlink" title="安装 oh-my-posh"></a>安装 oh-my-posh</h3><blockquote><p>此处需要注意：</p><p>如果此前没有安装 NuGet 提供程序，则安装时会提示安装 NuGet，输入Y安装即可。</p><p>如果安装时没有权限执行脚本，可能需要先执行 <code>Set-ExecutionPolicy</code>获取权限。</p><blockquote><p>建议安装前先执行<code>get-executionpolicy</code> 获取当前权限，若为<code>Restricted</code> (默认)，则推荐使用 <code>Set-ExecutionPolicy -Scope CurrentUser RemoteSigned</code> 命令，将权限设为 <code>RemoteSigned</code> 。</p></blockquote></blockquote><p>使用管理员模式开启Windows Terminal (PowerShell)，安装 <code>posh-git</code> 和 <code>oh-my-posh</code> 这两个模块。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Install-Module posh-git -Scope CurrentUser</span><br><span class="line">Install-Module oh-my-posh -Scope CurrentUser</span><br></pre></td></tr></table></figure><h3 id="安装-Get-ChildItemColor"><a href="#安装-Get-ChildItemColor" class="headerlink" title="安装 Get-ChildItemColor"></a>安装 Get-ChildItemColor</h3><p>在图中可以看到，使用 <code>ls</code> 命令可以获得一个类似Linux的彩色输出，如何在Windows下实现这种好看的文件输出呢？我们可以安装 <code>Get-ChildItemColor</code> 模块。</p><p>执行以下命令安装：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Install-Module -AllowClobber Get-ChildItemColor</span><br></pre></td></tr></table></figure><p>详细配置可以参考其<a href="https://github.com/joonro/Get-ChildItemColor">README</a> 。</p><h3 id="配置主题配置文件"><a href="#配置主题配置文件" class="headerlink" title="配置主题配置文件"></a>配置主题配置文件</h3><p>通过以下命令测试，如果之前没有配置文件，就新建一个 PowerShell 配置文件。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">if (!(Test-Path -Path $PROFILE )) &#123; New-Item -Type File -Path $PROFILE -Force &#125;</span><br></pre></td></tr></table></figure><p>可以选择使用vscode或其他编辑器打开（选择其一）：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">code $PROFILE</span><br><span class="line">notepad $PROFILE</span><br></pre></td></tr></table></figure><p>在其中添加：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Import-Module posh-git</span><br><span class="line">Import-Module oh-my-posh</span><br><span class="line">Set-PoshPrompt -Theme aliens</span><br><span class="line">If (-Not (Test-Path Variable:PSise)) &#123;</span><br><span class="line">    Import-Module Get-ChildItemColor</span><br><span class="line">    Set-Alias l Get-ChildItem -option AllScope</span><br><span class="line">    Set-Alias ls Get-ChildItemColorFormatWide -option AllScope</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中1，2行导入刚才安装的 <code>oh-my-posh</code> 模块；第3行设置 <code>oh-my-posh</code> 的主题；最后几行设置 <code>Get-ChildItemColor</code> 模块，使 <code>l</code> 、<code>ls</code> 命令成为调用该模块命令的别名，以覆盖原有命令。</p><p>关于 <code>oh-my-posh</code> 的主题，官方目前给出了19款，可以前往其 <a href="https://ohmyposh.dev/docs/themes">文档</a> 查看并选择自己喜欢的主题，这里个人推荐使用 <code>aliens</code> ，会比较适合浅色背景使用。</p><h3 id="字体设置"><a href="#字体设置" class="headerlink" title="字体设置"></a>字体设置</h3><p>由于<code>oh-my-posh</code> 的很多主题使用powerline字体，所以若没有设置字体为powerline字体，PowerShell中将出现很多方框。</p><p>在<a href="https://github.com/powerline/fonts">这里</a>可以下载powerline字体，个人使用的是 <code>Meslo</code> 。</p><p>在Windows Terminal中应用该字体的方法可以参考上文：”Windows Terminal 美化”中 <a href="#其他设置">其他设置</a> 。</p><p>同时，也可以将vscode的终端字体设置为该字体:</p><ol><li>打开vscode的文件-&gt;首选项-&gt;设置 (ctrl+,)</li><li>找到 Terminal &gt; Integrated &gt; Font Family </li><li>设置为该字体即可。</li></ol><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>至此，Windows Terminal的美化就大致完成了，好看才是第一生产力，毕竟心情愉悦才能提高效率不是？</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;由于去年使用过一段时间的ArchLinux，让我对Linux系统的自由度有了很深的认识，从桌面到系统的各项配置，都可以按照自己的喜好进行配置，像是桌面的各种工具，图标排列，动画，开机界面等等。这次因为一些原因需要在Windows上完成一些工作，恰好又重装了系统，于是就捣鼓了一下Win下的命令行，让它也美观起来~&lt;/p&gt;</summary>
    
    
    
    
    <category term="Windows Terminal" scheme="https://blog.reilkay.com/tags/Windows-Terminal/"/>
    
    <category term="美化" scheme="https://blog.reilkay.com/tags/%E7%BE%8E%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>新的开始</title>
    <link href="https://blog.reilkay.com/NewBegin/"/>
    <id>https://blog.reilkay.com/NewBegin/</id>
    <published>2021-03-14T13:32:53.000Z</published>
    <updated>2022-04-08T13:33:36.214Z</updated>
    
    <content type="html"><![CDATA[<p>折腾真的是永远停不下来的事情，在去年九月份将博客从 Hugo 迁移到 Hexo 之后，虽然几乎没更新文章，但毕竟是对两种博客系统的体验有了些许了解。在享受 Hexo + Butterfly 的舒适的同时，网站极慢的访问速度却成了问题，网页在 PageSpeed Insights 上只能得到67分，网页完全渲染甚至需要7秒左右的时间。然而让我舍弃这些好看的主题和各种方便的功能去换取速度，又是一件相当痛苦的事情，于是我萌生了分离日常生活记录博客和技术博客的想法。</p><span id="more"></span><h2 id="大致思路"><a href="#大致思路" class="headerlink" title="大致思路"></a>大致思路</h2><p>因为想要同时保留美观与速度是一件很难实现的事情，所以只能将二者分开实现，于是对二者的主要需求进行分析：</p><ul><li>日常记录博客：<ul><li>美观</li><li>方便插入图片</li><li>文章可能较长需要目录</li><li>对访问速度不敏感</li><li>文章类型较多较杂需要索引</li></ul></li><li>技术博客<ul><li>更多专注文字内容，足够简洁</li><li>提供较好的阅读体验</li><li>尽量快的访问速度</li></ul></li></ul><p>基于以上这些想法，我计划将原博客作为日常用，而新建一个简洁风格的博客用于技术向，并取名为<code>Binray</code>。</p><h2 id="命名由来"><a href="#命名由来" class="headerlink" title="命名由来"></a>命名由来</h2><p>博客名<code>Binray</code> 取自二进制的英语简称 BIN，和我的常用名 Ray 进行组合，且形似于二进制的英语单词 “Binary” ，故博客的中文名也叫做<code>二进制蕾伊</code>。读法上没有什么讲究，个人暂且习惯于将前后分开按照原读音读作 “BIN-RAY”。</p><h2 id="实现过程"><a href="#实现过程" class="headerlink" title="实现过程"></a>实现过程</h2><p>既然是想要新建一个简洁高效的博客，我第一时间想到的还是老朋友Hugo，但机缘巧合之下，从朋友那里得知了一款异常简洁干净的 Hexo 主题——<a href="https://github.com/tiaanduplessis/hexo-theme-brewski">brewski</a> 。</p><p>在 README 中可以看出这款主题是基于 <a href="https://github.com/Dreyer/hexo-theme-artemis">artemis</a> 进行修改，而 artemis 则是基于经典主题 <a href="https://github.com/pinggod/hexo-theme-apollo">Apollo</a> 进行更新和修改的，于是使用 brewski 主题就有了几个优点：</p><ul><li>较新的Pug支持</li><li>简洁的 Apollo 风格</li><li>较 artemis 相比更舒适的布局和字体</li></ul><p>但问题在于，这款主题也已超过一年没有更新，可以看出作者对这款主题也没有什么继续优化的欲望，基于这款主题缺失了一些个人需要的功能，且缺少一些应当具有的自定义设置，我决定基于这款主题做一些修改，于是就有了今天看到的这款主题—— <a href="https://github.com/reilkay/hexo-theme-report">report</a> 。</p><p>这款主题主要修改有：</p><ul><li>增加全局 Pjax 、instant.page</li><li>添加页面加载进度条</li><li>将评论系统更换为 miniValine 前端+ waline 后端</li><li>更换了网站图标及Logo</li><li>修改布局及主题色</li><li>更新为新版谷歌分析</li></ul><p>修改主题后，在博客中加入了MathJax支持，并增加了gulp进行静态资源压缩以进一步提升访问速度。</p><p>至此，博客已基本施工完成。</p><h2 id="或许会增加的功能"><a href="#或许会增加的功能" class="headerlink" title="或许会增加的功能"></a>或许会增加的功能</h2><ul><li>PWA</li><li>友链页面</li><li>文章过期提醒</li><li>优化代码高亮</li><li>自定义主题色</li><li>增加站点运行时间</li><li>etc.</li></ul><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>有了前几次搭建博客的经验，这次除了在研究如何使用新版 barba.js 上，和排查访客量无法显示的问题上花费了较多的时间，一切都较为顺利地完成了。</p><p>这次将两个博客分开使用一是为了优化体验，同时也是为了督促自己多多更新（多水几篇），希望自己以后能多多更新吧~</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;折腾真的是永远停不下来的事情，在去年九月份将博客从 Hugo 迁移到 Hexo 之后，虽然几乎没更新文章，但毕竟是对两种博客系统的体验有了些许了解。在享受 Hexo + Butterfly 的舒适的同时，网站极慢的访问速度却成了问题，网页在 PageSpeed Insights 上只能得到67分，网页完全渲染甚至需要7秒左右的时间。然而让我舍弃这些好看的主题和各种方便的功能去换取速度，又是一件相当痛苦的事情，于是我萌生了分离日常生活记录博客和技术博客的想法。&lt;/p&gt;</summary>
    
    
    
    
    <category term="博客" scheme="https://blog.reilkay.com/tags/%E5%8D%9A%E5%AE%A2/"/>
    
    <category term="hexo" scheme="https://blog.reilkay.com/tags/hexo/"/>
    
    <category term="主题" scheme="https://blog.reilkay.com/tags/%E4%B8%BB%E9%A2%98/"/>
    
  </entry>
  
  <entry>
    <title>使用Github Actions自动部署Hugo到Github Pages</title>
    <link href="https://blog.reilkay.com/AutomaticDeploymentOfHugo/"/>
    <id>https://blog.reilkay.com/AutomaticDeploymentOfHugo/</id>
    <published>2020-07-16T18:10:08.000Z</published>
    <updated>2020-07-16T18:10:08.000Z</updated>
    
    <content type="html"><![CDATA[<p>前段时间看到好多人用Github Actions搞自动化，最近又有Dalao告诉我能用Action自动部署博客，顿时有些心痒，毕竟Hugo博客每次更新的时候要删掉public里的内容重新生成，一不小心就会把git文件也删掉（好像暴露了不经常写博客所以不熟练的事实），遂上网查了查，没什么中文的文档，于是在此记录一下折腾的经历，以备不时之需。</p><span id="more"></span><h2 id="建立分支上传源文件"><a href="#建立分支上传源文件" class="headerlink" title="建立分支上传源文件"></a>建立分支上传源文件</h2><p>首先需要先建一个新的分支把整个博客的源文件传上去，因为我是网页已经在master分支上挂着了不想折腾，所以又建立了source分支用于放置源文件（记得把源文件的分支设为default）。</p><p><img src="https://i.loli.net/2020/07/17/KPXEr1noR8DqwSv.png" alt="img"></p><p>注：事实上可以用master分支放置源文件，而新建一个gh-page分支挂网页，这样可以减少一些不必要的操作~</p><h2 id="在Actions中新建workflow"><a href="#在Actions中新建workflow" class="headerlink" title="在Actions中新建workflow"></a>在Actions中新建workflow</h2><ol><li><p>首先打开Actions页面，点击新建workflow。</p><p> <img src="https://i.loli.net/2020/07/17/9ZrvTxWMlX8pdQf.png" alt="img"></p><p> <img src="https://i.loli.net/2020/07/17/QGb4jmJesqyrXta.png" alt="img"></p></li><li><p>之后我们使用现成的项目:</p><p> <a href="https://github.com/peaceiris/actions-hugo"><img src="https://i.loli.net/2020/07/17/IGAUmnKEV73eh8b.png" alt="image-20200717142237607"></a></p><p> 根据README中给出的代码填写。</p><p> <img src="https://i.loli.net/2020/07/17/F9exYaksP7TNbrz.png" alt="image-20200717142456613"></p><p> 此时注意：如果源代码在master分支，则不需要进行下一步。</p></li><li><p>修改第六行<code>- master</code>为你的源代码所在的分支，并在末尾添加一行<code>publish_branch: master</code>。</p><p> 例如我这里：</p><p> <img src="https://i.loli.net/2020/07/17/bIZhDCUzBGKqcay.png" alt="img"></p></li><li><p>Commit到源码分支即可</p><p><img src="https://i.loli.net/2020/07/17/LbaptGHQTyNrc5P.png" alt="img"></p></li></ol><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>无需进行其他操作，在每次更新完博客后，将源文件commit至源码所在分支，即可实现自动生成html并部署至GitHub Pages。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;前段时间看到好多人用Github Actions搞自动化，最近又有Dalao告诉我能用Action自动部署博客，顿时有些心痒，毕竟Hugo博客每次更新的时候要删掉public里的内容重新生成，一不小心就会把git文件也删掉（好像暴露了不经常写博客所以不熟练的事实），遂上网查了查，没什么中文的文档，于是在此记录一下折腾的经历，以备不时之需。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Hugo" scheme="https://blog.reilkay.com/tags/Hugo/"/>
    
    <category term="博客" scheme="https://blog.reilkay.com/tags/%E5%8D%9A%E5%AE%A2/"/>
    
  </entry>
  
  <entry>
    <title>使用Python求Select集</title>
    <link href="https://blog.reilkay.com/UsePythonTofindSelectCollection/"/>
    <id>https://blog.reilkay.com/UsePythonTofindSelectCollection/</id>
    <published>2020-07-16T09:53:22.000Z</published>
    <updated>2020-07-16T09:53:22.000Z</updated>
    
    <content type="html"><![CDATA[<p>刚刚整完编译原理的课设报告，突然想起来求Select的时候遇到的各种坑，想到当时网上各种资料的错误和不全面，然后又想到万年没更新过的博客，特地来更新一下。</p><span id="more"></span><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><blockquote><p>既然要用<code>Python</code>求Select集，那至少得知道手动怎么求吧（笑</p></blockquote><p>众所周知，求Select集首先需要求得First集和Follow集，先来看一看定义：</p><h3 id="First集合"><a href="#First集合" class="headerlink" title="First集合"></a>First集合</h3><p>顾名思义，First集就是一个文法符号串，所可能推导出的符号串中，第一个终结符构成的集合。</p><p>如果还是不理解的话，举个例子：First(X) 就是求X所有能推导出内容中第一个终结符的集合。</p><p>求First集分为：</p><ol><li><p>求终结符的First集：终结符的First集是他本身。</p></li><li><p>求非终结符的First集：</p><ul><li><p>若A-&gt;a，则根据定义，a <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.09ex" xmlns="http://www.w3.org/2000/svg" width="1.509ex" height="1.312ex" role="img" focusable="false" viewBox="0 -540 667 580"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z"></path></g></g></g></svg></mjx-container> First(A)。</p></li><li><p>若A-&gt;B，同样根据定义，First(B) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> First(A)。</p></li></ul></li><li><p>求符号串的First集（例如ABC）：</p><ol><li>第一步：看串首是否为终结符或不能推导出ε（空）的非终结符。<ul><li>若是终结符，则First(ABC) = { 该终结符 }；</li><li>若是不能推导出ε的非终结符，则First(ABC) =  First(A)；</li><li>若非上述情况，则First(A) - ε <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> First(ABC)，并进行下一步。</li></ul></li><li>第二步：若串首非终结符能推出ε，当其推出空时，符号串将变为BC。<ul><li>重复第一步的操作，即查看随后的符号是否为终结符或或不能推导出ε的非终结符，并按第一步操作。</li><li>若不能推出ε则结束循环。</li></ul></li></ol></li></ol><p>注意事项：First集合中的符号一定是终结符，终结符也包括空串ε。</p><h3 id="Follow集合"><a href="#Follow集合" class="headerlink" title="Follow集合"></a>Follow集合</h3><p>同样，顾名思义，Follow集就是非终结符后面可能跟随的终结符的集合（不包括ε）。</p><p>求Follow集分为：</p><ol><li><p><code>A-&gt;...Bc...</code>型：根据定义，c <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.09ex" xmlns="http://www.w3.org/2000/svg" width="1.509ex" height="1.312ex" role="img" focusable="false" viewBox="0 -540 667 580"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z"></path></g></g></g></svg></mjx-container> Follow(B)。</p></li><li><p><code>A-&gt;...BC...</code>型：根据定义，First(C) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Follow(B)。</p></li><li><p><code>A-&gt;...C</code>型：文法左部的Follow集包含于串尾非终结符的Follow集。本例中Follow(A) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Follow(C)。</p></li><li><p><code>A-&gt;...BC</code>这一类较为特殊，处理方法如下：</p><ul><li><p>该类型是<code>A-&gt;...BC...</code>型和<code>A-&gt;...C</code>型的特例情况，除了要按<code>A-&gt;...BC...</code>型的情况处理，将First(C) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Follow(B)，还要进行以下操作：</p><ol><li><p>第一步：看串尾C能否推导出ε。</p><ul><li><p>若不能推导出空，则同<code>A-&gt;...C</code>型操作，将Follow(A) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Follow(C)。</p></li><li><p>若能推导出空，则Follow(A)也属于Follow(B)，即Follow(A) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Follow(B)，并进行下一步。</p></li></ul></li><li><p>第二步：若串尾非终结符能推导出ε，当其推空时，符号串将变为<code>A-&gt;...B</code>。</p><ul><li>重复第一步操作，即判断当前串尾符号B能否推导出ε，并按第一步操作。</li><li>若不能推出ε则结束循环。</li></ul></li></ol></li></ul></li></ol><p>注意事项：Follow集合中的符号一定是终结符，并且不包括空串ε，而且定义<strong>开始符号</strong> 的Follow集合包含 <code>#</code> 。</p><h3 id="Select集合"><a href="#Select集合" class="headerlink" title="Select集合"></a>Select集合</h3><p>Select集合则是产生式左部的可能的推导结果的起始符号。</p><p>举个例子：Select(A-&gt;B)就是求这个文法产生式中A可能推导出起始符号集合。</p><p>求Select集分为：</p><ol><li><code>A–&gt;X（X为任意串且X不能推导出空）</code>型：根据定义，Select(A–&gt;X) = First(X)。</li><li><code>A–&gt;X（X为任意串且X能推导出空）</code>型：<ul><li>当X不推导出空时，First(X) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Select(A–&gt;X)</li><li>当X推导出空时，A推导出的符号串就会是A后面的符号的推导结果，即Follow(A)，故Follow(A) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.312ex" xmlns="http://www.w3.org/2000/svg" width="1.76ex" height="1.751ex" role="img" focusable="false" viewBox="0 -636 778 774"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2286" d="M84 346Q84 468 166 546T360 635Q361 635 370 635T395 635T430 636T475 636T524 636H679Q694 628 694 616Q694 607 681 597L522 596H470H441Q366 596 338 592T266 568Q244 557 224 542T179 500T139 433T124 346V341Q124 253 185 185Q244 121 328 103Q348 98 366 98T522 96H681Q694 86 694 76Q694 64 679 56H526Q510 56 480 56T434 55Q350 55 289 71T172 141Q84 223 84 346ZM104 -131T104 -118T118 -98H679Q694 -106 694 -118T679 -138H118Q104 -131 104 -118Z"></path></g></g></g></svg></mjx-container> Select(A–&gt;X)</li><li>所以 Select(A–&gt;X) = First(X) <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.05ex" xmlns="http://www.w3.org/2000/svg" width="1.509ex" height="1.403ex" role="img" focusable="false" viewBox="0 -598 667 620"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="222A" d="M591 598H592Q604 598 611 583V376Q611 345 611 296Q610 162 606 148Q605 146 605 145Q586 68 507 23T333 -22Q268 -22 209 -1T106 66T56 173Q55 180 55 384L56 585Q66 598 75 598Q85 598 95 585V378L96 172L98 162Q112 95 181 57T332 18Q415 18 487 58T570 175Q571 180 571 383V583Q579 598 591 598Z"></path></g></g></g></svg></mjx-container> Follow(A) </li></ul></li></ol><h2 id="利用Python自动求Select集"><a href="#利用Python自动求Select集" class="headerlink" title="利用Python自动求Select集"></a>利用Python自动求Select集</h2><blockquote><p>有了上面这些前置知识，就可以着手用程序求这些集合了！</p></blockquote><p>程序求法与人工求法有些许不同，具体表现在程序是顺序执行的，没有人工求那么灵活，所以可能需要运行多次才能得出正确结果~</p><h3 id="大致思路"><a href="#大致思路" class="headerlink" title="大致思路"></a>大致思路</h3><ol><li><p>求First集：</p><ul><li><p>先求First集第一个部分：针对-&gt;直接推出第一个字符为终结符部分，直接将其加入非终结符的First集中。</p></li><li><p>再循环求出First集第二部分：针对A -&gt; B型，反复把B的first集加到A的first集合中并去重，直到集合不再扩大为止。</p></li></ul></li><li><p>求Follow集：</p><ul><li>将非终结符后的终结符加入非终结符的Follow集</li><li>将非终结符后跟非终结符的First集加入前者的Follow集</li><li>当非终结符在末尾时，将生成式左侧的Follow集加入末尾非终结符的Follow集</li><li>若句末非终结符的First集包含空，则也将生成式左侧的Follow集加入倒数第二个位置上的非终结符的Follow集中，重复向前直到遇到终结符或First集中不含空的非终结符。</li></ul><p>循环上述过程并去重，直到集合不再扩大为止。</p></li><li><p>求Select集：</p><p>针对A-&gt;X，分为两种情况讨论：</p><ul><li><p>若X不能推导出空，则根据定义，A的Select集应当为First（X）</p></li><li><p>若X能推导出空，则根据定义， First（X）属于A的Select集，此外，Follow（A）也属于A的Select集。</p></li></ul></li></ol><h3 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h3><p>我个人实现的代码算是覆盖了大多数情况，暂时没有发现什么Bug。</p><p>若要使用大概需要注意：</p><ul><li>文法中各符号用空格分开</li><li>非终结符用<code>&lt; &gt;</code>包裹(也可以通过修改<code>判断非终结符的函数</code>修改非终结符样式)</li><li>结果保存在 <code>self.FIRST</code>、  <code>self.FOLLOW</code> 、 <code>self.SELECT</code>三个字典中，也可以通过去除<code>run_cal</code>函数中<code>self.debug_out()</code>前的注释符号 <code>#</code> 实现在控制台输出上述三个集合。</li></ul><p><a href="https://www.qiyuex.top/download/BlogDownload/cal_select.py">代码下载</a></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 判断非终结符的函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">isnonterminal</span>(<span class="params">symbol</span>):</span></span><br><span class="line">    <span class="keyword">if</span> symbol[<span class="number">0</span>] == <span class="string">'&lt;'</span> <span class="keyword">and</span> symbol[-<span class="number">1</span>] == <span class="string">'&gt;'</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CalSelect</span>(<span class="params"><span class="built_in">object</span></span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 初始化集合字典</span></span><br><span class="line">        self.FIRST = {}</span><br><span class="line">        self.FOLLOW = {}</span><br><span class="line">        self.SELECT = {}</span><br><span class="line">        <span class="comment"># 初始化文法</span></span><br><span class="line">        self.grammar = [</span><br><span class="line"><span class="comment"># 文法填在此处</span></span><br><span class="line"><span class="string">"&lt;E&gt;-&gt;&lt;T&gt; &lt;E'&gt;"</span>,</span><br><span class="line"><span class="string">"&lt;E'&gt;-&gt;+ &lt;T&gt; &lt;E'&gt;"</span>,</span><br><span class="line"><span class="string">"&lt;E'&gt;-&gt;ε"</span>,</span><br><span class="line"><span class="string">"&lt;T&gt;-&gt;&lt;F&gt; &lt;T'&gt;"</span>,</span><br><span class="line"><span class="string">"&lt;T'&gt;-&gt;* &lt;F&gt; &lt;T'&gt;"</span>,</span><br><span class="line"><span class="string">"&lt;T'&gt;-&gt;ε"</span>,</span><br><span class="line"><span class="string">"&lt;F&gt;-&gt;( &lt;E&gt; )"</span>,</span><br><span class="line"><span class="string">"&lt;F&gt;-&gt;i"</span></span><br><span class="line">        ]</span><br><span class="line">        <span class="comment"># 初始化终结符</span></span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(self.grammar)):</span><br><span class="line">            self.grammar[i] = self.grammar[i].replace(<span class="string">'函数名'</span>, <span class="string">'FT'</span>)</span><br><span class="line">            self.grammar[i] = self.grammar[i].replace(<span class="string">'变量名'</span>, <span class="string">'iT'</span>)</span><br><span class="line">            self.grammar[i] = self.grammar[i].replace(<span class="string">'常数'</span>, <span class="string">'CT'</span>)</span><br><span class="line">            self.grammar[i] = self.grammar[i].replace(<span class="string">'字符串'</span>, <span class="string">'sT'</span>)</span><br><span class="line">            self.grammar[i] = self.grammar[i].replace(<span class="string">'字符'</span>, <span class="string">'cT'</span>)</span><br><span class="line">        <span class="comment"># 初始化first集、follow集和select集字典的键值对中的值为空</span></span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> self.grammar:</span><br><span class="line">            part_begin = line.split(<span class="string">"-&gt;"</span>)[<span class="number">0</span>]</span><br><span class="line">            part_end_temp = line.split(<span class="string">"-&gt;"</span>)[<span class="number">1</span>]</span><br><span class="line">            part_end = part_end_temp.split(<span class="string">" "</span>)</span><br><span class="line">            self.FIRST[part_begin] = []</span><br><span class="line">            self.FOLLOW[part_begin] = []</span><br><span class="line">            self.SELECT[line] = []</span><br><span class="line">        self.FOLLOW[self.grammar[<span class="number">0</span>].split(<span class="string">"-&gt;"</span>)[<span class="number">0</span>]].append(<span class="string">'#'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 求first集中第一部分：针对-&gt;直接推出第一个字符为终结符部分</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getFirst</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> self.grammar:</span><br><span class="line">            part_begin = line.split(<span class="string">"-&gt;"</span>)[<span class="number">0</span>]</span><br><span class="line">            part_end_temp = line.split(<span class="string">"-&gt;"</span>)[<span class="number">1</span>]</span><br><span class="line">            part_end = part_end_temp.split(<span class="string">" "</span>)</span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(part_end[<span class="number">0</span>]):</span><br><span class="line">                self.FIRST[part_begin].append(part_end[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 求first第二部分：针对A -&gt; B型，把B的first集加到A的first集合中</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getFirst_2</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> self.grammar:</span><br><span class="line">            part_begin = line.split(<span class="string">"-&gt;"</span>)[<span class="number">0</span>]</span><br><span class="line">            part_end_temp = line.split(<span class="string">"-&gt;"</span>)[<span class="number">1</span>]</span><br><span class="line">            part_end = part_end_temp.split(<span class="string">" "</span>)</span><br><span class="line">            <span class="comment"># 如果型如A -&gt; B：则把B的first集加到A的first集中去</span></span><br><span class="line">            <span class="keyword">if</span> isnonterminal(part_end[<span class="number">0</span>]):</span><br><span class="line">                <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(part_end)):</span><br><span class="line">                    <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(part_end[i]):</span><br><span class="line">                        self.FIRST[part_begin].append(part_end[i])</span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line">                    list_remove = self.FIRST.get(part_end[i]).copy()</span><br><span class="line">                    <span class="keyword">if</span> <span class="string">'ε'</span> <span class="keyword">in</span> list_remove <span class="keyword">and</span> i <span class="keyword">is</span> <span class="keyword">not</span> <span class="built_in">len</span>(part_end) - <span class="number">1</span>:</span><br><span class="line">                        list_remove.remove(<span class="string">'ε'</span>)</span><br><span class="line">                    self.FIRST[part_begin].extend(list_remove)</span><br><span class="line">                    <span class="keyword">if</span> <span class="string">'ε'</span> <span class="keyword">not</span> <span class="keyword">in</span> self.FIRST[part_end[i]]:</span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getFirst_3</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">            test = self.FIRST</span><br><span class="line">            self.getFirst_2()</span><br><span class="line">            <span class="comment"># 去除重复项</span></span><br><span class="line">            <span class="keyword">for</span> i, j <span class="keyword">in</span> self.FIRST.items():</span><br><span class="line">                temp = []</span><br><span class="line">                <span class="keyword">for</span> word <span class="keyword">in</span> <span class="built_in">list</span>(<span class="built_in">set</span>(j)):</span><br><span class="line">                    temp.append(word)</span><br><span class="line">                self.FIRST[i] = temp</span><br><span class="line">            <span class="keyword">if</span> test == self.FIRST:</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getFOLLOW_3</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">while</span> <span class="number">1</span>:</span><br><span class="line">            test = self.FOLLOW</span><br><span class="line">            self.getFollow()</span><br><span class="line">            <span class="comment"># 去除重复项</span></span><br><span class="line">            <span class="keyword">for</span> i, j <span class="keyword">in</span> self.FOLLOW.items():</span><br><span class="line">                temp = []</span><br><span class="line">                <span class="keyword">for</span> word <span class="keyword">in</span> <span class="built_in">list</span>(<span class="built_in">set</span>(j)):</span><br><span class="line">                    temp.append(word)</span><br><span class="line">                self.FOLLOW[i] = temp</span><br><span class="line">            <span class="keyword">if</span> test == self.FOLLOW:</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 计算follow集的第一部分，先计算 S -&gt; A b 类型的</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getFollow</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> self.grammar:</span><br><span class="line">            part_begin = line.split(<span class="string">"-&gt;"</span>)[<span class="number">0</span>]</span><br><span class="line">            part_end_temp = line.split(<span class="string">"-&gt;"</span>)[<span class="number">1</span>]</span><br><span class="line">            part_end = part_end_temp.split(<span class="string">" "</span>)</span><br><span class="line">            <span class="keyword">if</span> part_begin == <span class="string">"&lt;G&gt;"</span>:</span><br><span class="line">                <span class="keyword">pass</span></span><br><span class="line">            <span class="comment"># 如果是 S-&gt;a 直接推出终结符 则 continue</span></span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">len</span>(part_end) == <span class="number">1</span> <span class="keyword">and</span> <span class="keyword">not</span> isnonterminal(part_end[<span class="number">0</span>]):</span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            <span class="comment"># 否则执行下面的操作</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="comment"># 将-&gt;后面的倒序</span></span><br><span class="line">                part_end.reverse()</span><br><span class="line">                <span class="comment"># 最后一个为非终结符</span></span><br><span class="line">                <span class="keyword">if</span> isnonterminal(part_end[<span class="number">0</span>]):</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(part_end)):</span><br><span class="line">                        <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(part_end[i]):</span><br><span class="line">                            <span class="keyword">break</span></span><br><span class="line">                        self.FOLLOW[part_end[i]].extend(self.FOLLOW.get(part_begin))</span><br><span class="line">                        <span class="keyword">if</span> <span class="string">'ε'</span> <span class="keyword">not</span> <span class="keyword">in</span> self.FIRST[part_end[i]]:</span><br><span class="line">                            <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">                    terminal_temp = part_end[<span class="number">0</span>]</span><br><span class="line">                    <span class="keyword">for</span> item <span class="keyword">in</span> part_end[<span class="number">1</span>:]:</span><br><span class="line">                        <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(item):</span><br><span class="line">                            terminal_temp = item</span><br><span class="line">                        <span class="keyword">else</span>:</span><br><span class="line">                            <span class="keyword">if</span> isnonterminal(terminal_temp):</span><br><span class="line">                                list_remove = self.FIRST.get(terminal_temp).copy()</span><br><span class="line">                                <span class="keyword">if</span> <span class="string">"ε"</span> <span class="keyword">in</span> list_remove:</span><br><span class="line">                                    list_remove.remove(<span class="string">"ε"</span>)</span><br><span class="line">                                self.FOLLOW[item].extend(list_remove)</span><br><span class="line">                            <span class="keyword">elif</span> terminal_temp != <span class="string">'ε'</span>:</span><br><span class="line">                                self.FOLLOW[item].append(terminal_temp)</span><br><span class="line">                            terminal_temp = item</span><br><span class="line">                <span class="comment"># 如果终结符在句型的末端</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    terminal_temp = part_end[<span class="number">0</span>]</span><br><span class="line">                    <span class="keyword">for</span> item <span class="keyword">in</span> part_end[<span class="number">1</span>:]:</span><br><span class="line">                        <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(item):</span><br><span class="line">                            terminal_temp = item</span><br><span class="line">                        <span class="keyword">else</span>:</span><br><span class="line">                            <span class="keyword">if</span> isnonterminal(terminal_temp):</span><br><span class="line">                                list_remove = self.FIRST.get(terminal_temp).copy()</span><br><span class="line">                                <span class="keyword">if</span> <span class="string">"ε"</span> <span class="keyword">in</span> list_remove:</span><br><span class="line">                                    list_remove.remove(<span class="string">"ε"</span>)</span><br><span class="line">                                self.FOLLOW[item].extend(list_remove)</span><br><span class="line">                            <span class="keyword">elif</span> terminal_temp != <span class="string">'ε'</span>:</span><br><span class="line">                                self.FOLLOW[item].append(terminal_temp)</span><br><span class="line">                            terminal_temp = item</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getSelect</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">for</span> line <span class="keyword">in</span> self.grammar:</span><br><span class="line">            part_begin = line.split(<span class="string">"-&gt;"</span>)[<span class="number">0</span>]</span><br><span class="line">            part_end_temp = line.split(<span class="string">"-&gt;"</span>)[<span class="number">1</span>]</span><br><span class="line">            part_end = part_end_temp.split(<span class="string">" "</span>)</span><br><span class="line">            line_first = []</span><br><span class="line">            <span class="keyword">for</span> item <span class="keyword">in</span> part_end:</span><br><span class="line">                <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(item):</span><br><span class="line">                    line_first.append(item)</span><br><span class="line">                    <span class="keyword">break</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    line_first.extend(self.FIRST[item])</span><br><span class="line">                    <span class="keyword">if</span> <span class="string">'ε'</span> <span class="keyword">not</span> <span class="keyword">in</span> self.FIRST[item]:</span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line">            line_first = <span class="built_in">list</span>(<span class="built_in">set</span>(line_first))</span><br><span class="line">            can_derive_empty = <span class="literal">True</span></span><br><span class="line">            part_end.reverse()</span><br><span class="line">            <span class="keyword">for</span> item <span class="keyword">in</span> part_end:</span><br><span class="line">                <span class="keyword">if</span> <span class="keyword">not</span> isnonterminal(item):</span><br><span class="line">                    <span class="keyword">if</span> item != <span class="string">'ε'</span>:</span><br><span class="line">                        can_derive_empty = <span class="literal">False</span></span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="keyword">if</span> <span class="string">'ε'</span> <span class="keyword">not</span> <span class="keyword">in</span> self.FIRST[item]:</span><br><span class="line">                        can_derive_empty = <span class="literal">False</span></span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line">            list_remove = line_first.copy()</span><br><span class="line">            <span class="keyword">if</span> <span class="string">"ε"</span> <span class="keyword">in</span> list_remove:</span><br><span class="line">                list_remove.remove(<span class="string">"ε"</span>)</span><br><span class="line">            <span class="keyword">if</span> can_derive_empty:</span><br><span class="line">                self.SELECT[line].extend(list_remove)</span><br><span class="line">                self.SELECT[line].extend(self.FOLLOW[part_begin])</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                self.SELECT[line].extend(list_remove)</span><br><span class="line">            self.SELECT[line] = <span class="built_in">list</span>(<span class="built_in">set</span>(self.SELECT[line]))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">debug_out</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">for</span> i, j <span class="keyword">in</span> self.FIRST.items():</span><br><span class="line">            <span class="built_in">str</span> = j[<span class="number">0</span>]</span><br><span class="line">            <span class="keyword">for</span> temp <span class="keyword">in</span> j[<span class="number">1</span>:]:</span><br><span class="line">                <span class="built_in">str</span> = <span class="built_in">str</span> + <span class="string">','</span> + temp</span><br><span class="line">            print(<span class="string">"FIRST("</span> + i + <span class="string">")"</span> + <span class="string">" = {"</span> + <span class="built_in">str</span> + <span class="string">"}"</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> i, j <span class="keyword">in</span> self.FOLLOW.items():</span><br><span class="line">            <span class="built_in">str</span> = j[<span class="number">0</span>]</span><br><span class="line">            <span class="keyword">for</span> temp <span class="keyword">in</span> j[<span class="number">1</span>:]:</span><br><span class="line">                <span class="built_in">str</span> = <span class="built_in">str</span> + <span class="string">','</span> + temp</span><br><span class="line">            print(<span class="string">"FOLLOW("</span> + i + <span class="string">")"</span> + <span class="string">" = {"</span> + <span class="built_in">str</span> + <span class="string">"}"</span>)</span><br><span class="line">        <span class="keyword">for</span> i, j <span class="keyword">in</span> self.SELECT.items():</span><br><span class="line">            <span class="built_in">str</span> = j[<span class="number">0</span>]</span><br><span class="line">            <span class="keyword">for</span> temp <span class="keyword">in</span> j[<span class="number">1</span>:]:</span><br><span class="line">                <span class="built_in">str</span> = <span class="built_in">str</span> + <span class="string">','</span> + temp</span><br><span class="line">            print(<span class="string">"SELECT("</span> + i + <span class="string">")"</span> + <span class="string">" = {"</span> + <span class="built_in">str</span> + <span class="string">"}"</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run_cal</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.getFirst()</span><br><span class="line">        self.getFirst_3()</span><br><span class="line">        self.getFirst_3()</span><br><span class="line">        self.getFOLLOW_3()</span><br><span class="line">        self.getFOLLOW_3()</span><br><span class="line">        self.getSelect()</span><br><span class="line">        <span class="comment"># self.debug_out()</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line">    CalSelect().run_cal()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;刚刚整完编译原理的课设报告，突然想起来求Select的时候遇到的各种坑，想到当时网上各种资料的错误和不全面，然后又想到万年没更新过的博客，特地来更新一下。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Python" scheme="https://blog.reilkay.com/tags/Python/"/>
    
    <category term="编译原理" scheme="https://blog.reilkay.com/tags/%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86/"/>
    
    <category term="学习日记" scheme="https://blog.reilkay.com/tags/%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0/"/>
    
  </entry>
  
</feed>
