<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>石头的杂货铺</title>
      <link>https://st1020.com</link>
      <description>St1020 的博客</description>
      <generator>Zola</generator>
      <language>zh-CN</language>
      <atom:link href="https://st1020.com/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sun, 20 Jul 2025 00:00:00 +0000</lastBuildDate>
      <item>
          <title>理解代理</title>
          <pubDate>Sun, 20 Jul 2025 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/understand-proxy/</link>
          <guid>https://st1020.com/posts/understand-proxy/</guid>
          <description xml:base="https://st1020.com/posts/understand-proxy/">&lt;p&gt;在网上冲浪时，我们难免需要访问一些“不安全”的网站，我们可能不希望这些不安全的网站得知我们的真实 IP 地址，在这种情况下，代理可以帮助我们。&lt;&#x2F;p&gt;
&lt;p&gt;或者，我们处于公司的内网，需要访问公共互联网，但是公司的防火墙禁止用户直接访问互联网，公司的网络管理员通常会提供一个代理服务器用于访问。&lt;&#x2F;p&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;figure class=&quot;inline-svg&quot;&gt;
  &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!-- Do not edit this file with editors other than draw.io --&gt;
&lt;!DOCTYPE svg PUBLIC &quot;-&#x2F;&#x2F;W3C&#x2F;&#x2F;DTD SVG 1.1&#x2F;&#x2F;EN&quot; &quot;http:&#x2F;&#x2F;www.w3.org&#x2F;Graphics&#x2F;SVG&#x2F;1.1&#x2F;DTD&#x2F;svg11.dtd&quot;&gt;
&lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; style=&quot;background: transparent; background-color: transparent; color-scheme: light dark;&quot; xmlns:xlink=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xlink&quot; version=&quot;1.1&quot; width=&quot;842px&quot; height=&quot;301px&quot; viewBox=&quot;-0.5 -0.5 842 301&quot; content=&quot;&amp;lt;mxfile host=&amp;quot;Electron&amp;quot; agent=&amp;quot;Mozilla&#x2F;5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit&#x2F;537.36 (KHTML, like Gecko) draw.io&#x2F;28.0.4 Chrome&#x2F;138.0.7204.97 Electron&#x2F;37.2.1 Safari&#x2F;537.36&amp;quot; version=&amp;quot;28.0.4&amp;quot;&amp;gt;&amp;#10;  &amp;lt;diagram name=&amp;quot;第 1 页&amp;quot; id=&amp;quot;dOIuBL2UsX8HxQ0cNeCZ&amp;quot;&amp;gt;&amp;#10;    &amp;lt;mxGraphModel dx=&amp;quot;1158&amp;quot; dy=&amp;quot;732&amp;quot; grid=&amp;quot;1&amp;quot; gridSize=&amp;quot;10&amp;quot; guides=&amp;quot;1&amp;quot; tooltips=&amp;quot;1&amp;quot; connect=&amp;quot;1&amp;quot; arrows=&amp;quot;1&amp;quot; fold=&amp;quot;1&amp;quot; page=&amp;quot;1&amp;quot; pageScale=&amp;quot;1&amp;quot; pageWidth=&amp;quot;1169&amp;quot; pageHeight=&amp;quot;827&amp;quot; math=&amp;quot;0&amp;quot; shadow=&amp;quot;0&amp;quot;&amp;gt;&amp;#10;      &amp;lt;root&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;1&amp;quot; parent=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-50&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.rect;fillColor2=none;strokeWidth=1;size=20;indent=5;fillColor=none;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;400&amp;quot; height=&amp;quot;300&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-7&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;fillColor=none;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;480&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;250&amp;quot; height=&amp;quot;300&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-6&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;fontColor=#0066CC;verticalAlign=top;verticalLabelPosition=bottom;labelPosition=center;align=center;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.firewall;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;616.25&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;100&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-8&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;fontColor=#0066CC;verticalAlign=top;verticalLabelPosition=bottom;labelPosition=center;align=center;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.server;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;495&amp;quot; y=&amp;quot;220&amp;quot; width=&amp;quot;90&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-9&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;fontColor=#0066CC;verticalAlign=top;verticalLabelPosition=bottom;labelPosition=center;align=center;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.user_male;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;40&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-15&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-9&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-6&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-28&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-6&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-31&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-31&amp;quot; value=&amp;quot;Internet&amp;quot; style=&amp;quot;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.cloud;fontColor=#000000;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;790&amp;quot; y=&amp;quot;60&amp;quot; width=&amp;quot;90&amp;quot; height=&amp;quot;50&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-35&amp;quot; value=&amp;quot;Company Intranet&amp;quot; style=&amp;quot;text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;480&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;30&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-36&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;fontColor=#0066CC;verticalAlign=top;verticalLabelPosition=bottom;labelPosition=center;align=center;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.user_male;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;80&amp;quot; y=&amp;quot;202.5&amp;quot; width=&amp;quot;40&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-41&amp;quot; value=&amp;quot;Safe&amp;quot; style=&amp;quot;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.cloud;fontColor=#000000;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;200&amp;quot; y=&amp;quot;65&amp;quot; width=&amp;quot;90&amp;quot; height=&amp;quot;50&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-45&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-36&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-51&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot;&amp;gt;&amp;#10;            &amp;lt;mxPoint x=&amp;quot;200&amp;quot; y=&amp;quot;205&amp;quot; as=&amp;quot;targetPoint&amp;quot; &#x2F;&amp;gt;&amp;#10;          &amp;lt;&#x2F;mxGeometry&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-46&amp;quot; value=&amp;quot;Unsafe&amp;quot; style=&amp;quot;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.cloud;fontColor=#000000;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;320&amp;quot; y=&amp;quot;65&amp;quot; width=&amp;quot;90&amp;quot; height=&amp;quot;50&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-47&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-36&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-41&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot;&amp;gt;&amp;#10;            &amp;lt;Array as=&amp;quot;points&amp;quot;&amp;gt;&amp;#10;              &amp;lt;mxPoint x=&amp;quot;100&amp;quot; y=&amp;quot;145&amp;quot; &#x2F;&amp;gt;&amp;#10;              &amp;lt;mxPoint x=&amp;quot;245&amp;quot; y=&amp;quot;145&amp;quot; &#x2F;&amp;gt;&amp;#10;            &amp;lt;&#x2F;Array&amp;gt;&amp;#10;          &amp;lt;&#x2F;mxGeometry&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-49&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.88;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-51&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-46&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot;&amp;gt;&amp;#10;            &amp;lt;mxPoint x=&amp;quot;290&amp;quot; y=&amp;quot;205.0526315789474&amp;quot; as=&amp;quot;sourcePoint&amp;quot; &#x2F;&amp;gt;&amp;#10;          &amp;lt;&#x2F;mxGeometry&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-51&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;fontColor=#0066CC;verticalAlign=top;verticalLabelPosition=bottom;labelPosition=center;align=center;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.proxy_server;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;200&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;105&amp;quot; height=&amp;quot;105&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-54&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;fontColor=#0066CC;verticalAlign=top;verticalLabelPosition=bottom;labelPosition=center;align=center;html=1;outlineConnect=0;fillColor=#CCCCCC;strokeColor=#6881B3;gradientColor=none;gradientDirection=north;strokeWidth=2;shape=mxgraph.networks.proxy_server;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;613.75&amp;quot; y=&amp;quot;220&amp;quot; width=&amp;quot;105&amp;quot; height=&amp;quot;105&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-56&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.no_symbol;fillColor=#f8cecc;strokeColor=#b85450;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;748.75&amp;quot; y=&amp;quot;110&amp;quot; width=&amp;quot;40&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-59&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-54&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-31&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot;&amp;gt;&amp;#10;            &amp;lt;Array as=&amp;quot;points&amp;quot;&amp;gt;&amp;#10;              &amp;lt;mxPoint x=&amp;quot;835&amp;quot; y=&amp;quot;272&amp;quot; &#x2F;&amp;gt;&amp;#10;            &amp;lt;&#x2F;Array&amp;gt;&amp;#10;          &amp;lt;&#x2F;mxGeometry&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;LT5l49i-5sKJs4NMfgQQ-33&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.tick;fillColor=#d5e8d4;strokeColor=#82b366;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;821.25&amp;quot; y=&amp;quot;169&amp;quot; width=&amp;quot;34&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;DG0Eh5BLZ3PX7DVNh1gw-1&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; edge=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-9&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-8&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;DG0Eh5BLZ3PX7DVNh1gw-2&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; edge=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;LT5l49i-5sKJs4NMfgQQ-6&amp;quot; target=&amp;quot;LT5l49i-5sKJs4NMfgQQ-54&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;      &amp;lt;&#x2F;root&amp;gt;&amp;#10;    &amp;lt;&#x2F;mxGraphModel&amp;gt;&amp;#10;  &amp;lt;&#x2F;diagram&amp;gt;&amp;#10;&amp;lt;&#x2F;mxfile&amp;gt;&amp;#10;&quot;&gt;&lt;defs&#x2F;&gt;&lt;g&gt;&lt;g data-cell-id=&quot;0&quot;&gt;&lt;g data-cell-id=&quot;1&quot;&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-50&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 0 0 L 400 0 L 400 300 L 0 300 L 0 0 Z&quot; fill=&quot;none&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot;&#x2F;&gt;&lt;path d=&quot;M 5 5 L 5 295 L 5 295 L 395 295 L 395 5 L 5 5&quot; fill=&quot;transparent&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: transparent;&quot;&#x2F;&gt;&lt;path d=&quot;M 0 0 L 400 0 L 400 300 L 0 300 L 0 0 Z&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-7&quot;&gt;&lt;g&gt;&lt;rect x=&quot;440&quot; y=&quot;0&quot; width=&quot;250&quot; height=&quot;300&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-6&quot;&gt;&lt;g&gt;&lt;rect x=&quot;576.25&quot; y=&quot;40&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;589.55&quot; y=&quot;40&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;614.75&quot; y=&quot;40&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;640.55&quot; y=&quot;40&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;665.75&quot; y=&quot;40&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;50.25&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;601.95&quot; y=&quot;50.25&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;627.65&quot; y=&quot;50.25&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;653.25&quot; y=&quot;50.25&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;60.5&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;589.55&quot; y=&quot;60.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;614.75&quot; y=&quot;60.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;640.55&quot; y=&quot;60.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;665.75&quot; y=&quot;60.5&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;70.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;601.95&quot; y=&quot;70.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;627.65&quot; y=&quot;70.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;653.25&quot; y=&quot;70.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;81&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;589.55&quot; y=&quot;81&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;615.25&quot; y=&quot;81&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;640.55&quot; y=&quot;81&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;665.75&quot; y=&quot;81&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;91.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;601.95&quot; y=&quot;91.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;627.65&quot; y=&quot;91.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;653.25&quot; y=&quot;91.5&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;101.75&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;589.55&quot; y=&quot;101.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;615.25&quot; y=&quot;101.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;640.55&quot; y=&quot;101.75&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;665.75&quot; y=&quot;101.75&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;112&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;601.95&quot; y=&quot;112&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;627.65&quot; y=&quot;112&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;653.25&quot; y=&quot;112&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;122&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;589.55&quot; y=&quot;122&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;614.75&quot; y=&quot;122&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;640.55&quot; y=&quot;122&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;665.75&quot; y=&quot;122&quot; width=&quot;10.5&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;576.25&quot; y=&quot;132&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;601.95&quot; y=&quot;132&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;627.65&quot; y=&quot;132&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;653.25&quot; y=&quot;132&quot; width=&quot;23&quot; height=&quot;8&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;path d=&quot;M 619.65 121.6 C 620.24 117.25 621.78 113.09 624.15 109.4 C 624.9 108.21 625.57 106.98 626.15 105.7 C 626.87 104.5 627.05 103.04 626.65 101.7 C 627.86 102.88 628.51 104.51 628.45 106.2 C 627.99 109.58 628.4 113.02 629.65 116.2 C 630.91 118.63 632.81 120.67 635.15 122.1 C 640.25 120.97 644.86 118.28 648.35 114.4 C 651.73 110.5 652.86 105.13 651.35 100.2 C 649.64 95.31 647.36 90.65 644.55 86.3 C 642.92 83.91 642.02 81.09 641.95 78.2 C 642.29 76.94 643.12 75.86 644.25 75.2 C 642.57 75.17 640.94 75.73 639.65 76.8 C 637 79.44 635.43 82.97 635.25 86.7 C 634.22 83.84 634.08 80.74 634.85 77.8 C 635.82 73.87 635.36 69.72 633.55 66.1 C 632.32 64.21 630.84 62.49 629.15 61 C 627.75 59.89 626.57 58.53 625.65 57 C 625.45 58.91 625.62 60.85 626.15 62.7 C 626.86 65.65 626.43 68.76 624.95 71.4 C 623.94 73.06 622.84 74.67 621.65 76.2 C 619.96 78.72 618.87 81.59 618.45 84.6 C 618.03 81.15 617.02 77.8 615.45 74.7 C 613.98 71.71 611.78 69.13 609.05 67.2 C 610.23 70.11 610.71 73.27 610.45 76.4 C 610.09 79.07 609.41 81.69 608.45 84.2 C 606.08 89.11 604.52 94.38 603.85 99.8 C 603.41 105.15 605.14 110.44 608.65 114.5 C 611.51 117.93 615.35 120.4 619.65 121.6 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-8&quot;&gt;&lt;g&gt;&lt;rect x=&quot;455&quot; y=&quot;265&quot; width=&quot;90&quot; height=&quot;15&quot; rx=&quot;2&quot; ry=&quot;2&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;455&quot; y=&quot;247.5&quot; width=&quot;90&quot; height=&quot;15&quot; rx=&quot;2&quot; ry=&quot;2&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;455&quot; y=&quot;230&quot; width=&quot;90&quot; height=&quot;15&quot; rx=&quot;2&quot; ry=&quot;2&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;455&quot; y=&quot;212.5&quot; width=&quot;90&quot; height=&quot;15&quot; rx=&quot;2&quot; ry=&quot;2&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;455&quot; y=&quot;195&quot; width=&quot;90&quot; height=&quot;15&quot; rx=&quot;2&quot; ry=&quot;2&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;path d=&quot;M 459 193 L 480 180 L 520 180 L 541 193 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;537&quot; cy=&quot;272.5&quot; rx=&quot;4&quot; ry=&quot;4&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;536.67&quot; cy=&quot;255&quot; rx=&quot;4&quot; ry=&quot;4&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;537&quot; cy=&quot;237.5&quot; rx=&quot;4&quot; ry=&quot;4&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;537&quot; cy=&quot;220&quot; rx=&quot;4&quot; ry=&quot;4&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;537&quot; cy=&quot;202.5&quot; rx=&quot;4&quot; ry=&quot;4&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;path d=&quot;M 460 278 L 465 267 L 470 267 L 465 278 Z M 470 278 L 475 267 L 480 267 L 475 278 Z M 480 278 L 485 267 L 490 267 L 485 278 Z M 490 278 L 495 267 L 500 267 L 495 278 Z M 500 278 L 505 267 L 510 267 L 505 278 Z M 510 278 L 515 267 L 520 267 L 515 278 Z M 460 260.5 L 465 249.5 L 470 249.5 L 465 260.5 Z M 470 260.5 L 475 249.5 L 480 249.5 L 475 260.5 Z M 480 260.5 L 485 249.5 L 490 249.5 L 485 260.5 Z M 490 260.5 L 495 249.5 L 500 249.5 L 495 260.5 Z M 500 260.5 L 505 249.5 L 510 249.5 L 505 260.5 Z M 510 260.5 L 515 249.5 L 520 249.5 L 515 260.5 Z M 460 243 L 465 232 L 470 232 L 465 243 Z M 470 243 L 475 232 L 480 232 L 475 243 Z M 480 243 L 484.5 232 L 489.5 232 L 484.5 243 Z M 490 243 L 495 232 L 500 232 L 495 243 Z M 500 243 L 505 232 L 510 232 L 505 243 Z M 510 243 L 515 232 L 520 232 L 515 243 Z M 460 225.5 L 465 214.5 L 470 214.5 L 465 225.5 Z M 470 225.5 L 475 214.5 L 480 214.5 L 475 225.5 Z M 480 225.5 L 485 214.5 L 490 214.5 L 485 225.5 Z M 490 225.5 L 495 214.5 L 500 214.5 L 495 225.5 Z M 500 225.5 L 505 214.5 L 510 214.5 L 505 225.5 Z M 510 225.5 L 515 214.5 L 520 214.5 L 515 225.5 Z M 460 208 L 465 197 L 470 197 L 465 208 Z M 470 208 L 475 197 L 480 197 L 475 208 Z M 480 208 L 485 197 L 490 197 L 485 208 Z M 490 208 L 495 197 L 500 197 L 495 208 Z M 500 208 L 505 197 L 510 197 L 505 208 Z M 510 208 L 515 197 L 520 197 L 515 208 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-9&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 500 40 C 508.28 40 515 46.72 515 55 C 515 63.28 508.28 70 500 70 C 491.72 70 485 63.28 485 55 C 485 46.72 491.72 40 500 40 Z M 510 75 C 515.52 75 520 79.48 520 85 L 520 100 C 520 105.52 515.52 110 510 110 L 510 135 C 510 137.76 507.76 140 505 140 L 495 140 C 492.24 140 490 137.76 490 135 L 490 110 C 484.48 110 480 105.52 480 100 L 480 85 C 480 79.48 484.48 75 490 75 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-15&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 520 90 L 569.88 90&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 575.13 90 L 568.13 93.5 L 569.88 90 L 568.13 86.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-28&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 676.25 90 L 795 90 L 795 76.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 795 71.12 L 798.5 78.12 L 795 76.37 L 791.5 78.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-31&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 828.45 70 C 835.2 69.15 840.01 62.69 839.2 55.57 C 838.39 48.45 832.26 43.38 825.52 44.23 C 825.44 33.6 818.38 24.46 808.52 22.23 C 798.67 20 788.67 25.29 784.48 34.96 C 781.36 31.2 776.42 29.79 771.94 31.36 C 767.46 32.94 764.31 37.2 763.95 42.17 C 756.67 41.89 750.54 47.89 750.27 55.57 C 750 63.25 755.69 69.72 762.98 70 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.95&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 45px; margin-left: 795px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; &quot;&gt;Internet&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;795&quot; y=&quot;49&quot; fill=&quot;#000000&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Internet&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-35&quot;&gt;&lt;g&gt;&lt;rect x=&quot;440&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;30&quot; fill=&quot;none&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 15px; margin-left: 500px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; &quot;&gt;Company Intranet&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;500&quot; y=&quot;19&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Company Intranet&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-36&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 60 162.5 C 68.28 162.5 75 169.22 75 177.5 C 75 185.78 68.28 192.5 60 192.5 C 51.72 192.5 45 185.78 45 177.5 C 45 169.22 51.72 162.5 60 162.5 Z M 70 197.5 C 75.52 197.5 80 201.98 80 207.5 L 80 222.5 C 80 228.02 75.52 232.5 70 232.5 L 70 257.5 C 70 260.26 67.76 262.5 65 262.5 L 55 262.5 C 52.24 262.5 50 260.26 50 257.5 L 50 232.5 C 44.48 232.5 40 228.02 40 222.5 L 40 207.5 C 40 201.98 44.48 197.5 50 197.5 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-41&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 238.45 75 C 245.2 74.15 250.01 67.69 249.2 60.57 C 248.39 53.45 242.26 48.38 235.52 49.23 C 235.44 38.6 228.38 29.46 218.52 27.23 C 208.67 25 198.67 30.29 194.48 39.96 C 191.36 36.2 186.42 34.79 181.94 36.36 C 177.46 37.94 174.31 42.2 173.95 47.17 C 166.67 46.89 160.54 52.89 160.27 60.57 C 160 68.25 165.69 74.72 172.98 75 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.95&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 50px; margin-left: 205px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; &quot;&gt;Safe&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;205&quot; y=&quot;54&quot; fill=&quot;#000000&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Safe&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-45&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 80 212.5 L 153.63 212.5&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 158.88 212.5 L 151.88 216 L 153.63 212.5 L 151.88 209 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-46&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 358.45 75 C 365.2 74.15 370.01 67.69 369.2 60.57 C 368.39 53.45 362.26 48.38 355.52 49.23 C 355.44 38.6 348.38 29.46 338.52 27.23 C 328.67 25 318.67 30.29 314.48 39.96 C 311.36 36.2 306.42 34.79 301.94 36.36 C 297.46 37.94 294.31 42.2 293.95 47.17 C 286.67 46.89 280.54 52.89 280.27 60.57 C 280 68.25 285.69 74.72 292.98 75 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.95&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 50px; margin-left: 325px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; &quot;&gt;Unsafe&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;325&quot; y=&quot;54&quot; fill=&quot;#000000&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Unsafe&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-47&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 60 162.5 L 60 105 L 205 105 L 205 81.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 205 76.12 L 208.5 83.12 L 205 81.37 L 201.5 83.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-49&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 252.4 212.5 L 325 212.56 L 325 81.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 325 76.12 L 328.5 83.12 L 325 81.37 L 321.5 83.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-51&quot;&gt;&lt;g&gt;&lt;rect x=&quot;160&quot; y=&quot;243.41&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;160&quot; y=&quot;226.24&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;160&quot; y=&quot;209.07&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;160&quot; y=&quot;191.89&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;160&quot; y=&quot;174.72&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;path d=&quot;M 164.08 172.76 L 185.49 160 L 226.26 160 L 247.67 172.76 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;243.59&quot; cy=&quot;250.77&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;243.26&quot; cy=&quot;233.6&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;243.59&quot; cy=&quot;216.43&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;243.59&quot; cy=&quot;199.25&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;243.59&quot; cy=&quot;182.08&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;path d=&quot;M 165.1 256.17 L 170.19 245.37 L 175.29 245.37 L 170.19 256.17 Z M 175.29 256.17 L 180.39 245.37 L 185.49 245.37 L 180.39 256.17 Z M 185.49 256.17 L 190.58 245.37 L 195.68 245.37 L 190.58 256.17 Z M 195.68 256.17 L 200.78 245.37 L 205.87 245.37 L 200.78 256.17 Z M 205.87 256.17 L 210.97 245.37 L 216.07 245.37 L 210.97 256.17 Z M 216.07 256.17 L 221.17 245.37 L 226.26 245.37 L 221.17 256.17 Z M 165.1 239 L 170.19 228.2 L 175.29 228.2 L 170.19 239 Z M 175.29 239 L 180.39 228.2 L 185.49 228.2 L 180.39 239 Z M 185.49 239 L 190.58 228.2 L 195.68 228.2 L 190.58 239 Z M 195.68 239 L 200.78 228.2 L 205.87 228.2 L 200.78 239 Z M 205.87 239 L 210.97 228.2 L 216.07 228.2 L 210.97 239 Z M 216.07 239 L 221.17 228.2 L 226.26 228.2 L 221.17 239 Z M 165.1 221.82 L 170.19 211.03 L 175.29 211.03 L 170.19 221.82 Z M 175.29 221.82 L 180.39 211.03 L 185.49 211.03 L 180.39 221.82 Z M 185.49 221.82 L 190.07 211.03 L 195.17 211.03 L 190.07 221.82 Z M 195.68 221.82 L 200.78 211.03 L 205.87 211.03 L 200.78 221.82 Z M 205.87 221.82 L 210.97 211.03 L 216.07 211.03 L 210.97 221.82 Z M 216.07 221.82 L 221.17 211.03 L 226.26 211.03 L 221.17 221.82 Z M 165.1 204.65 L 170.19 193.86 L 175.29 193.86 L 170.19 204.65 Z M 175.29 204.65 L 180.39 193.86 L 185.49 193.86 L 180.39 204.65 Z M 185.49 204.65 L 190.58 193.86 L 195.68 193.86 L 190.58 204.65 Z M 195.68 204.65 L 200.78 193.86 L 205.87 193.86 L 200.78 204.65 Z M 205.87 204.65 L 210.97 193.86 L 216.07 193.86 L 210.97 204.65 Z M 216.07 204.65 L 221.17 193.86 L 226.26 193.86 L 221.17 204.65 Z M 165.1 187.48 L 170.19 176.68 L 175.29 176.68 L 170.19 187.48 Z M 175.29 187.48 L 180.39 176.68 L 185.49 176.68 L 180.39 187.48 Z M 185.49 187.48 L 190.58 176.68 L 195.68 176.68 L 190.58 187.48 Z M 195.68 187.48 L 200.78 176.68 L 205.87 176.68 L 200.78 187.48 Z M 205.87 187.48 L 210.97 176.68 L 216.07 176.68 L 210.97 187.48 Z M 216.07 187.48 L 221.17 176.68 L 226.26 176.68 L 221.17 187.48 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;rect x=&quot;160&quot; y=&quot;160&quot; width=&quot;0&quot; height=&quot;0&quot; fill=&quot;none&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;246.65&quot; cy=&quot;247.34&quot; rx=&quot;18.349514563106794&quot; ry=&quot;17.66355140186916&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;234.93&quot; y=&quot;238.5&quot; width=&quot;23.45&quot; height=&quot;17.66&quot; fill=&quot;none&quot; stroke=&quot;#ffffff&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;stroke: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;rect x=&quot;237.48&quot; y=&quot;240.96&quot; width=&quot;18.35&quot; height=&quot;13.25&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-54&quot;&gt;&lt;g&gt;&lt;rect x=&quot;573.75&quot; y=&quot;263.41&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;573.75&quot; y=&quot;246.24&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;573.75&quot; y=&quot;229.07&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;573.75&quot; y=&quot;211.89&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;573.75&quot; y=&quot;194.72&quot; width=&quot;91.75&quot; height=&quot;14.72&quot; rx=&quot;1.96&quot; ry=&quot;1.96&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;path d=&quot;M 577.83 192.76 L 599.24 180 L 640.01 180 L 661.42 192.76 Z&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;657.34&quot; cy=&quot;270.77&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;657.01&quot; cy=&quot;253.6&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;657.34&quot; cy=&quot;236.43&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;657.34&quot; cy=&quot;219.25&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;657.34&quot; cy=&quot;202.08&quot; rx=&quot;4.077669902912621&quot; ry=&quot;3.925233644859813&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;path d=&quot;M 578.85 276.17 L 583.94 265.37 L 589.04 265.37 L 583.94 276.17 Z M 589.04 276.17 L 594.14 265.37 L 599.24 265.37 L 594.14 276.17 Z M 599.24 276.17 L 604.33 265.37 L 609.43 265.37 L 604.33 276.17 Z M 609.43 276.17 L 614.53 265.37 L 619.62 265.37 L 614.53 276.17 Z M 619.62 276.17 L 624.72 265.37 L 629.82 265.37 L 624.72 276.17 Z M 629.82 276.17 L 634.92 265.37 L 640.01 265.37 L 634.92 276.17 Z M 578.85 259 L 583.94 248.2 L 589.04 248.2 L 583.94 259 Z M 589.04 259 L 594.14 248.2 L 599.24 248.2 L 594.14 259 Z M 599.24 259 L 604.33 248.2 L 609.43 248.2 L 604.33 259 Z M 609.43 259 L 614.53 248.2 L 619.62 248.2 L 614.53 259 Z M 619.62 259 L 624.72 248.2 L 629.82 248.2 L 624.72 259 Z M 629.82 259 L 634.92 248.2 L 640.01 248.2 L 634.92 259 Z M 578.85 241.82 L 583.94 231.03 L 589.04 231.03 L 583.94 241.82 Z M 589.04 241.82 L 594.14 231.03 L 599.24 231.03 L 594.14 241.82 Z M 599.24 241.82 L 603.82 231.03 L 608.92 231.03 L 603.82 241.82 Z M 609.43 241.82 L 614.53 231.03 L 619.62 231.03 L 614.53 241.82 Z M 619.62 241.82 L 624.72 231.03 L 629.82 231.03 L 624.72 241.82 Z M 629.82 241.82 L 634.92 231.03 L 640.01 231.03 L 634.92 241.82 Z M 578.85 224.65 L 583.94 213.86 L 589.04 213.86 L 583.94 224.65 Z M 589.04 224.65 L 594.14 213.86 L 599.24 213.86 L 594.14 224.65 Z M 599.24 224.65 L 604.33 213.86 L 609.43 213.86 L 604.33 224.65 Z M 609.43 224.65 L 614.53 213.86 L 619.62 213.86 L 614.53 224.65 Z M 619.62 224.65 L 624.72 213.86 L 629.82 213.86 L 624.72 224.65 Z M 629.82 224.65 L 634.92 213.86 L 640.01 213.86 L 634.92 224.65 Z M 578.85 207.48 L 583.94 196.68 L 589.04 196.68 L 583.94 207.48 Z M 589.04 207.48 L 594.14 196.68 L 599.24 196.68 L 594.14 207.48 Z M 599.24 207.48 L 604.33 196.68 L 609.43 196.68 L 604.33 207.48 Z M 609.43 207.48 L 614.53 196.68 L 619.62 196.68 L 614.53 207.48 Z M 619.62 207.48 L 624.72 196.68 L 629.82 196.68 L 624.72 207.48 Z M 629.82 207.48 L 634.92 196.68 L 640.01 196.68 L 634.92 207.48 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;rect x=&quot;573.75&quot; y=&quot;180&quot; width=&quot;0&quot; height=&quot;0&quot; fill=&quot;none&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;ellipse cx=&quot;660.4&quot; cy=&quot;267.34&quot; rx=&quot;18.349514563106794&quot; ry=&quot;17.66355140186916&quot; fill=&quot;#cccccc&quot; stroke=&quot;#6881b3&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(204, 204, 204); stroke: rgb(104, 129, 179);&quot;&#x2F;&gt;&lt;rect x=&quot;648.68&quot; y=&quot;258.5&quot; width=&quot;23.45&quot; height=&quot;17.66&quot; fill=&quot;none&quot; stroke=&quot;#ffffff&quot; stroke-width=&quot;1.96&quot; pointer-events=&quot;all&quot; style=&quot;stroke: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;rect x=&quot;651.23&quot; y=&quot;260.96&quot; width=&quot;18.35&quot; height=&quot;13.25&quot; fill=&quot;#ffffff&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(255, 255, 255);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-56&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 708.75 90 C 708.75 78.95 717.7 70 728.75 70 C 739.8 70 748.75 78.95 748.75 90 C 748.75 101.05 739.8 110 728.75 110 C 717.7 110 708.75 101.05 708.75 90 Z M 740.33 97.88 C 744.13 92.32 743.44 84.84 738.68 80.07 C 733.91 75.31 726.43 74.62 720.87 78.42 Z M 717.21 82.12 C 713.42 87.67 714.11 95.14 718.86 99.9 C 723.6 104.66 731.07 105.37 736.63 101.6 Z&quot; fill=&quot;#f8cecc&quot; stroke=&quot;#b85450&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(248, 206, 204); stroke: rgb(184, 84, 80);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-59&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 678.75 232.56 L 795 232.56 L 795 76.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 795 71.12 L 798.5 78.12 L 795 76.37 L 791.5 78.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;LT5l49i-5sKJs4NMfgQQ-33&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 781.4 156.35 C 781.76 155 782.67 153.87 783.9 153.24 C 785.13 152.61 786.56 152.55 787.84 153.07 C 789.7 153.99 791.15 155.6 791.87 157.58 C 795.19 147.96 800.25 139.06 806.77 131.33 C 808.63 129.62 811.21 129 813.62 129.69 C 814.24 129.79 814.76 130.21 815.01 130.79 C 815.25 131.37 815.18 132.04 814.83 132.56 C 805.96 142.76 799.36 154.79 795.49 167.83 C 793.21 169 790.52 169 788.24 167.83 C 786.52 163.94 784.21 160.34 781.4 157.17 C 781.25 156.92 781.25 156.6 781.4 156.35 Z&quot; fill=&quot;#d5e8d4&quot; stroke=&quot;#82b366&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(213, 232, 212); stroke: rgb(130, 179, 102);&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;DG0Eh5BLZ3PX7DVNh1gw-1&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 500 140 L 500 173.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 500 178.88 L 496.5 171.88 L 500 173.63 L 503.5 171.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;DG0Eh5BLZ3PX7DVNh1gw-2&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 626.25 140 L 626.25 173.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 626.25 178.88 L 622.75 171.88 L 626.25 173.63 L 629.75 171.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;switch&gt;&lt;g requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&#x2F;&gt;&lt;a transform=&quot;translate(0,-5)&quot; xlink:href=&quot;https:&#x2F;&#x2F;www.drawio.com&#x2F;doc&#x2F;faq&#x2F;svg-export-text-problems&quot; target=&quot;_blank&quot;&gt;&lt;text text-anchor=&quot;middle&quot; font-size=&quot;10px&quot; x=&quot;50%&quot; y=&quot;100%&quot;&gt;Text is not SVG - cannot display&lt;&#x2F;text&gt;&lt;&#x2F;a&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;svg&gt;&lt;!----&gt;
  
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;准备&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#准备&quot; aria-label=&quot;Anchor link for: 准备&quot;&gt;准备&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在开始理解代理之前，首先需要复习一些计算机网络知识。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;OSI_模型&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#OSI_模型&quot; aria-label=&quot;Anchor link for: OSI_模型&quot;&gt;OSI 模型&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;OSI 模型将通讯系统中的数据流划分为了七个层：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;L7 应用层：唯一直接接触用户的层。定义了应用程序之间通讯的接口。&lt;&#x2F;li&gt;
&lt;li&gt;L6 表示层：处理格式转换（加密、压缩、编码）。&lt;&#x2F;li&gt;
&lt;li&gt;L5 会话层：设置和维护两个设备之间的通信（维持会话）。&lt;&#x2F;li&gt;
&lt;li&gt;L4 传输层：两个设备间的端到端通信（流量控制和错误控制）。&lt;&#x2F;li&gt;
&lt;li&gt;L3 网络层：两个不同网络之间的数据传输（路由）。&lt;&#x2F;li&gt;
&lt;li&gt;L2 数据链路层：设备点对点的网络寻址、错误检测和错误控制。&lt;&#x2F;li&gt;
&lt;li&gt;L1 物理层：参与数据传输的物理设备。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;figure class=&quot;inline-svg&quot;&gt;
  &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!-- Do not edit this file with editors other than draw.io --&gt;
&lt;!DOCTYPE svg PUBLIC &quot;-&#x2F;&#x2F;W3C&#x2F;&#x2F;DTD SVG 1.1&#x2F;&#x2F;EN&quot; &quot;http:&#x2F;&#x2F;www.w3.org&#x2F;Graphics&#x2F;SVG&#x2F;1.1&#x2F;DTD&#x2F;svg11.dtd&quot;&gt;
&lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; style=&quot;background: transparent; background-color: transparent; color-scheme: light dark;&quot; xmlns:xlink=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xlink&quot; version=&quot;1.1&quot; width=&quot;1081px&quot; height=&quot;321px&quot; viewBox=&quot;-0.5 -0.5 1081 321&quot; content=&quot;&amp;lt;mxfile host=&amp;quot;Electron&amp;quot; agent=&amp;quot;Mozilla&#x2F;5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit&#x2F;537.36 (KHTML, like Gecko) draw.io&#x2F;28.0.4 Chrome&#x2F;138.0.7204.97 Electron&#x2F;37.2.1 Safari&#x2F;537.36&amp;quot; version=&amp;quot;28.0.4&amp;quot;&amp;gt;&amp;#10;  &amp;lt;diagram name=&amp;quot;第 1 页&amp;quot; id=&amp;quot;NIRP4e9idBFbi0EXMQZO&amp;quot;&amp;gt;&amp;#10;    &amp;lt;mxGraphModel dx=&amp;quot;1042&amp;quot; dy=&amp;quot;659&amp;quot; grid=&amp;quot;1&amp;quot; gridSize=&amp;quot;10&amp;quot; guides=&amp;quot;1&amp;quot; tooltips=&amp;quot;1&amp;quot; connect=&amp;quot;1&amp;quot; arrows=&amp;quot;1&amp;quot; fold=&amp;quot;1&amp;quot; page=&amp;quot;1&amp;quot; pageScale=&amp;quot;1&amp;quot; pageWidth=&amp;quot;1169&amp;quot; pageHeight=&amp;quot;827&amp;quot; math=&amp;quot;0&amp;quot; shadow=&amp;quot;0&amp;quot;&amp;gt;&amp;#10;      &amp;lt;root&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;1&amp;quot; parent=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-1&amp;quot; value=&amp;quot;L7 应用层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-2&amp;quot; value=&amp;quot;L6 表示层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-3&amp;quot; value=&amp;quot;L5 会话层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;160&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-4&amp;quot; value=&amp;quot;L4 传输层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-5&amp;quot; value=&amp;quot;L3 网络层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-6&amp;quot; value=&amp;quot;L2 数据链路层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-7&amp;quot; value=&amp;quot;L1 物理层&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-8&amp;quot; value=&amp;quot;HTTP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-9&amp;quot; value=&amp;quot;TCP&#x2F;QUIC&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-12&amp;quot; value=&amp;quot;IP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-13&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-14&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-15&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-16&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-17&amp;quot; value=&amp;quot;IP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-18&amp;quot; value=&amp;quot;TCP&#x2F;QUIC&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-19&amp;quot; value=&amp;quot;HTTP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-20&amp;quot; value=&amp;quot;TLS&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-21&amp;quot; value=&amp;quot;http:&#x2F;&#x2F;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-22&amp;quot; value=&amp;quot;https:&#x2F;&#x2F;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;280&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-23&amp;quot; value=&amp;quot;DNS over UDP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-25&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;160&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-26&amp;quot; value=&amp;quot;DNS&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-27&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-28&amp;quot; value=&amp;quot;UDP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-29&amp;quot; value=&amp;quot;IP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-30&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-31&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-32&amp;quot; value=&amp;quot;DNS over TLS&amp;amp;lt;div&amp;amp;gt;(DoT)&amp;amp;lt;&#x2F;div&amp;amp;gt;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-33&amp;quot; value=&amp;quot;DNS&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-34&amp;quot; value=&amp;quot;TLS&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-35&amp;quot; value=&amp;quot;TCP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-36&amp;quot; value=&amp;quot;IP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-37&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-38&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;640&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-39&amp;quot; value=&amp;quot;DNS over HTTPS (DoH)&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-40&amp;quot; value=&amp;quot;DNS + HTTP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-41&amp;quot; value=&amp;quot;TLS&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-42&amp;quot; value=&amp;quot;TCP&#x2F;QUIC&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-43&amp;quot; value=&amp;quot;IP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-44&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-45&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-46&amp;quot; value=&amp;quot;ping&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;880&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-47&amp;quot; value=&amp;quot;IP (ICMP)&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;880&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-48&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;880&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;160&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-49&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;880&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-50&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;880&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-52&amp;quot; value=&amp;quot;ssh:&#x2F;&#x2F;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;400&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-53&amp;quot; value=&amp;quot;SSH&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;400&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;120&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-54&amp;quot; value=&amp;quot;TCP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;400&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-55&amp;quot; value=&amp;quot;IP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;400&amp;quot; y=&amp;quot;240&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-56&amp;quot; value=&amp;quot;Ethernet&#x2F;Wi‑Fi&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;400&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-57&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;400&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-79&amp;quot; value=&amp;quot;OSI 模型&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-81&amp;quot; value=&amp;quot;终端设备常见实现&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;1000&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-84&amp;quot; value=&amp;quot;网卡&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;1000&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-86&amp;quot; value=&amp;quot;双绞线&#x2F;光纤&#x2F;射频&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;1000&amp;quot; y=&amp;quot;320&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-87&amp;quot; value=&amp;quot;应用程序&amp;amp;lt;div&amp;amp;gt;（浏览器、服务器等）&amp;amp;lt;&#x2F;div&amp;amp;gt;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;1000&amp;quot; y=&amp;quot;80&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-88&amp;quot; value=&amp;quot;应用程序的编解码库&amp;amp;lt;div&amp;amp;gt;（OpenSSL、&amp;amp;lt;span style=&amp;amp;quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&amp;amp;quot;&amp;amp;gt;BoringSSL等&amp;amp;lt;&#x2F;span&amp;amp;gt;&amp;amp;lt;span style=&amp;amp;quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&amp;amp;quot;&amp;amp;gt;）&amp;amp;lt;&#x2F;span&amp;amp;gt;&amp;amp;lt;&#x2F;div&amp;amp;gt;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;1000&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;lX5WImYW38jEtJqywhDp-89&amp;quot; value=&amp;quot;操作系统提供的 TCP&#x2F;IP 协议栈&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; vertex=&amp;quot;1&amp;quot; parent=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;1000&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;80&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;      &amp;lt;&#x2F;root&amp;gt;&amp;#10;    &amp;lt;&#x2F;mxGraphModel&amp;gt;&amp;#10;  &amp;lt;&#x2F;diagram&amp;gt;&amp;#10;&amp;lt;&#x2F;mxfile&amp;gt;&amp;#10;&quot;&gt;&lt;defs&#x2F;&gt;&lt;g&gt;&lt;g data-cell-id=&quot;0&quot;&gt;&lt;g data-cell-id=&quot;1&quot;&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-1&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L7 应用层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L7 应用层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-2&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 100px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L6 表示层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;104&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L6 表示层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-3&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;120&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 140px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L5 会话层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;144&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L5 会话层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-4&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L4 传输层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L4 传输层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-5&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L3 网络层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L3 网络层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-6&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L2 数据链路层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L2 数据链路层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-7&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;L1 物理层&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;L1 物理层&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-8&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 121px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;HTTP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;180&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;HTTP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-9&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 121px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TCP&#x2F;QUIC&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;180&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TCP&#x2F;QUIC&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-12&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 121px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;180&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-13&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 121px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;180&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-14&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 121px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;180&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-15&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-16&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-17&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-18&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TCP&#x2F;QUIC&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TCP&#x2F;QUIC&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-19&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;HTTP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;HTTP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-20&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 120px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TLS&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TLS&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-21&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 121px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;http:&#x2F;&#x2F;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;180&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;http:&#x2F;&#x2F;&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-22&quot;&gt;&lt;g&gt;&lt;rect x=&quot;240&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 241px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;https:&#x2F;&#x2F;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;300&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;https:&#x2F;&#x2F;&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-23&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS over UDP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS over UDP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-25&quot;&gt;&lt;g&gt;&lt;rect x=&quot;120&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-26&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-27&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-28&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;UDP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;UDP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-29&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-30&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-31&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-32&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS over TLS&lt;div&gt;(DoT)&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS over TLS...&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-33&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-34&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 120px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TLS&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TLS&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-35&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TCP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TCP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-36&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-37&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-38&quot;&gt;&lt;g&gt;&lt;rect x=&quot;600&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 601px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;660&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-39&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS over HTTPS (DoH)&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS over HTTPS (DoH)&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-40&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS + HTTP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS + HTTP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-41&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 120px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TLS&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TLS&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-42&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TCP&#x2F;QUIC&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TCP&#x2F;QUIC&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-43&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-44&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-45&quot;&gt;&lt;g&gt;&lt;rect x=&quot;720&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 721px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;780&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-46&quot;&gt;&lt;g&gt;&lt;rect x=&quot;840&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 841px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;ping&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;900&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;ping&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-47&quot;&gt;&lt;g&gt;&lt;rect x=&quot;840&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 841px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP (ICMP)&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;900&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP (ICMP)&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-48&quot;&gt;&lt;g&gt;&lt;rect x=&quot;840&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;160&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-49&quot;&gt;&lt;g&gt;&lt;rect x=&quot;840&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 841px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;900&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-50&quot;&gt;&lt;g&gt;&lt;rect x=&quot;840&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 841px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;900&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-52&quot;&gt;&lt;g&gt;&lt;rect x=&quot;360&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 361px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;ssh:&#x2F;&#x2F;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;420&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;ssh:&#x2F;&#x2F;&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-53&quot;&gt;&lt;g&gt;&lt;rect x=&quot;360&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;120&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 100px; margin-left: 361px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;SSH&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;420&quot; y=&quot;104&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;SSH&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-54&quot;&gt;&lt;g&gt;&lt;rect x=&quot;360&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 361px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;TCP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;420&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;TCP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-55&quot;&gt;&lt;g&gt;&lt;rect x=&quot;360&quot; y=&quot;200&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 220px; margin-left: 361px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;IP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;420&quot; y=&quot;224&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;IP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-56&quot;&gt;&lt;g&gt;&lt;rect x=&quot;360&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 361px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;420&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Ethernet&#x2F;Wi‑Fi&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-57&quot;&gt;&lt;g&gt;&lt;rect x=&quot;360&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 361px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;420&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-79&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;OSI 模型&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;OSI 模型&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-81&quot;&gt;&lt;g&gt;&lt;rect x=&quot;960&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 961px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;终端设备常见实现&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;1020&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;终端设备常见实现&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-84&quot;&gt;&lt;g&gt;&lt;rect x=&quot;960&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 961px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;网卡&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;1020&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;网卡&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-86&quot;&gt;&lt;g&gt;&lt;rect x=&quot;960&quot; y=&quot;280&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 300px; margin-left: 961px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;1020&quot; y=&quot;304&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;双绞线&#x2F;光纤&#x2F;射频&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-87&quot;&gt;&lt;g&gt;&lt;rect x=&quot;960&quot; y=&quot;40&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 60px; margin-left: 961px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;应用程序&lt;div&gt;（浏览器、服务器等）&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;1020&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;应用程序&amp;#xa;（浏览器、服务器等）&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-88&quot;&gt;&lt;g&gt;&lt;rect x=&quot;960&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 120px; margin-left: 961px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;应用程序的编解码库&lt;div&gt;（OpenSSL、&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;BoringSSL等&lt;&#x2F;span&gt;&lt;span style=&quot;background-color: transparent; color: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&gt;）&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;1020&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;应用程序的编解码库&amp;#xa;（OpenSSL、BoringSSL等）&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;lX5WImYW38jEtJqywhDp-89&quot;&gt;&lt;g&gt;&lt;rect x=&quot;960&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;80&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 200px; margin-left: 961px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;操作系统提供的 TCP&#x2F;IP 协议栈&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;1020&quot; y=&quot;204&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;操作系统提供的 TCP&#x2F;IP 协议栈&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;switch&gt;&lt;g requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&#x2F;&gt;&lt;a transform=&quot;translate(0,-5)&quot; xlink:href=&quot;https:&#x2F;&#x2F;www.drawio.com&#x2F;doc&#x2F;faq&#x2F;svg-export-text-problems&quot; target=&quot;_blank&quot;&gt;&lt;text text-anchor=&quot;middle&quot; font-size=&quot;10px&quot; x=&quot;50%&quot; y=&quot;100%&quot;&gt;Text is not SVG - cannot display&lt;&#x2F;text&gt;&lt;&#x2F;a&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;svg&gt;&lt;!----&gt;
  
&lt;&#x2F;figure&gt;
&lt;p&gt;上图描述了 OSI 七个层在常见应用场景下的对应的协议和在终端设备（PC）上的常见实现。&lt;&#x2F;p&gt;
&lt;p&gt;这里只是“常见”实现，因为理论上每一层完全可以独立存在。上层的协议对于下层的来说只是其承载的内容而已，下层协议对于上层的协议来说只是载体。每一层之间就像俄罗斯套娃一样。&lt;&#x2F;p&gt;
&lt;p&gt;比如，HTTP 协议只是定义了一个基于文本的格式，实际上完全可以不依赖 TCP&#x2F;IP 协议传输 HTTP 请求，比如，把 HTTP 请求文本写在纸上，让信鸽来传递（IPoAC，&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc1149&quot;&gt;RFC 1149&lt;&#x2F;a&gt;）。&lt;&#x2F;p&gt;
&lt;p&gt;现实中 TCP&#x2F;IP 协议也是运行在不同的数据链路层&#x2F;物理层的，比如 Ethernet + 双绞线、Ethernet + 光纤、Wi‑Fi + 射频等。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;DNS&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#DNS&quot; aria-label=&quot;Anchor link for: DNS&quot;&gt;DNS&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;众所周知，一般人在使用互联网时不会在浏览器中输入 IP 地址来访问网站，而是输入域名，但是上述的 TCP&#x2F;IP 协议实际上只认识 IP 地址，所以，需要 DNS 服务将域名转换为 IP 地址。DNS 服务类似一个电话簿，用户发送一个域名，它就可以返回对应的 IP 地址。当然，DNS 服务器还有更多功能，这里指的是最基础的 A 记录。&lt;&#x2F;p&gt;
&lt;p&gt;如上一节所说，和 HTTP 协议类似，DNS 协议也可以建立来不同的层级之上，传统的 DNS 协议是 DNS over UDP，即建立在 UDP 协议上的 DNS 协议，除此之外，还有 DNS over TCP、DNS over TLS、DNS over HTTPS 等。&lt;&#x2F;p&gt;
&lt;p&gt;当用户在浏览器中输入一个网址时，会经历以下过程：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;缓存检查：浏览器检查本地 DNS 缓存、HTTP 缓存等，存在则可以跳过一些步骤。&lt;&#x2F;li&gt;
&lt;li&gt;DNS 解析：向 DNS 服务器发送请求，将域名转换为 IP 地址。&lt;&#x2F;li&gt;
&lt;li&gt;建立 TCP 连接：发送三次握手，和远程服务器建立 TCP 链接。&lt;&#x2F;li&gt;
&lt;li&gt;建立 TLS 连接：如果使用的是 HTTPS 协议，则与远程服务器进行密钥协商、证书校验等，建立加密隧道。&lt;&#x2F;li&gt;
&lt;li&gt;发送 HTTP 请求：组装一个标准的 HTTP 报文，通过 TCP&#x2F;TLS 通道发往服务器。&lt;&#x2F;li&gt;
&lt;li&gt;处理请求：服务器处理请求，生成 HTTP 响应，发送给客户端。&lt;&#x2F;li&gt;
&lt;li&gt;解析和渲染：浏览器解析响应信息，并将内容渲染在屏幕上。&lt;&#x2F;li&gt;
&lt;li&gt;连接关闭：根据特定策略关闭 TCP&#x2F;TLS 连接，处理缓存逻辑。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;HTTP_代理&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#HTTP_代理&quot; aria-label=&quot;Anchor link for: HTTP_代理&quot;&gt;HTTP 代理&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;为了不让那些不安全的网站获取的真实的 IP 地址，最简单的方案就是使用 HTTP 代理。&lt;&#x2F;p&gt;
&lt;p&gt;HTTP 代理位于 L7 应用层，它的工作原理十分简单，比如，我希望请求 &lt;code&gt;unsafe.example.com&lt;&#x2F;code&gt; 这个不安全的网站，可以不直接请求这个网站，而是转而请求 &lt;code&gt;proxy.example.com&lt;&#x2F;code&gt; 这个运行了代理服务器的网址，代理服务器会读取 HTTP 请求头中的 &lt;code&gt;Host&lt;&#x2F;code&gt; 字段，以得知用户真正需要请求的网站，代替用户发送网络请求，并将响应结果返回给用户。这样，网站只知道代理服务器的 IP 向它发送了一个请求，而不知道用户真实的 IP 地址。这也就是“代理”这一个词的含义，代替用户发送网络请求。&lt;&#x2F;p&gt;
&lt;p&gt;其原理非常简单，下面是一个用于描述其原理的简单示例：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; http.server&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; BaseHTTPRequestHandler, HTTPServer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; requests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;LISTEN_HOST =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;127.0.0.1&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;LISTEN_PORT =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8888&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; ProxyHandler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt;BaseHTTPRequestHandler&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; _proxy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        # 构造目标 URL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        target_url =&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;http:&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-variable z-language&quot;&gt;{self&lt;&#x2F;span&gt;&lt;span&gt;.headers[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Host&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-variable z-language&quot;&gt;}{self&lt;&#x2F;span&gt;&lt;span&gt;.path&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        # 准备请求头&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        headers = {k: v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; k, v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.headers.items()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; k.lower() !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;host&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        # 读取请求体&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        body =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Content-Length&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python z-variable z-language&quot;&gt; in self&lt;&#x2F;span&gt;&lt;span&gt;.headers:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            length =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.headers[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Content-Length&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            body =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.rfile.read(length)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        # 发起请求&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        resp = requests.request(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span&gt;.command, target_url,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=headers,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=body,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        # 转发状态码和头部&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.send_response(resp.status_code)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; k, v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; resp.headers.items():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; k.lower()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt; not in&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;content-encoding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;transfer-encoding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;connection&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;                self&lt;&#x2F;span&gt;&lt;span&gt;.send_header(k, v)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.end_headers()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        # 转发响应体&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; chunk&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; resp.iter_content(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;4096&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span&gt;.wfile.write(chunk)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; do_GET&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;._proxy()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; do_POST&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;._proxy()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    server = HTTPServer((LISTEN_HOST, LISTEN_PORT), ProxyHandler)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;[+] http:&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;LISTEN_HOST&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;LISTEN_PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    server.serve_forever()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HTTP 代理是一个通用的协议，一般可以直接在操作系统中设置，这样应用程序读取到这个配置后就知道自己不应该直接发送网络请求，而是应该发送到代理服务器的网址。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;st1020.com&#x2F;posts&#x2F;understand-proxy&#x2F;mac_proxy_setting.png&quot; alt=&quot;macOS Proxy Setting&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;还有一些软件，例如 FireFox，则是提供了自己单独的代理设置。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;st1020.com&#x2F;posts&#x2F;understand-proxy&#x2F;firefox_proxy_setting.png&quot; alt=&quot;FireFox Proxy Setting&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;但是，简单的 HTTP 代理有一些问题：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;出于一些原因，代理服务器可能并不直接向外提供 HTTP 代理服务，而是提供某种加密的代理服务，即用户在发送前先将请求体加密，代理服务器收到后先解密，再进行转发。但是，很显然，应用程序通常并不支持这种非标准的协议。&lt;&#x2F;li&gt;
&lt;li&gt;我们不仅需要访问一些“不安全”的网站，也需要访问一些“安全”的网站，访问“安全”网站时，我们不希望走代理。而 HTTP 代理是一个全局配置，一旦配置所有 HTTP 网络请求都会走代理。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;本地代理&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#本地代理&quot; aria-label=&quot;Anchor link for: 本地代理&quot;&gt;本地代理&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;为了实现自动分流和加密协议代理，我们需要在本地启动一个代理服务器（以下简称代理软件），这个代理软件将根据一个网站名单决定如何转发请求。对于名单内的网站将转发给位于远程的代理服务器，而其他网站则直接请求。&lt;&#x2F;p&gt;
&lt;p&gt;并且，代理软件还可以进行代理格式的转换：暴露一个普通的 HTTP 代理服务给用户，而在转发给远程代理服务器时则可以使用其实现的任意非标准协议。&lt;&#x2F;p&gt;
&lt;p&gt;看起来很很完美，我再也不用担心被不安全的网站获取真实的 IP 地址啦！&lt;&#x2F;p&gt;
&lt;p&gt;但是还是有一个“小问题”，应用程序可能并不会使用我们配置的 HTTP 代理。&lt;&#x2F;p&gt;
&lt;p&gt;正如 HTTP 代理一节所说，当我们设置了 HTTP 代理后，应用程序将会请求代理服务器而非原本的地址，但是，这完全是应用程序“自愿”的选择，它应该这样做，但也完全可以选择不这样做。当我们在操作系统中设置了 HTTP 代理后，操作系统只是会告诉应用程序现在设置了代理，例如通过 &lt;code&gt;HTTP_PROXY&lt;&#x2F;code&gt; 和 &lt;code&gt;HTTPS_PROXY&lt;&#x2F;code&gt; 环境变量，但是是否真的要请求代理服务器则完全是应用开发者的选择，有些应用程序并没有支持代理功能，或者有自己的代理设置，需要分别设置。&lt;&#x2F;p&gt;
&lt;p&gt;并且正如它的名字和工作原理，HTTP 代理自然只支持 HTTP 协议，无法处理任何其他网络请求，比如同样位于 L7 应用层的 SMTP、FTP、SSH 等协议，还有位于更底层的 TCP&#x2F;UDP&#x2F;ICMP 等协议。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;明确需求&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#明确需求&quot; aria-label=&quot;Anchor link for: 明确需求&quot;&gt;明确需求&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;让我们先来系统地梳理一下我对代理的需求：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;按照网站分流：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;我拥有一份不安全的网站（或者公司外部网站）的名单，我希望使用代理访问它们。&lt;&#x2F;li&gt;
&lt;li&gt;我拥有一份安全的网站（或者公司内部网站）的名单，我希望直接访问他们。&lt;&#x2F;li&gt;
&lt;li&gt;对于其他未知的网站可以根据需要选择直接访问或者通过代理访问（下面假设对于这种网站也通过代理访问）。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;支持 TCP&#x2F;UDP：除了 HTTP 之外的其他 TCP&#x2F;UDP 通讯也要支持通过代理。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;透明代理：应用程序不需要额外配置就会自动走代理，即代理的存在对于应用程序来说是透明的，它并不知道自己在通过代理访问网络。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;准确的 DNS：我们本地的 DNS 服务器可能是不准确的，比如，公司内网可能存在自己搭建的 DNS 服务器，它可能更新不及时，造成查询结果不正确。&lt;&#x2F;p&gt;
&lt;p&gt;但是，对于公司内部网站，我们还是应该优先使用公司内部的 DNS 服务器，因为它更加快速，并且只有公司内部的 DNS 服务器才记录了公司内部域名的信息。&lt;&#x2F;p&gt;
&lt;p&gt;也就是说，需要走代理的网站的 DNS 解析也要走代理。不走代理的网站的 DNS 解析也不走代理。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;性能：实现上述功能的前提下，网络性能尽可能好。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;当前的本地 HTTP 代理软件方案可以实现，1. 分流、4. 准确的 DNS 和 5. 性能。能实现 4 因为其发送给远程代理服务器的就是域名，代理服务器自然会在远程进行 DNS 解析。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;TUN_代理&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#TUN_代理&quot; aria-label=&quot;Anchor link for: TUN_代理&quot;&gt;TUN 代理&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;首先我们如何让尽可能多的网络请求经过代理呢？&lt;&#x2F;p&gt;
&lt;p&gt;很简单，让代理软件工作在 OSI 模型中尽可能低的层级。&lt;&#x2F;p&gt;
&lt;p&gt;如果不考虑实际连一条光纤到代理服务器的话，我们能够控制的最低的层级就是 L2&#x2F;L3——虚拟网卡，又称 TAP&#x2F;TUN。&lt;&#x2F;p&gt;
&lt;p&gt;一般情况下，我们不会考虑 TCP&#x2F;IP 协议之外的情况，因此，我们选择工作在 L3 网络层的 TUN，这在桌面端平台上对应虚拟网卡设备，在移动平台上则对应系统提供的 VPN（狭义的）接口。&lt;&#x2F;p&gt;
&lt;p&gt;TUN 代理要做的第一步就是进行 L3 到 L4 的转换，代理软件将会解析 IP 数据包中的内容，从其中提取出 TCP&#x2F;UDP 协议内容。&lt;&#x2F;p&gt;
&lt;p&gt;但是，我们又遇到了一个新的问题，现在代理对于应用程序来说是透明的，代理软件无从得知用户请求的域名。如果是 HTTP 代理，它可以通过 HTTP 请求头中的 &lt;code&gt;Host&lt;&#x2F;code&gt; 请求头得知需要请求的域名，从而按照黑白名单进行分流。但是现在，应用并不知道自己正在走代理，因此进行的还是正常的请求流程：先进行 DNS 解析，拿到 IP 再进行请求。这时位于 L3&#x2F;L4 的代理软件拿到的只有 IP，无法按照域名进行分流。&lt;&#x2F;p&gt;
&lt;p&gt;这个问题看似无解，但好在聪明的代理软件开发者想到了一个解决方案——域名嗅探。代理软件可以进一步解析 TCP 协议承载的内容，如果分析得到其内容类似 HTTP 协议，则可以按照之前的流程提取出域名。除了 HTTP 协议外，代理软件通常实现了更多常见的协议的嗅探。&lt;&#x2F;p&gt;
&lt;p&gt;现在我们成功实现了 1. 分流、2. 支持 TCP&#x2F;UDP 和 3. 透明代理。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;DNS_劫持&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#DNS_劫持&quot; aria-label=&quot;Anchor link for: DNS_劫持&quot;&gt;DNS 劫持&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;现在，剩下的就是如何解决我们本地的 DNS 服务器不够准确的问题。&lt;&#x2F;p&gt;
&lt;p&gt;思路和域名嗅探类似，DNS 协议运行于特定的端口（DNS over UDP 运行于 53 端口），并且像 HTTP 一样，DNS 请求也具有一定的特征，代理软件可以得知当前请求是 DNS 协议，并对其进行劫持。&lt;&#x2F;p&gt;
&lt;p&gt;当代理软件发现应用程序发送了一个 DNS 请求时，不会实际执行这个请求，而是先判断这个域名在哪个名单中，按照规则请求本地的 DNS 服务器或者通过代理请求特定公共 DNS 服务器。&lt;&#x2F;p&gt;
&lt;p&gt;似乎所有问题都解决了……吗？&lt;&#x2F;p&gt;
&lt;h2 id=&quot;性能问题&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#性能问题&quot; aria-label=&quot;Anchor link for: 性能问题&quot;&gt;性能问题&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;别忘了，我们还有最后一个要求，性能要足够好。&lt;&#x2F;p&gt;
&lt;p&gt;虽然刚才提到的过程看起来很复杂，L3 到 L4 转换、协议嗅探、DNS 劫持、域名分流等等，但对于现代的计算机来说，这些计算任务都不是问题，网络请求才是最耗时间的。&lt;&#x2F;p&gt;
&lt;p&gt;但是看起来刚才的流程中并没有引入新的网络请求啊，为什么会影响性能呢？那是因为 DNS 解析并不如同我们刚才讲到的那么简单。&lt;&#x2F;p&gt;
&lt;p&gt;现代网站都依靠 CDN 加速网络请求，简单来说，就是部署很多服务器，用户优先访问距离自己最近的服务器获取内容，以加速网络请求。这个过程是要依赖 DNS 服务器的。当用户向 DNS 服务器请求有 CDN 加速的网站时，DNS 服务器可以根据请求者的 IP 地址返回距离其最近的 CDN 服务器的 IP 地址。&lt;&#x2F;p&gt;
&lt;p&gt;但是，当我们通过代理请求 DNS 服务器时，DNS 服务器可能无法返回距离代理服务器最近的 CDN 节点的 IP。&lt;&#x2F;p&gt;
&lt;p&gt;为了解决这个问题，我们希望代理服务器知道我正在访问的域名。这一方面是为了让代理服务器自行请求其配置好的最佳 DNS 服务器解析得到 IP 地址，以获得最佳的 CDN 命中。另一方面，也是为了允许代理服务进行二次分流，代理服务器可以根据请求的网站域名按照特定规则再次分流给二级代理服务器。&lt;&#x2F;p&gt;
&lt;p&gt;解决的方案还是域名嗅探，我们可以让代理软件在域名嗅探完成后不直接转发 IP 地址，而是用嗅探出的域名代替 IP 地址再转发给代理服务器。&lt;&#x2F;p&gt;
&lt;p&gt;但是，这个方案还是有一个问题，那就是造成了冗余的 DNS 请求。现在浏览器访问一个需要被代理的网站的流程如下：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;浏览器发起 DNS 解析&lt;&#x2F;li&gt;
&lt;li&gt;代理软件劫持 DNS 请求&lt;&#x2F;li&gt;
&lt;li&gt;代理软件通过远程代理请求公共 DNS&lt;&#x2F;li&gt;
&lt;li&gt;浏览器使用拿到的 IP 地址发起网络请求&lt;&#x2F;li&gt;
&lt;li&gt;代理软件进行域名嗅探，拿到实际请求的域名&lt;&#x2F;li&gt;
&lt;li&gt;代理软件使用域名代替 IP 转发给代理服务器&lt;&#x2F;li&gt;
&lt;li&gt;代理服务器请求 DNS 服务器拿到 IP&lt;&#x2F;li&gt;
&lt;li&gt;代理服务器使用 IP 实际发出请求&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;可以看到，第一次 DNS 解析得到的结果完全没有被用到，这次 DNS 请求只是因为应用程序不知道自己处于代理环境导致的。&lt;&#x2F;p&gt;
&lt;p&gt;此外，使用嗅探出的域名代替 IP 地址还有一定风险，即嗅探出来的域名不一定是正确的。以 HTTP 请求为例，毕竟 &lt;code&gt;Host&lt;&#x2F;code&gt; 也只是一个请求头，用户完全可以手动发起一个带有特定 &lt;code&gt;Host&lt;&#x2F;code&gt; 请求头，但是实际指定向某个 IP 请求的 HTTP 请求，而如果强行用 &lt;code&gt;Host&lt;&#x2F;code&gt; 替代 IP，就会导致请求了错误了服务器。也就是说，用嗅探出来的域名做分流没问题，最多只是选错这个请求需要直连还是走代理而已，但如果用于转发，在极少数情况下就可能会出错了。&lt;&#x2F;p&gt;
&lt;p&gt;似乎，鱼与熊掌不可兼得？&lt;&#x2F;p&gt;
&lt;h2 id=&quot;FakeIP&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#FakeIP&quot; aria-label=&quot;Anchor link for: FakeIP&quot;&gt;FakeIP&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;FakeIP 是 IETF 在 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc3089&quot;&gt;RFC 3089&lt;&#x2F;a&gt; 中提供的一个网关方案。&lt;&#x2F;p&gt;
&lt;p&gt;所谓 FakeIP，是指代理软件可以在劫持 DNS 请求后，不转发这次 DNS 请求，而是立即返回一个假的 IP 地址（FakeIP），并在自己的数据库中新增一条记录：FakeIP -&amp;gt; 域名。后续，当应用程序请求这个 FakeIP 时，就查询出真正的域名，使用记录的域名请求远程代理。这样就避免了冗余的 DNS 解析。在返回 FakeIP DNS 结果时，会将其 TTL 写为 1，以避免应用程序缓存 FakeIP 的 DNS 结果，导致在代理关闭后仍然使用 FakeIP 请求网站。&lt;&#x2F;p&gt;
&lt;p&gt;那么，我们是否应该为既不在安全网站名单，也不在不安全网站名单中的未知网站启用 FakeIP 呢？&lt;&#x2F;p&gt;
&lt;p&gt;理论上来说，因为未知网站也会通过代理请求，为了实现最佳的性能，启用 FakeIP 是合理的。但是，我们的列表可能并不全是域名列表，还有 IP 列表。假设我们拥有四种匹配规则：安全域名、不安全域名、安全 IP、不安全 IP。如果我们在 DNS 解析时，对不安全域名和未知域名均采取了 FakeIP，那么在路由时，IP 类的匹配规则就无法生效了。比如，存在一个未知域名，它实际指向了一个安全的 IP，由于我们在 DNS 解析时没有实际解析，而是将其解析为了 FakeIP，那么路由阶段就无法正确匹配“安全 IP”规则，导致本不需要走代理的网站错误地走了代理。&lt;&#x2F;p&gt;
&lt;p&gt;因此，如果优先考虑正确性，最终完整的方案如下：&lt;&#x2F;p&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;figure class=&quot;inline-svg&quot;&gt;
  &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!-- Do not edit this file with editors other than draw.io --&gt;
&lt;!DOCTYPE svg PUBLIC &quot;-&#x2F;&#x2F;W3C&#x2F;&#x2F;DTD SVG 1.1&#x2F;&#x2F;EN&quot; &quot;http:&#x2F;&#x2F;www.w3.org&#x2F;Graphics&#x2F;SVG&#x2F;1.1&#x2F;DTD&#x2F;svg11.dtd&quot;&gt;
&lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; style=&quot;background: transparent; background-color: transparent; color-scheme: light dark;&quot; xmlns:xlink=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xlink&quot; version=&quot;1.1&quot; width=&quot;761px&quot; height=&quot;442px&quot; viewBox=&quot;-0.5 -0.5 761 442&quot; content=&quot;&amp;lt;mxfile host=&amp;quot;Electron&amp;quot; agent=&amp;quot;Mozilla&#x2F;5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit&#x2F;537.36 (KHTML, like Gecko) draw.io&#x2F;28.0.4 Chrome&#x2F;138.0.7204.97 Electron&#x2F;37.2.1 Safari&#x2F;537.36&amp;quot; version=&amp;quot;28.0.4&amp;quot;&amp;gt;&amp;#10;  &amp;lt;diagram name=&amp;quot;第 1 页&amp;quot; id=&amp;quot;wCwicMGc-H3R1qBDOWEI&amp;quot;&amp;gt;&amp;#10;    &amp;lt;mxGraphModel dx=&amp;quot;1303&amp;quot; dy=&amp;quot;824&amp;quot; grid=&amp;quot;1&amp;quot; gridSize=&amp;quot;10&amp;quot; guides=&amp;quot;1&amp;quot; tooltips=&amp;quot;1&amp;quot; connect=&amp;quot;1&amp;quot; arrows=&amp;quot;1&amp;quot; fold=&amp;quot;1&amp;quot; page=&amp;quot;1&amp;quot; pageScale=&amp;quot;1&amp;quot; pageWidth=&amp;quot;1169&amp;quot; pageHeight=&amp;quot;827&amp;quot; math=&amp;quot;0&amp;quot; shadow=&amp;quot;0&amp;quot;&amp;gt;&amp;#10;      &amp;lt;root&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;1&amp;quot; parent=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-18&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-1&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-3&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-20&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-1&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-19&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-1&amp;quot; value=&amp;quot;浏览器&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;360&amp;quot; y=&amp;quot;40&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-11&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-3&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-4&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-12&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-3&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-5&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-13&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-3&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-6&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-3&amp;quot; value=&amp;quot;DNS 请求&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;200&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-14&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-4&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-7&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-4&amp;quot; value=&amp;quot;安全网站&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-15&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-5&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-8&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-5&amp;quot; value=&amp;quot;不安全网站&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;200&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-17&amp;quot; style=&amp;quot;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-6&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-9&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-6&amp;quot; value=&amp;quot;未知网站&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;360&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-7&amp;quot; value=&amp;quot;本地 DNS 服务器&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;40&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-8&amp;quot; value=&amp;quot;FakeIP&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;200&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-9&amp;quot; value=&amp;quot;通过代理服务器请求&amp;amp;lt;div&amp;amp;gt;公共 DNS 服务器&amp;amp;lt;&#x2F;div&amp;amp;gt;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;360&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-40&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-19&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-22&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-19&amp;quot; value=&amp;quot;HTTP 请求&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;120&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-41&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-22&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-23&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-22&amp;quot; value=&amp;quot;如果是 FakeIP&amp;amp;lt;div&amp;amp;gt;则还原为域名请求&amp;amp;lt;&#x2F;div&amp;amp;gt;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;200&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-45&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-23&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-42&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-46&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-23&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-43&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-47&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-23&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-44&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-23&amp;quot; value=&amp;quot;&amp;amp;lt;div&amp;amp;gt;域名嗅探&amp;amp;lt;&#x2F;div&amp;amp;gt;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;280&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-49&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-42&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-48&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-42&amp;quot; value=&amp;quot;安全网站&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;360&amp;quot; y=&amp;quot;360&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-51&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-43&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-50&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-43&amp;quot; value=&amp;quot;不安全网站&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;520&amp;quot; y=&amp;quot;360&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-53&amp;quot; style=&amp;quot;edgeStyle=none;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;kIc2mQei8pWa2ecX7WWh-44&amp;quot; target=&amp;quot;kIc2mQei8pWa2ecX7WWh-50&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot;&amp;gt;&amp;#10;            &amp;lt;mxPoint x=&amp;quot;740&amp;quot; y=&amp;quot;440&amp;quot; as=&amp;quot;targetPoint&amp;quot; &#x2F;&amp;gt;&amp;#10;          &amp;lt;&#x2F;mxGeometry&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-44&amp;quot; value=&amp;quot;未知网站&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;680&amp;quot; y=&amp;quot;360&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-48&amp;quot; value=&amp;quot;直接访问&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;360&amp;quot; y=&amp;quot;440&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;kIc2mQei8pWa2ecX7WWh-50&amp;quot; value=&amp;quot;代理访问&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;600&amp;quot; y=&amp;quot;440&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;40&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;      &amp;lt;&#x2F;root&amp;gt;&amp;#10;    &amp;lt;&#x2F;mxGraphModel&amp;gt;&amp;#10;  &amp;lt;&#x2F;diagram&amp;gt;&amp;#10;&amp;lt;&#x2F;mxfile&amp;gt;&amp;#10;&quot;&gt;&lt;defs&#x2F;&gt;&lt;g&gt;&lt;g data-cell-id=&quot;0&quot;&gt;&lt;g data-cell-id=&quot;1&quot;&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-18&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 380 40 L 226.18 78.46&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 221.08 79.73 L 227.03 74.64 L 226.18 78.46 L 228.72 81.43 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-20&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 380 40 L 533.82 78.46&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 538.92 79.73 L 531.28 81.43 L 533.82 78.46 L 532.97 74.64 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-1&quot;&gt;&lt;g&gt;&lt;rect x=&quot;320&quot; y=&quot;0&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 321px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;浏览器&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;380&quot; y=&quot;24&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;浏览器&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-11&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 220 120 L 66.18 158.46&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 61.08 159.73 L 67.03 154.64 L 66.18 158.46 L 68.72 161.43 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-12&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 220 120 L 220 153.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 220 158.88 L 216.5 151.88 L 220 153.63 L 223.5 151.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-13&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 220 120 L 373.82 158.46&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 378.92 159.73 L 371.28 161.43 L 373.82 158.46 L 372.97 154.64 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-3&quot;&gt;&lt;g&gt;&lt;rect x=&quot;160&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 100px; margin-left: 161px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;DNS 请求&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;220&quot; y=&quot;104&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;DNS 请求&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-14&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 60 200 L 60 233.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 60 238.88 L 56.5 231.88 L 60 233.63 L 63.5 231.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-4&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;安全网站&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;安全网站&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-15&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 220 200 L 220 233.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 220 238.88 L 216.5 231.88 L 220 233.63 L 223.5 231.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-5&quot;&gt;&lt;g&gt;&lt;rect x=&quot;160&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 161px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;不安全网站&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;220&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;不安全网站&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-17&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 380 200 L 380 233.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 380 238.88 L 376.5 231.88 L 380 233.63 L 383.5 231.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-6&quot;&gt;&lt;g&gt;&lt;rect x=&quot;320&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 321px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;未知网站&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;380&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;未知网站&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-7&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 1px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;本地 DNS 服务器&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;60&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;本地 DNS 服务器&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-8&quot;&gt;&lt;g&gt;&lt;rect x=&quot;160&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 161px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;FakeIP&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;220&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;FakeIP&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-9&quot;&gt;&lt;g&gt;&lt;rect x=&quot;320&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 321px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;通过代理服务器请求&lt;div&gt;公共 DNS 服务器&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;380&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;通过代理服务器请求&amp;#xa;公共 DNS 服务器&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-40&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 540 120 L 540 153.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 540 158.88 L 536.5 151.88 L 540 153.63 L 543.5 151.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-19&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;80&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 100px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;HTTP 请求&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;104&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;HTTP 请求&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-41&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 540 200 L 540 233.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 540 238.88 L 536.5 231.88 L 540 233.63 L 543.5 231.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-22&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;160&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 180px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;如果是 FakeIP&lt;div&gt;则还原为域名请求&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;如果是 FakeIP...&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-45&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 540 280 L 386.18 318.46&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 381.08 319.73 L 387.03 314.64 L 386.18 318.46 L 388.72 321.43 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-46&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 540 280 L 540 313.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 540 318.88 L 536.5 311.88 L 540 313.63 L 543.5 311.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-47&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 540 280 L 693.82 318.46&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 698.92 319.73 L 691.28 321.43 L 693.82 318.46 L 692.97 314.64 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-23&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;240&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 260px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;&lt;div&gt;域名嗅探&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;264&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;域名嗅探&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-49&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 380 360 L 380 393.63&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 380 398.88 L 376.5 391.88 L 380 393.63 L 383.5 391.88 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-42&quot;&gt;&lt;g&gt;&lt;rect x=&quot;320&quot; y=&quot;320&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 340px; margin-left: 321px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;安全网站&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;380&quot; y=&quot;344&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;安全网站&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-51&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 540 360 L 614.3 397.15&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 619 399.5 L 611.17 399.5 L 614.3 397.15 L 614.3 393.24 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-43&quot;&gt;&lt;g&gt;&lt;rect x=&quot;480&quot; y=&quot;320&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 340px; margin-left: 481px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;不安全网站&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;540&quot; y=&quot;344&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;不安全网站&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-53&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 700 360 L 625.7 397.15&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 621 399.5 L 625.7 393.24 L 625.7 397.15 L 628.83 399.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-44&quot;&gt;&lt;g&gt;&lt;rect x=&quot;640&quot; y=&quot;320&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 340px; margin-left: 641px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;未知网站&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;700&quot; y=&quot;344&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;未知网站&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-48&quot;&gt;&lt;g&gt;&lt;rect x=&quot;320&quot; y=&quot;400&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 420px; margin-left: 321px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;直接访问&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;380&quot; y=&quot;424&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;直接访问&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;kIc2mQei8pWa2ecX7WWh-50&quot;&gt;&lt;g&gt;&lt;rect x=&quot;560&quot; y=&quot;400&quot; width=&quot;120&quot; height=&quot;40&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 420px; margin-left: 561px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;代理访问&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;620&quot; y=&quot;424&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;代理访问&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;switch&gt;&lt;g requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&#x2F;&gt;&lt;a transform=&quot;translate(0,-5)&quot; xlink:href=&quot;https:&#x2F;&#x2F;www.drawio.com&#x2F;doc&#x2F;faq&#x2F;svg-export-text-problems&quot; target=&quot;_blank&quot;&gt;&lt;text text-anchor=&quot;middle&quot; font-size=&quot;10px&quot; x=&quot;50%&quot; y=&quot;100%&quot;&gt;Text is not SVG - cannot display&lt;&#x2F;text&gt;&lt;&#x2F;a&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;svg&gt;&lt;!----&gt;
  
&lt;&#x2F;figure&gt;
&lt;p&gt;实际上，假设域名列表足够准确，我们应该极少遇到未知域名指向安全 IP 的情况，因此，完全可以选择未知域名一律走 FakeIP，以获得最佳的性能。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;下一步？&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#下一步？&quot; aria-label=&quot;Anchor link for: 下一步？&quot;&gt;下一步？&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;现在的方案真的是完美的吗？代理软件还有什么问题呢？&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;ICMP 协议：目前，TUN 代理软件虽然运行于 L2&#x2F;L3，但是，实际上它并无法正确处理 ICMP 协议，也就是 ping 使用的协议。目前，对于 ICMP 协议，代理软件通常使用两种方式处理：不代理 ICMP 通讯或者直接立即返回假的 ICMP 结果。前者会导致 ping 需要代理的网站时无法 ping 通，而后者则会导致 ping 无法真实反应通讯延迟和丢包情况（ping 在亚毫秒内返回）。部分软件可能会依靠 ping 确定服务器的可用性或者选择最佳的服务器，这些软件在使用代理时无法正常工作。&lt;&#x2F;li&gt;
&lt;li&gt;FakeIP：尽管 FakeIP 可以几乎完美地解决代理的性能问题，但是，使用 FakeIP 会让透明代理变得没有那么“透明”。FakeIP 对需要代理的网站的 DNS 请求返回一个内网 IP 地址，这使得应用程序可以通过这一特征判断出当前可能正在使用代理软件（至少说明 DNS 服务出了什么问题）。当然，大部分软件都不会因此改变行为，但理论上软件可以由此检测代理的存在。当然，HTTP 代理根本就不是透明代理。使用 TUN 代理时即使不使用 FakeIP 也总是会存在一些应用程序可以获取的特征，比如在移动平台上，应用程序可以得知是否启用了 VPN，桌面端平台上，应用程序也可以检查是否存在 TUN 虚拟网卡。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;这些问题还有待代理软件的开发者进一步提出新的解决方案。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;参考&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#参考&quot; aria-label=&quot;Anchor link for: 参考&quot;&gt;参考&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cloudflare.com&#x2F;zh-cn&#x2F;learning&#x2F;ddos&#x2F;glossary&#x2F;open-systems-interconnection-model-osi&#x2F;&quot;&gt;什么是 OSI 模型？&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.skk.moe&#x2F;post&#x2F;i-have-my-unique-dns-setup&#x2F;&quot;&gt;我有特别的 DNS 配置和使用技巧&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lhy.life&#x2F;20231012-sing-box-tproxy&#x2F;&quot;&gt;sing-box tproxy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</description>
      </item>
      <item>
          <title>简单但强大的 Pratt Parsing【译】</title>
          <pubDate>Thu, 01 Aug 2024 00:00:00 +0000</pubDate>
          <author>Alex Kladov</author>
          <link>https://st1020.com/posts/simple-but-powerful-pratt-parsing/</link>
          <guid>https://st1020.com/posts/simple-but-powerful-pratt-parsing/</guid>
          <description xml:base="https://st1020.com/posts/simple-but-powerful-pratt-parsing/">&lt;p&gt;&lt;strong&gt;原文：&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2020&#x2F;04&#x2F;13&#x2F;simple-but-powerful-pratt-parsing.html&quot;&gt;https:&#x2F;&#x2F;matklad.github.io&#x2F;2020&#x2F;04&#x2F;13&#x2F;simple-but-powerful-pratt-parsing.html&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;欢迎阅读我关于 Pratt 解析的文章——语法分析的 monad 教程。关于 Pratt 解析文章数量如此之多，以至于存在一个&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.oilshell.org&#x2F;blog&#x2F;2017&#x2F;03&#x2F;31.html&quot;&gt;调查帖子&lt;&#x2F;a&gt; :)&lt;&#x2F;p&gt;
&lt;p&gt;这篇文章的目标是：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;提出所谓的左递归（left-recursion）问题被夸大了。&lt;&#x2F;li&gt;
&lt;li&gt;抱怨 BNF 不足以表示中缀表达式。&lt;&#x2F;li&gt;
&lt;li&gt;提供仅包含核心且不引入 DSL-y 抽象的 Pratt 解析算法的描述和实现。&lt;&#x2F;li&gt;
&lt;li&gt;希望这是最后一次让自己理解该算法。我曾经&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-analyzer&#x2F;rust-analyzer&#x2F;blob&#x2F;c388130f5ffbcbe7d3131213a24d12d02f769b87&#x2F;crates&#x2F;ra_parser&#x2F;src&#x2F;grammar&#x2F;expressions.rs#L280-L281&quot;&gt;实现过&lt;&#x2F;a&gt;一个生产级的 Pratt 解析器，但我不再理解该代码:-)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这篇文章假设你对解析技术有一定的了解，例如，本文没有解释什么是上下文无关语法（context free grammar）。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;介绍&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#介绍&quot; aria-label=&quot;Anchor link for: 介绍&quot;&gt;介绍&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;解析是编译器将 Token &lt;em&gt;序列&lt;&#x2F;em&gt;转换为&lt;em&gt;树&lt;&#x2F;em&gt;表示的过程：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            Add&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 Parser     &#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &amp;quot;1 + 2 * 3&amp;quot;    -------&amp;gt;   1  Mul&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                              &#x2F; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                             2   3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;完成这项任务的方法有很多，大致可以分为两类：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;使用 DSL 指定语言的抽象语法&lt;&#x2F;li&gt;
&lt;li&gt;手写解析器&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Pratt 解析是手写解析最常用的技术之一。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;BNF&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#BNF&quot; aria-label=&quot;Anchor link for: BNF&quot;&gt;BNF&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;语法分析理论的巅峰是发现了上下文无关语法符号（通常使用 BNF 具体语法）用于将线性结构解码为树：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Item ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    StructItem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | EnumItem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;StructItem ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;struct&amp;#39; Name &amp;#39;{&amp;#39; FieldList &amp;#39;}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;我记得我曾经很喜欢这个想法，尤其是它与自然语言句法结构的相似性。然而，一旦我们开始描述表达式，我的乐观很快就消失了。自然表达式语法确实让人们了解表达式是什么。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Expr ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Expr &amp;#39;+&amp;#39; Expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Expr &amp;#39;*&amp;#39; Expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | &amp;#39;(&amp;#39; Expr &amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | &amp;#39;number&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;虽然这个语法看起来很棒，但实际上它是模糊且不严密的，需要重写才能用于自动解析器生成。具体来说，我们需要指定运算符的优先级（precedence）和结合性（associativity）。确定的语法如下所示：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Expr ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Factor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Expr &amp;#39;+&amp;#39; Factor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Factor ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Atom&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Factor &amp;#39;*&amp;#39; Atom&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Atom ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;#39;number&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | &amp;#39;(&amp;#39; Expr &amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;对我来说，表达式的“形状”在这个新的表述中完全消失了。此外，我花了三四门正式的语言&lt;em&gt;课程&lt;&#x2F;em&gt;才能够自己可靠地创建这种语法。&lt;&#x2F;p&gt;
&lt;p&gt;这就是我喜欢 Pratt 解析的原因——它是递归下降解析（recursive descent parsing）算法的增强，它使用优先级和结合性这种自然的术语来解析表达式，而不是语法混淆技术。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;递归下降和左递归&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#递归下降和左递归&quot; aria-label=&quot;Anchor link for: 递归下降和左递归&quot;&gt;递归下降和左递归&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;手写解析器的最简单技术是递归下降法，它将语法建模为一组相互递归的函数。例如，上面的 item 语法片段如下所示：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; item&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Parser&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        STRUCT_KEYWORD =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; struct_item&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        ENUM_KEYWORD   =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; enum_item&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; struct_item&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Parser&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(STRUCT_KEYWORD);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;L_CURLY&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    field_list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;R_CURLY&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;传统上，教科书指出左递归语法是这种方法的致命弱点，并利用这一缺点来引出更先进的 LR 解析技术。有问题的语法示例如下所示：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Sum ::=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Sum &amp;#39;+&amp;#39; Int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;确实，如果我们简单地编写 &lt;code&gt;sum&lt;&#x2F;code&gt; 函数，它不会生效：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Parser&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; 尝试第一种情况&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(PLUS);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; 如果失败了，尝试其他情况&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;这时我们立即进入了死循序并且发生栈溢出&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;该问题的理论上解决方法包括重写语法以消除左递归。然而在实践中，对于手写的解析器，解决方案要简单得多——摆脱纯粹的&lt;em&gt;递归&lt;&#x2F;em&gt;范式并使用循环：&lt;&#x2F;p&gt;
&lt;h2 id=&quot;Pratt_解析的大体结构&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#Pratt_解析的大体结构&quot; aria-label=&quot;Anchor link for: Pratt_解析的大体结构&quot;&gt;Pratt 解析的大体结构&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;仅使用循环不足以解析中缀表达式。因此，Pratt 解析&lt;em&gt;同时&lt;&#x2F;em&gt;使用循环和递归：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; parse_expr&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        parse_expr&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;它不仅能让你的思维进入莫比乌斯环形状的仓鼠轮，还能处理结合性和优先级！&lt;&#x2F;p&gt;
&lt;h2 id=&quot;从优先级（Precedence）到绑定力（Binding_Power）&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#从优先级（Precedence）到绑定力（Binding_Power）&quot; aria-label=&quot;Anchor link for: 从优先级（Precedence）到绑定力（Binding_Power）&quot;&gt;从优先级（Precedence）到绑定力（Binding Power）&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;我必须承认：我对“高优先级”和“低优先级”感到困惑。在 &lt;code&gt;a + b * c&lt;&#x2F;code&gt; 中，加法的优先级较低，但它位于解析树的顶部......&lt;&#x2F;p&gt;
&lt;p&gt;因此，我发现绑定力的思考方式更加直观。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;expr:   A       +       B       *       C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;power:      3       3       5       5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;*&lt;&#x2F;code&gt; 绑定力更强，它能更有力地将 &lt;code&gt;B&lt;&#x2F;code&gt; 和 &lt;code&gt;C&lt;&#x2F;code&gt; 结合在一起，因此表达式被解析为 &lt;code&gt;A + (B * C)&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;那么结合性又是什么呢？在 &lt;code&gt;A + B + C&lt;&#x2F;code&gt; 中，所有运算符似乎都具有相同的绑定力，并且不清楚首先折叠哪个 &lt;code&gt;+&lt;&#x2F;code&gt; 。但如果我们让它稍微不对称的话，这也可以用绑定力来建模：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;expr:      A       +       B       +       C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;power:  0      3      3.1      3      3.1     0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;在这里，我们稍微增加了 &lt;code&gt;+&lt;&#x2F;code&gt; 右侧的绑定力，以便它更紧密地结合右操作数。我们还在两端添加了零，因为两侧没有要绑定的运算符。在这里，第一个（并且只有第一个）&lt;code&gt;+&lt;&#x2F;code&gt; 比相邻运算符的更紧密地结合其两个操作数，因此我们可以折叠它：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;译注：观察 &lt;code&gt;A&lt;&#x2F;code&gt; 两侧，3 &amp;gt; 0，其被第一个 &lt;code&gt;+&lt;&#x2F;code&gt; 吸引，观察 &lt;code&gt;B&lt;&#x2F;code&gt; 两侧，3.1 &amp;gt; 3，其也被第一个 &lt;code&gt;+&lt;&#x2F;code&gt; 吸引。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;expr:     (A + B)     +     C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;power:  0          3    3.1    0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;现在我们可以折叠第二个加号并得到 &lt;code&gt;(A + B) + C&lt;&#x2F;code&gt; 。或者，就语法树而言，第二个 &lt;code&gt;+&lt;&#x2F;code&gt; 确实比起左侧操作数更喜欢右侧操作数，因此它急于结合 C。当它这样做时，第一个 &lt;code&gt;+&lt;&#x2F;code&gt; 已经捕获了 &lt;code&gt;A&lt;&#x2F;code&gt; 和 &lt;code&gt;B&lt;&#x2F;code&gt;，因此没有争议。&lt;&#x2F;p&gt;
&lt;p&gt;Pratt 解析的作用是通过从左到右处理字符串来找到这些比邻居运算符更强大的“坏蛋”。我们即将开始编写一些代码，但让我们首先看一下另一个可以运行的示例。我们将使用函数组合运算符 &lt;code&gt;.&lt;&#x2F;code&gt;（点）作为具有高绑定力的&lt;em&gt;右&lt;&#x2F;em&gt;结合运算符。即， &lt;code&gt;f . g . h&lt;&#x2F;code&gt; 被解析为 &lt;code&gt;f . (g . h)&lt;&#x2F;code&gt;，或者，其绑定力如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  f     .    g     .    h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0   8.5    8   8.5    8   0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;最小的_Pratt_解析器&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#最小的_Pratt_解析器&quot; aria-label=&quot;Anchor link for: 最小的_Pratt_解析器&quot;&gt;最小的 Pratt 解析器&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;我们将要解析一种将&lt;em&gt;单字符&lt;&#x2F;em&gt;数字和变量作为基本原子，将标点符号作为操作符的表达式。让我们定义一个简单的词法解析器（tokenizer）：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Copy&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; PartialEq&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Eq&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Eof&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Token&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;| !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_ascii_whitespace&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                &amp;#39;0&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;9&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                &amp;#39;a&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;z&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;A&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Z&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reverse&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; tokens&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; next&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-variable z-language&quot;&gt;mut self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.tokens.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pop&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; peek&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-variable z-language&quot;&gt;mut self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.tokens.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;last&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;copied&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;为了确保我们得到正确的&lt;del&gt;优先级&lt;&#x2F;del&gt;绑定力，我们将把中缀表达式转换为黄金标准（无论出于何种原因，在波兰不太流行）明确记号—— S-表达式（S-expressions）：&lt;code&gt;1 + 2 * 3 == (+ 1 (* 2 3))&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;译注：S-表达式也叫做波兰表达式。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::fmt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Display&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Formatter&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;({}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                    write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot; {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;让我们从这里开始：带有原子和两个中缀二元运算符 &lt;code&gt;+&lt;&#x2F;code&gt; 和 &lt;code&gt;*&lt;&#x2F;code&gt; 的表达式：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    expr_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1 + 2 * 3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(+ 1 (* 2 3))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;所以，我们用来处理左递归的方法大体上就是——从解析第一个数字开始，然后循环，消费运算符，然后……？&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;请注意，我们已经可以解析这个简单的测试了！&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;我们想要使用这个绑定力的想法，所以让我们计算运算符的左绑定力和右绑定力。我们将使用 &lt;code&gt;u8&lt;&#x2F;code&gt; 来表示绑定力，因此，为了表示结合性，我们将增加 &lt;code&gt;1&lt;&#x2F;code&gt;。我们将为输入的末尾保留为 &lt;code&gt;0&lt;&#x2F;code&gt; 绑定力，因此运算符可以拥有的最低绑定力是 &lt;code&gt;1&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;译注：&lt;code&gt;+&lt;&#x2F;code&gt;、&lt;code&gt;-&lt;&#x2F;code&gt;、&lt;code&gt;*&lt;&#x2F;code&gt;、&lt;code&gt;&#x2F;&lt;&#x2F;code&gt; 都具有左结合性，因此其右侧的绑定力高于左侧，即 &lt;code&gt;r_bp = l_bp + 1&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;现在到了巧妙的部分，让我们引入递归。让我们考虑一下这个例子（具有以下绑定力）：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a   +   b   *   c   *   d   +   e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  1   2   3   4   3   4   1   2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;光标在第一个 &lt;code&gt;+&lt;&#x2F;code&gt; 号处，我们知道左边的 &lt;code&gt;bp&lt;&#x2F;code&gt; 是 &lt;code&gt;1&lt;&#x2F;code&gt;，右边的是 &lt;code&gt;2&lt;&#x2F;code&gt;。&lt;code&gt;lhs&lt;&#x2F;code&gt; 存储了 &lt;code&gt;a&lt;&#x2F;code&gt;。&lt;code&gt;+&lt;&#x2F;code&gt; 的后的下一个运算符是 &lt;code&gt;*&lt;&#x2F;code&gt;，所以我们不应该将 &lt;code&gt;b&lt;&#x2F;code&gt; 和 &lt;code&gt;a&lt;&#x2F;code&gt; 相加。问题是我们还没有看到下一个运算符，我们只通过了 &lt;code&gt;+&lt;&#x2F;code&gt; 号。那么我们可以添加一个 lookahead（译注：向前检视数个字符）吗？看起来不行——我们得通过所有的 &lt;code&gt;b&lt;&#x2F;code&gt;、&lt;code&gt;c&lt;&#x2F;code&gt; 和 &lt;code&gt;d&lt;&#x2F;code&gt; 才能找到下一个具有较低绑定力的运算符，这听起来似乎没有边界。但我们发现了一些东西！我们当前的右优先级是 &lt;code&gt;2&lt;&#x2F;code&gt;，为了能够折叠表达式，我们需要找到下一个具有较低优先级的运算符。所以让我们从 &lt;code&gt;b&lt;&#x2F;code&gt; 开始递归调用 &lt;code&gt;expr_bp&lt;&#x2F;code&gt;，但同时告诉它一旦 &lt;code&gt;bp&lt;&#x2F;code&gt; 低于 &lt;code&gt;2&lt;&#x2F;code&gt; 就停止。这需要在主函数中添加 &lt;code&gt;min_bp&lt;&#x2F;code&gt; 参数。&lt;&#x2F;p&gt;
&lt;p&gt;瞧，我们有了一个功能齐全的最小 Pratt 解析器：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    expr_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ❺&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➋&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ❸&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ❹&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1 + 2 * 3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(+ 1 (* 2 3))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;a + b * c * d + e&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(+ (+ a (* (* b c) d)) e)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;min_bp&lt;&#x2F;code&gt; 参数是关键的补充。 &lt;code&gt;expr_bp&lt;&#x2F;code&gt; 现在解析具有相对较高绑定力的表达式。一旦它发现比 &lt;code&gt;min_bp&lt;&#x2F;code&gt; 绑定力弱的运算符，它就会停止。&lt;&#x2F;li&gt;
&lt;li&gt;这是“停止”的点。&lt;&#x2F;li&gt;
&lt;li&gt;在这里我们越过运算符本身并进行递归调用。注意我们如何使用 &lt;code&gt;l_bp&lt;&#x2F;code&gt; 来检查 &lt;code&gt;min_bp&lt;&#x2F;code&gt;，以及将 &lt;code&gt;r_bp&lt;&#x2F;code&gt; 作为递归调用的新 &lt;code&gt;min_bp&lt;&#x2F;code&gt;。因此，你可以将 &lt;code&gt;min_bp&lt;&#x2F;code&gt; 看作是当前表达式左侧运算符的绑定力。&lt;&#x2F;li&gt;
&lt;li&gt;最后，在解析正确的右侧之后，我们组装新的当前表达式。&lt;&#x2F;li&gt;
&lt;li&gt;开始递归时，我们使用的绑定力为零。记住，在开始时左侧运算符的绑定力是最低的，即为零，因为那里实际上没有运算符。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;是的，这 40 行&lt;em&gt;就是&lt;&#x2F;em&gt; Pratt 解析算法。它们很巧妙，但是，如果你理解它们，其他一切都是简单的添加。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;花哨的东西&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#花哨的东西&quot; aria-label=&quot;Anchor link for: 花哨的东西&quot;&gt;花哨的东西&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;现在让我们添加各种奇怪的表达式来展示算法的强大功能和灵活性。首先，我们添加一个高优先级的右结合函数复合运算符：&lt;code&gt;.&lt;&#x2F;code&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;.&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;是的，只有一行！请注意运算符的左侧绑定得更加紧密，这为我们提供了所需的右关联性：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;f . g . h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(. f (. g h))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot; 1 + 2 + f . g . h * 3 * 4&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(+ (+ 1 2) (* (* (. f (. g h)) 3) 4))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;现在，让我们添加一元运算符 &lt;code&gt;-&lt;&#x2F;code&gt;，它的绑定比二元算术运算符更紧密，但不如组合紧密。这需要改变我们开始循环的方式，因为我们不再假设第一个标记是原子，并且还需要处理减号。但让类型来驱动我们吧。首先，我们从绑定力开始。由于这是一个一元运算符，它实际上只有右绑定力，所以，咳咳，让我们直接编写一下代码：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;.&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➋&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;在这里，我们返回一个空 &lt;code&gt;()&lt;&#x2F;code&gt;，以明确表示这是一个前缀运算符，而不是后缀运算符，因此只能绑定右侧的内容。&lt;&#x2F;li&gt;
&lt;li&gt;注意，因为我们想在 &lt;code&gt;.&lt;&#x2F;code&gt; 和 &lt;code&gt;*&lt;&#x2F;code&gt; 之间添加一元负号 &lt;code&gt;-&lt;&#x2F;code&gt;，所以我们需要将 &lt;code&gt;.&lt;&#x2F;code&gt; 的优先级提高两个等级。一般规则是我们使用奇数优先级作为基础，如果运算符是二元的，则通过一个单位来调整优先级。对于一元运算符负号 &lt;code&gt;-&lt;&#x2F;code&gt; 来说，这无关紧要，我们可以使用 &lt;code&gt;5&lt;&#x2F;code&gt; 或 &lt;code&gt;6&lt;&#x2F;code&gt;，但使用奇数优先级会更一致。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;将其插入 &lt;code&gt;expr_bp&lt;&#x2F;code&gt;，我们得到：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            todo!&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;现在，我们只有 &lt;code&gt;r_bp&lt;&#x2F;code&gt; 而没有 &lt;code&gt;l_bp&lt;&#x2F;code&gt;，所以让我们只复制主循环中一半的代码？记住，我们在递归调用中使用 &lt;code&gt;r_bp&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;--1 * 2&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(* (- (- 1)) 2)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;--f . g&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(- (- (. f g)))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;有趣的是，这种纯粹机械化、类型驱动的转换是有效的。当然，你也可以推理出它为什么有效。同样的论点也适用于：在我们处理了一个前缀运算符后，操作数由绑定得更加紧密的的运算符组成，而我们恰好有一个函数可以解析比指定优先级更加紧密的表达式。&lt;&#x2F;p&gt;
&lt;p&gt;好吧，越来越简单了。如果使用 &lt;code&gt;((), u8)&lt;&#x2F;code&gt; 对前缀运算符“正好奏效”，那么 &lt;code&gt;(u8, ())&lt;&#x2F;code&gt; 能处理后缀运算符吗？好，让我们添加 &lt;code&gt;!&lt;&#x2F;code&gt; 作为阶乘运算符。它应该比 &lt;code&gt;-&lt;&#x2F;code&gt; 绑定得更紧，因为 &lt;code&gt;-(92!)&lt;&#x2F;code&gt; 显然比 &lt;code&gt;(-92)!&lt;&#x2F;code&gt; 更有用。所以，熟悉的流程——新的优先级函数，调整 &lt;code&gt;.&lt;&#x2F;code&gt; 的优先级（这一点在 Pratt 解析器中确实很烦人），复制粘贴代码...&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, ()) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;等等，这里有些问题。在我们解析前缀表达式之后，我们可能会看到一个后缀或中缀运算符。但是我们在遇到未识别的运算符时会退出，这样是行不通的……所以，我们让 &lt;code&gt;postfix_binding_power&lt;&#x2F;code&gt; 返回一个 option，以便在运算符不是后缀的情况下处理：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, ())) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, ())&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;, ()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;.&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;-9!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(- (! 9))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;f . g !&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(! (. f g))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;很好，新旧测试都通过了。&lt;&#x2F;p&gt;
&lt;p&gt;现在，我们准备添加一种新的表达式：括号表达式。实际上，这并不难，我们本来可以从一开始就做到这一点，但在这里处理这个问题是有意义的，稍后你就会明白为什么。括号只是一个 primary 表达式，其处理方式与原子类似：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;(&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;不幸的是，以下测试失败：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;(((0)))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;panic 来自下面的循环——我们唯一的终止条件是到达 eof，而 &lt;code&gt;)&lt;&#x2F;code&gt; 显然不是 eof。修复这个问题的最简单方法是让 &lt;code&gt;infix_binding_power&lt;&#x2F;code&gt; 在遇到未识别的操作数时返回 &lt;code&gt;None&lt;&#x2F;code&gt;。这样，它将也变得类似于 &lt;code&gt;postfix_binding_power&lt;&#x2F;code&gt;！&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;(&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, ())) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, ())&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;, ()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;)&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;.&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;现在让我们添加数组索引运算符：&lt;code&gt;a[i]&lt;&#x2F;code&gt;。它是什么类型的运算符？周围类型？如果只是 &lt;code&gt;a[]&lt;&#x2F;code&gt;，它显然是后缀的。如果只是 &lt;code&gt;[i]&lt;&#x2F;code&gt;，它会像括号一样工作。关键在于：&lt;code&gt;i&lt;&#x2F;code&gt; 部分实际上并不参与整个绑定力游戏，因为它有明确的范围。因此，我们可以这样做：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;(&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, ())) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;[&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;]&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span&gt;            };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, ())&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;[&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;, ()),&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; ➊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;)&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;.&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;x[0][1]&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;([ ([ x 0) 1)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;注意，我们为 &lt;code&gt;!&lt;&#x2F;code&gt; 和 &lt;code&gt;[&lt;&#x2F;code&gt; 使用了相同的优先级。一般来说，为了算法的正确性，在做决策时，优先级永远不能相等。否则，我们可能会遇到类似之前的小调整中的情况，那时有两个同样合适的折叠候选项。然而，我们只比较右侧的 &lt;code&gt;bp&lt;&#x2F;code&gt; 和左侧的 &lt;code&gt;bp&lt;&#x2F;code&gt;！因此，对于两个后缀运算符，它们具有相同的优先级是可以的，因为它们都是右侧的。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;最后，所有运算符的最终 boos，可怕的三元运算符：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c ? e1 : e2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这是……“所有其他地方”类型运算符吗？好吧，让我们稍微改变一下三元运算符的语法：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c [ e1 ] e2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;让我们回忆一下，&lt;code&gt;a[i]&lt;&#x2F;code&gt; 被认为是一个后缀运算符 + 括号的组合……所以，&lt;code&gt;?&lt;&#x2F;code&gt; 和 &lt;code&gt;:&lt;&#x2F;code&gt; 实际上是一对奇特的括号！让我们这样处理它们吧！现在，优先级和结合性呢？在这种情况下，结合性到底是什么？&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a ? b : c ? d : e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;为了弄清楚这一点，我们只需要将括号部分变形：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a ?: c ?: e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这可以解析为&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(a ?: c) ?: e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;或者&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?: (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;哪一种更有用呢？对于这样的 &lt;code&gt;?&lt;&#x2F;code&gt; 链：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a ? b :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;c ? d :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;右结合的解读更有用。在优先级方面，三元运算符优先级较低。在 C 语言中，只有 &lt;code&gt;=&lt;&#x2F;code&gt; 和 &lt;code&gt;,&lt;&#x2F;code&gt; 的优先级更低。既然提到这里了，我们也添加上 C 语言风格的右结合 &lt;code&gt;=&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;这是我们最完整、最完美的简单 Pratt 解析器版本：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::{fmt,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;BufRead&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Display&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Formatter&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;({}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                    write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot; {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                write!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Copy&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; PartialEq&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Eq&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Eof&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Token&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;| !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_ascii_whitespace&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                &amp;#39;0&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;9&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;a&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;z&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;A&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Z&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        tokens&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reverse&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Lexer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; tokens&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; next&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-variable z-language&quot;&gt;mut self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.tokens.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pop&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; peek&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-variable z-language&quot;&gt;mut self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.tokens.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;last&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;copied&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    expr_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Atom&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;it&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;(&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Eof&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;            Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad token: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, ())) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;[&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;]&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;l_bp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;)) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l_bp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; min_bp&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            lhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;?&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Op&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;:&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr_bp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lexer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r_bp&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Cons&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lhs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            continue&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    lhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; prefix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; ((),&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;bad op: {:?}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; postfix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, ())&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;!&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;, ()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;[&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;, ()),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; infix_binding_power&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;op&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;)&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; op&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;=&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;?&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;+&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;-&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;*&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;#39;.&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;14&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 13&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tests&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1 + 2 * 3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(+ 1 (* 2 3))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;a + b * c * d + e&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(+ (+ a (* (* b c) d)) e)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;f . g . h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(. f (. g h))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot; 1 + 2 + f . g . h * 3 * 4&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;(+ (+ 1 2) (* (* (. f (. g h)) 3) 4))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;--1 * 2&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(* (- (- 1)) 2)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;--f . g&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(- (- (. f g)))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;-9!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(- (! 9))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;f . g !&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(! (. f g))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;(((0)))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;x[0][1]&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;([ ([ x 0) 1)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;a ? b :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;         c ? d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;         : e&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(? a b (? c d e))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;a = 0 ? b : c = d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;(= a (= (? 0 b c) d))&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;stdin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;().&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;line&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;{}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;代码也可以在&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;matklad&#x2F;minipratt&quot;&gt;这个仓库&lt;&#x2F;a&gt;中找到，Eof :-)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>使用 Markdown 写论文（二）</title>
          <pubDate>Thu, 11 Apr 2024 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/write-thesis-with-markdown-part2/</link>
          <guid>https://st1020.com/posts/write-thesis-with-markdown-part2/</guid>
          <description xml:base="https://st1020.com/posts/write-thesis-with-markdown-part2/">&lt;p&gt;这篇是&lt;a href=&quot;https:&#x2F;&#x2F;st1020.com&#x2F;posts&#x2F;write-thesis-with-markdown-part1&#x2F;&quot;&gt;上篇&lt;&#x2F;a&gt;的续集。&lt;&#x2F;p&gt;
&lt;p&gt;最近要交论文终稿了，学校的通知也说明了需要提交 PDF 格式的论文，那么看起来我没有不使用 Typst 的理由了。&lt;&#x2F;p&gt;
&lt;p&gt;所以，这次我打算把我的论文写作工作流切换到使用 Markdown + Pandoc + Typst。&lt;&#x2F;p&gt;
&lt;p&gt;首先，有一个问题是，我为什么仍然使用 Markdown 转换为 Typst 而非直接使用 Typst 呢？&lt;&#x2F;p&gt;
&lt;p&gt;理由主要有以下两点：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Markdown 的生态更加完善。Markdown 有大量配套工具，而 Typst 则尚且不完善。比如我常用的 Prettier 用于 formatter，markdown-lint 用于 linter。这些在 Typst 中都暂时不存在替代品。并且，虽然 Typst 可以做到实时预览 PDF，但是却无法做到定位当前编辑的位置，当我修改了 Typst 文件后，PDF 会回到文件开头，也无法做到跟随滚动。&lt;&#x2F;li&gt;
&lt;li&gt;Markdown 是一种很好的中间语言。Markdown 可以很方便的转化为任何一种标记语言，它就像是一种所有标记语言的交集，如果未来我希望把我的论文发布在网络上，或者转化为其它语言，Markdown 就可以很方便的做到。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;那么，开始我们的 Markdown to Typst 论文写作之旅吧。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;开始&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#开始&quot; aria-label=&quot;Anchor link for: 开始&quot;&gt;开始&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;首先，需要安装 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jgm&#x2F;pandoc&quot;&gt;Pandoc&lt;&#x2F;a&gt; 和 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typst&#x2F;typst&quot;&gt;Typst&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# For macOS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;brew&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install pandoc typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# For Arch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pacman&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pandoc typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# For deb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install pandoc typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;一图胜千言，下面是整个 Markdown to Typst 需要用到的文件和工作流：&lt;&#x2F;p&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;
&lt;!----&gt;

&lt;figure class=&quot;inline-svg&quot;&gt;
  &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!-- Do not edit this file with editors other than draw.io --&gt;
&lt;!DOCTYPE svg PUBLIC &quot;-&#x2F;&#x2F;W3C&#x2F;&#x2F;DTD SVG 1.1&#x2F;&#x2F;EN&quot; &quot;http:&#x2F;&#x2F;www.w3.org&#x2F;Graphics&#x2F;SVG&#x2F;1.1&#x2F;DTD&#x2F;svg11.dtd&quot;&gt;
&lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; style=&quot;background: transparent; background-color: transparent; color-scheme: light dark;&quot; xmlns:xlink=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xlink&quot; version=&quot;1.1&quot; width=&quot;771px&quot; height=&quot;291px&quot; viewBox=&quot;-0.5 -0.5 771 291&quot; content=&quot;&amp;lt;mxfile host=&amp;quot;Electron&amp;quot; agent=&amp;quot;Mozilla&#x2F;5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit&#x2F;537.36 (KHTML, like Gecko) draw.io&#x2F;28.0.4 Chrome&#x2F;138.0.7204.97 Electron&#x2F;37.2.1 Safari&#x2F;537.36&amp;quot; version=&amp;quot;28.0.4&amp;quot; scale=&amp;quot;1&amp;quot; border=&amp;quot;0&amp;quot;&amp;gt;&amp;#10;  &amp;lt;diagram id=&amp;quot;EIcbeMpGp6bTiObiR513&amp;quot; name=&amp;quot;第 1 页&amp;quot;&amp;gt;&amp;#10;    &amp;lt;mxGraphModel dx=&amp;quot;1042&amp;quot; dy=&amp;quot;659&amp;quot; grid=&amp;quot;1&amp;quot; gridSize=&amp;quot;10&amp;quot; guides=&amp;quot;1&amp;quot; tooltips=&amp;quot;1&amp;quot; connect=&amp;quot;1&amp;quot; arrows=&amp;quot;1&amp;quot; fold=&amp;quot;1&amp;quot; page=&amp;quot;1&amp;quot; pageScale=&amp;quot;1&amp;quot; pageWidth=&amp;quot;1169&amp;quot; pageHeight=&amp;quot;827&amp;quot; math=&amp;quot;0&amp;quot; shadow=&amp;quot;0&amp;quot;&amp;gt;&amp;#10;      &amp;lt;root&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;1&amp;quot; parent=&amp;quot;0&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-45&amp;quot; value=&amp;quot;&amp;quot; style=&amp;quot;rounded=0;whiteSpace=wrap;html=1;fillColor=none;dashed=1;strokeColor=default;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;70&amp;quot; y=&amp;quot;160&amp;quot; width=&amp;quot;220&amp;quot; height=&amp;quot;240&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-5&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-2&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-3&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-2&amp;quot; value=&amp;quot;thesis.md&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;200&amp;quot; y=&amp;quot;230&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-6&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-3&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-4&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-3&amp;quot; value=&amp;quot;Pandoc&amp;quot; style=&amp;quot;shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;320&amp;quot; y=&amp;quot;250&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;60&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-8&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-4&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-7&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-4&amp;quot; value=&amp;quot;thesis.typ&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;480&amp;quot; y=&amp;quot;230&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-10&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-7&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-9&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-7&amp;quot; value=&amp;quot;Typst&amp;quot; style=&amp;quot;shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;600&amp;quot; y=&amp;quot;250&amp;quot; width=&amp;quot;120&amp;quot; height=&amp;quot;60&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-9&amp;quot; value=&amp;quot;thesis.pdf&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;760&amp;quot; y=&amp;quot;230&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-14&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-11&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-3&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-11&amp;quot; value=&amp;quot;defaults.yaml&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;295&amp;quot; y=&amp;quot;350&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-15&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-12&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-3&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-12&amp;quot; value=&amp;quot;filter.lua&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;385&amp;quot; y=&amp;quot;350&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-33&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-20&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-2&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-20&amp;quot; value=&amp;quot;ref.bib&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;80&amp;quot; y=&amp;quot;290&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-24&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-22&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-7&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-22&amp;quot; value=&amp;quot;template.typ&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;620&amp;quot; y=&amp;quot;350&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-41&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-29&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-2&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-29&amp;quot; value=&amp;quot;images&amp;quot; style=&amp;quot;shape=card;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;80&amp;quot; y=&amp;quot;170&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-44&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-30&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-7&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-30&amp;quot; value=&amp;quot;assets&amp;quot; style=&amp;quot;shape=card;whiteSpace=wrap;html=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;710&amp;quot; y=&amp;quot;350&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-43&amp;quot; style=&amp;quot;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;&amp;quot; parent=&amp;quot;1&amp;quot; source=&amp;quot;vF7zuAULpLhDV7Q-WaRX-38&amp;quot; target=&amp;quot;vF7zuAULpLhDV7Q-WaRX-7&amp;quot; edge=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry relative=&amp;quot;1&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-38&amp;quot; value=&amp;quot;china-national-standard-gb-t-7714-2015-numeric.csl&amp;quot; style=&amp;quot;shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;530&amp;quot; y=&amp;quot;350&amp;quot; width=&amp;quot;80&amp;quot; height=&amp;quot;100&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;        &amp;lt;mxCell id=&amp;quot;vF7zuAULpLhDV7Q-WaRX-46&amp;quot; value=&amp;quot;Input&amp;quot; style=&amp;quot;text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;dashed=1;&amp;quot; parent=&amp;quot;1&amp;quot; vertex=&amp;quot;1&amp;quot;&amp;gt;&amp;#10;          &amp;lt;mxGeometry x=&amp;quot;150&amp;quot; y=&amp;quot;400&amp;quot; width=&amp;quot;60&amp;quot; height=&amp;quot;30&amp;quot; as=&amp;quot;geometry&amp;quot; &#x2F;&amp;gt;&amp;#10;        &amp;lt;&#x2F;mxCell&amp;gt;&amp;#10;      &amp;lt;&#x2F;root&amp;gt;&amp;#10;    &amp;lt;&#x2F;mxGraphModel&amp;gt;&amp;#10;  &amp;lt;&#x2F;diagram&amp;gt;&amp;#10;&amp;lt;&#x2F;mxfile&amp;gt;&amp;#10;&quot;&gt;&lt;defs&#x2F;&gt;&lt;g&gt;&lt;g data-cell-id=&quot;0&quot;&gt;&lt;g data-cell-id=&quot;1&quot;&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-45&quot;&gt;&lt;g&gt;&lt;rect x=&quot;0&quot; y=&quot;0&quot; width=&quot;220&quot; height=&quot;240&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-dasharray=&quot;3 3&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-5&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 210 120 L 243.63 120&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 248.88 120 L 241.88 123.5 L 243.63 120 L 241.88 116.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-2&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 130 70 L 180 70 L 210 100 L 210 170 L 130 170 L 130 70 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 180 70 L 180 100 L 210 100 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 180 70 L 180 100 L 210 100&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 120px; margin-left: 131px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;thesis.md&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;170&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;thesis.md&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-6&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 370 120 L 403.63 120&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 408.88 120 L 401.88 123.5 L 403.63 120 L 401.88 116.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-3&quot;&gt;&lt;g&gt;&lt;rect x=&quot;250&quot; y=&quot;90&quot; width=&quot;120&quot; height=&quot;60&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 262 90 L 262 150 M 358 90 L 358 150&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 94px; height: 1px; padding-top: 120px; margin-left: 263px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Pandoc&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;310&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Pandoc&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-8&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 490 120 L 523.63 120&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 528.88 120 L 521.88 123.5 L 523.63 120 L 521.88 116.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-4&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 410 70 L 460 70 L 490 100 L 490 170 L 410 170 L 410 70 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 460 70 L 460 100 L 490 100 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 460 70 L 460 100 L 490 100&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 120px; margin-left: 411px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;thesis.typ&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;450&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;thesis.typ&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-10&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 650 120 L 683.63 120&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 688.88 120 L 681.88 123.5 L 683.63 120 L 681.88 116.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-7&quot;&gt;&lt;g&gt;&lt;rect x=&quot;530&quot; y=&quot;90&quot; width=&quot;120&quot; height=&quot;60&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 542 90 L 542 150 M 638 90 L 638 150&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 94px; height: 1px; padding-top: 120px; margin-left: 543px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Typst&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;590&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Typst&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-9&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 690 70 L 740 70 L 770 100 L 770 170 L 690 170 L 690 70 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 740 70 L 740 100 L 770 100 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 740 70 L 740 100 L 770 100&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 120px; margin-left: 691px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;thesis.pdf&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;730&quot; y=&quot;124&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;thesis.pdf&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-14&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 265 190 L 265 170 L 310 170 L 310 156.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 310 151.12 L 313.5 158.12 L 310 156.37 L 306.5 158.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-11&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 225 190 L 275 190 L 305 220 L 305 290 L 225 290 L 225 190 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 275 190 L 275 220 L 305 220 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 275 190 L 275 220 L 305 220&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 240px; margin-left: 226px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;defaults.yaml&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;265&quot; y=&quot;244&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;defaults.yaml&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-15&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 355 190 L 355 170 L 310 170 L 310 156.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 310 151.12 L 313.5 158.12 L 310 156.37 L 306.5 158.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-12&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 315 190 L 365 190 L 395 220 L 395 290 L 315 290 L 315 190 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 365 190 L 365 220 L 395 220 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 365 190 L 365 220 L 395 220&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 240px; margin-left: 316px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;filter.lua&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;355&quot; y=&quot;244&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;filter.lua&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-33&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 90 180 L 110 180 L 110 120 L 123.63 120&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 128.88 120 L 121.88 123.5 L 123.63 120 L 121.88 116.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-20&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 10 130 L 60 130 L 90 160 L 90 230 L 10 230 L 10 130 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 60 130 L 60 160 L 90 160 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 60 130 L 60 160 L 90 160&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 180px; margin-left: 11px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;ref.bib&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;50&quot; y=&quot;184&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;ref.bib&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-24&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 590 190 L 590 156.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 590 151.12 L 593.5 158.12 L 590 156.37 L 586.5 158.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-22&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 550 190 L 600 190 L 630 220 L 630 290 L 550 290 L 550 190 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 600 190 L 600 220 L 630 220 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 600 190 L 600 220 L 630 220&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 240px; margin-left: 551px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;template.typ&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;590&quot; y=&quot;244&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;template.typ&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-41&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 90 60 L 110 60 L 110 120 L 123.63 120&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 128.88 120 L 121.88 123.5 L 123.63 120 L 121.88 116.5 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-29&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 40 10 L 90 10 L 90 110 L 10 110 L 10 40 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 60px; margin-left: 11px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;images&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;50&quot; y=&quot;64&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;images&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-44&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 680 190 L 680 170 L 590 170 L 590 156.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 590 151.12 L 593.5 158.12 L 590 156.37 L 586.5 158.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-30&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 670 190 L 720 190 L 720 290 L 640 290 L 640 220 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 240px; margin-left: 641px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;assets&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;680&quot; y=&quot;244&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;assets&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-43&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 500 190 L 500 170 L 590 170 L 590 156.37&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 590 151.12 L 593.5 158.12 L 590 156.37 L 586.5 158.12 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-38&quot;&gt;&lt;g&gt;&lt;path d=&quot;M 460 190 L 510 190 L 540 220 L 540 290 L 460 290 L 460 190 Z&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;path d=&quot;M 510 190 L 510 220 L 540 220 Z&quot; fill-opacity=&quot;0.05&quot; fill=&quot;#000000&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&#x2F;&gt;&lt;path d=&quot;M 510 190 L 510 220 L 540 220&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot; style=&quot;stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 240px; margin-left: 461px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;500&quot; y=&quot;244&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;china-nationa...&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;g data-cell-id=&quot;vF7zuAULpLhDV7Q-WaRX-46&quot;&gt;&lt;g&gt;&lt;rect x=&quot;80&quot; y=&quot;240&quot; width=&quot;60&quot; height=&quot;30&quot; fill=&quot;none&quot; stroke=&quot;none&quot; pointer-events=&quot;all&quot;&#x2F;&gt;&lt;&#x2F;g&gt;&lt;g&gt;&lt;g&gt;&lt;switch&gt;&lt;foreignObject style=&quot;overflow: visible; text-align: left;&quot; pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;SVG11&#x2F;feature#Extensibility&quot;&gt;&lt;div xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;1999&#x2F;xhtml&quot; style=&quot;display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 255px; margin-left: 81px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; font-size: 0; text-align: center; color: #000000; &quot;&gt;&lt;div style=&quot;display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; &quot;&gt;Input&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;&#x2F;foreignObject&gt;&lt;text x=&quot;110&quot; y=&quot;259&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;Helvetica&quot; font-size=&quot;12px&quot; text-anchor=&quot;middle&quot;&gt;Input&lt;&#x2F;text&gt;&lt;&#x2F;switch&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;g&gt;&lt;&#x2F;svg&gt;&lt;!----&gt;
  
&lt;&#x2F;figure&gt;
&lt;p&gt;文件树：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── assets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── logo.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── build.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── defaults.yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── filter.lua&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── images&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── image1.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── image2.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── ref.bib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── template.typ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── thesis.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── thesis.pdf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── thesis.typ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;输入&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#输入&quot; aria-label=&quot;Anchor link for: 输入&quot;&gt;输入&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;首先，整个工作流的输入的核心自然就是 thesis.md，Markdown 格式的论文：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 基于 Pandoc 和 Typst 的论文写作&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;link-citations&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;link-bibliography&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```thesis&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;title&amp;quot;: &amp;quot;基于 Pandoc 和 Typst 的论文写作&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;school&amp;quot;: &amp;quot;计算机学院&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;major&amp;quot;: &amp;quot;计算机科学与技术&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;class&amp;quot;: &amp;quot;xxx 班&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;author&amp;quot;: &amp;quot;张三&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;id&amp;quot;: &amp;quot;xxxxxx&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;mentor&amp;quot;: &amp;quot;李四&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;date&amp;quot;: &amp;quot;2024-04-11&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;::: preface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 摘要 {-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;本文简要介绍了如何使用 Pandoc 和 Typst 来撰写论文。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;**关键词：**&lt;&#x2F;span&gt;&lt;span&gt; 论文；Markdown；Pandoc；Typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## Abstract {-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;This article provides a brief introduction to writing papers using Pandoc and Typst.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;**Keywords:**&lt;&#x2F;span&gt;&lt;span&gt; Thesis; Markdown; Pandoc; Typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;::: mainmatter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 引言&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;这里是引言。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 一级标题&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;### 二级标题&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;#### 三级标题&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;这里是一个引用[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;@doe99&lt;&#x2F;span&gt;&lt;span&gt;]，以及一个同时多个引用[@doe99; @smith2000; @smith2004]。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;下面是一个表格：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 名称     | 拓展名 | MIME            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| -------- | ------ | --------------- |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Markdown | .md    | text&#x2F;markdown   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| PDF      | .pdf   | application&#x2F;pdf |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Table: 文件格式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;下面是一个图片：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;![&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;一个示例图片&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span&gt;images&#x2F;image1.png&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;下面是一个代码块：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```rust&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Hello World!&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 致谢 {-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;感谢 xxx 在本文写作过程中给予的帮助。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 参考文献 {-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;::: {#refs}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 附录 1 源代码 {-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;这里是附录。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上面基本上是就是普通的 Markdown 语法，但是使用了一些 Pandoc 拓展和自定义拓展。&lt;&#x2F;p&gt;
&lt;p&gt;首先是文件头的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#extension-yaml_metadata_block&quot;&gt;YAML 元数据块&lt;&#x2F;a&gt;，这里面使用 YAML 语法指定了论文的标题和一些 Pandoc 设置。&lt;&#x2F;p&gt;
&lt;p&gt;然后是文件开头的语言为 &lt;code&gt;thesis&lt;&#x2F;code&gt; 的代码块，这里面用 JSON 语法制定了论文的基本信息，它会被渲染为论文的封面中的信息。&lt;&#x2F;p&gt;
&lt;p&gt;然后是一个 class 为 &lt;code&gt;preface&lt;&#x2F;code&gt; 的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#extension-fenced_divs&quot;&gt;fenced Div&lt;&#x2F;a&gt; 块，这用于指示论文的前言开始了，下面可以放置论文的中英文摘要。&lt;&#x2F;p&gt;
&lt;p&gt;再之后是一个 class 为 &lt;code&gt;mainmatter&lt;&#x2F;code&gt; 的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#extension-fenced_divs&quot;&gt;fenced Div&lt;&#x2F;a&gt; 块，这用于指示论文的正文开始了。&lt;&#x2F;p&gt;
&lt;p&gt;参考文献的引用使用了&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#citation-syntax&quot;&gt;引文语法&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;表格下面的 &lt;code&gt;Table: 文件格式&lt;&#x2F;code&gt; 使用了&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#extension-table_captions&quot;&gt;表格说明&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;前面的摘要和最后的致谢、参考文献和附录标题使用了 &lt;code&gt;{-}&lt;&#x2F;code&gt; &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#extension-header_attributes&quot;&gt;标题属性&lt;&#x2F;a&gt;，用于不自动编号。&lt;&#x2F;p&gt;
&lt;p&gt;Id 为 &lt;code&gt;refs&lt;&#x2F;code&gt; 的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#extension-fenced_divs&quot;&gt;fenced Div&lt;&#x2F;a&gt; 块用于&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#placement-of-the-bibliography&quot;&gt;放置参考文献列表&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;除了 Markdown 文件，还需要 images 目录用于存储论文中用到的图片，和 ref.bib 文件用于存放参考文献，关于参考文献的管理，参考&lt;a href=&quot;https:&#x2F;&#x2F;st1020.com&#x2F;posts&#x2F;write-thesis-with-markdown-part1&#x2F;&quot;&gt;上篇&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;Pandoc&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#Pandoc&quot; aria-label=&quot;Anchor link for: Pandoc&quot;&gt;Pandoc&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;下一步就是要使用 Pandoc 将 Markdown 文件转化为 Typst 文件。&lt;&#x2F;p&gt;
&lt;p&gt;这一步，需要使用 defaults.yaml 和 filter.lua 文件。&lt;&#x2F;p&gt;
&lt;p&gt;defaults.yaml 文件用于指定 Pandoc 的默认选项，比如使用 &lt;code&gt;--citeproc&lt;&#x2F;code&gt; 选项启用 Pandoc 的引用功能，使用 &lt;code&gt;--filter&lt;&#x2F;code&gt; 选项指定 filter.lua 文件。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;filters&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; filter.lua&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;wrap&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; preserve&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;citeproc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;bibliography&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ref.bib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;csl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;filter.lua 是这部分的重点，它是一个 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;lua-filters.html&quot;&gt;Pandoc Lua Filter&lt;&#x2F;a&gt;，用于把上文中提到的一些自定义拓展语法正确渲染为 Typst。&lt;&#x2F;p&gt;
&lt;p&gt;主要工作就是要把上面的语言为 &lt;code&gt;thesis&lt;&#x2F;code&gt; 的代码块语法渲染为：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#import&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;template.typ&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#show&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;基于 Pandoc 和 Typst 的论文写作&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  school&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;计算机学院&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  major&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;计算机科学与技术&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  class&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;xxx班&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  author&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;张三&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;xxxxxx&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  mentor&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;李四&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  date&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2024&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 04&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 11&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;把 class 为 &lt;code&gt;preface&lt;&#x2F;code&gt;、&lt;code&gt;mainmatter&lt;&#x2F;code&gt; 和 id 为 &lt;code&gt;refs&lt;&#x2F;code&gt; 的 fenced Div 分别转换为 &lt;code&gt;#show: preface&lt;&#x2F;code&gt;、&lt;code&gt;#show: mainmatter&lt;&#x2F;code&gt; 和 &lt;code&gt;#bibliography(&quot;ref.bib&quot;, title: none, style: &quot;xxx.csl&quot;)&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;filter.lua 代码如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;local&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; function&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; has_element&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; element&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; ipairs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; element&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;local&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; doc_meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;local&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; THESIS_TEMPLATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; [[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;#import &amp;quot;template.typ&amp;quot;: *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;#show: thesis.with(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  title: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  school: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  major: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  class: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  author: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  id: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  mentor: &amp;quot;%s&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  date: (%s, %s, %s),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Pandoc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;doc&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            doc_meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; doc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;meta&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; doc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Div&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; has_element&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;classes&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;preface&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pandoc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;RawBlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;typst&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;#show: preface&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; has_element&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;classes&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;mainmatter&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pandoc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;RawBlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;typst&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;#show: mainmatter&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;identifier&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;refs&amp;quot; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pandoc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;RawBlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                    &amp;quot;typst&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;                    string.format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                        &amp;#39;#bibliography(&amp;quot;%s&amp;quot;, title: none, style: &amp;quot;%s&amp;quot;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        doc_meta&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;bibliography&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        doc_meta&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;csl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        CodeBlock&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; has_element&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;classes&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;thesis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                local&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; thesis&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pandoc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;json&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;decode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                local&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; year&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;month&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;day&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; string.match&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;date&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;(%d+)%-(%d+)%-(%d+)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; pandoc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;RawBlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                    &amp;quot;typst&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;                    string.format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        THESIS_TEMPLATE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;title&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;school&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;major&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;author&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;mentor&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                        year&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;month&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;day&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Header&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;使用 &lt;code&gt;pandoc thesis.md -o thesis.typ --defaults=defaults.yaml&lt;&#x2F;code&gt; 命令最终生成的 Typst 文件如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#import&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;template.typ&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#show&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; thesis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;基于 Pandoc 和 Typst 的论文写作&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  school&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;计算机学院&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  major&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;计算机科学与技术&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  class&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;xxx班&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  author&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;张三&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;xxxxxx&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  mentor&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;李四&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  date&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2024&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 04&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 11&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#show&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; preface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;= 摘要&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;本文简要介绍了如何使用 Pandoc 和 Typst 来撰写论文。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;#strong&lt;&#x2F;span&gt;&lt;span&gt;[关键词：] 论文；Markdown；Pandoc；Typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;= Abstract&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;This article provides a brief introduction to writing papers using Pandoc and Typst.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;#strong&lt;&#x2F;span&gt;&lt;span&gt;[Keywords:] Thesis; Markdown; Pandoc; Typst&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#show&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mainmatter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;= 引言&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;这里是引言。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;= 一级标题&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;== 二级标题&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;=== 三级标题&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;这里是一个引用@doe99，以及一个同时多个引用@doe99@smith2000@smith2004。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;下面是一个表格：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;#figure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  align&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;center&lt;&#x2F;span&gt;&lt;span&gt;)[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;#table&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    columns&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    align&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;,),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;header&lt;&#x2F;span&gt;&lt;span&gt;([名称], [拓展名], [MIME],),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    table&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;hline&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [Markdown], [.md], [text&#x2F;markdown],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [PDF], [.pdf], [application&#x2F;pdf],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; caption&lt;&#x2F;span&gt;&lt;span&gt;: [文件格式]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kind&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;下面是一个图片：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;#figure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;images&#x2F;image1.png&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  caption&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    一个示例图片&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;下面是一个代码块：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```rust&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fn main() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    println!(&amp;quot;Hello World!&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#heading(level: 1, numbering: none)[致谢]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;感谢 xxx 在本文写作过程中给予的帮助。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#heading(level: 1, numbering: none)[参考文献]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#bibliography(&amp;quot;ref.bib&amp;quot;, title: none, style: &amp;quot;china-national-standard-gb-t-7714-2015-numeric.csl&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#heading(level: 1, numbering: none)[附录 1 源代码]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;这里是附录。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;Typst&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#Typst&quot; aria-label=&quot;Anchor link for: Typst&quot;&gt;Typst&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;最后一步就是要将生成的 thesis.typ 文件渲染为 PDF。&lt;&#x2F;p&gt;
&lt;p&gt;这一步主要需要用到定义了符合 GB&#x2F;T 7714-2015 标准的引文格式的&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;citationstyles.org&#x2F;&quot;&gt;引文风格语言（Citation Style Language）&lt;&#x2F;a&gt;文件 china-national-standard-gb-t-7714-2015-numeric.csl、Typst 模板 template.typ 和 Typst 模板需要用到的资源文件夹 assets。&lt;&#x2F;p&gt;
&lt;p&gt;template.typ 文件中定义了论文的样式，由于不同的大学对样式的要求都略有不同，所以下面仅介绍一些通用的样式。&lt;&#x2F;p&gt;
&lt;p&gt;首先是论文开头的 &lt;code&gt;thesis&lt;&#x2F;code&gt; 函数，这部分设置了一些基础样式，并且在论文开头添加了封面、声明页、目录页等：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; heiti&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = (&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Times New Roman&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Heiti SC&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Heiti TC&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;SimHei&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; songti&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = (&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Times New Roman&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Songti SC&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Songti TC&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;SimSun&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 论文开头&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thesis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span&gt;: [],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  school&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  major&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  class&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  author&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  mentor&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  date&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1971&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; 设置页面布局&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  set&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; page&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;paper&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;a4&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; margin&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    top&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2.5cm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    bottom&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2.0cm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    left&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2.5cm&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    right&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2cm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; 设置字体&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  set&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;font&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; songti&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; size&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 12pt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;zh&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; region&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;cn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; 封面&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  cover&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; school&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; major&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; author&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mentor&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; date&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; 声明页&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  decl-page&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; 目录页&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  outline-page&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; 设置样式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;然后是 &lt;code&gt;preface&lt;&#x2F;code&gt; 和 &lt;code&gt;mainmatter&lt;&#x2F;code&gt; 函数，它们定义了前言和正文开始时需要进行的操作，包括重新设置页码计数器和设置页码的样式：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 前言样式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; preface&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  set&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; page&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;numbering&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;I&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; footer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; page-footer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;I&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  counter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;page&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;update&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 正文样式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;#let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; mainmatter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  set&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; page&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;numbering&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; footer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; page-footer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  counter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;page&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;update&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;是一些我写一些通用的样式：&lt;&#x2F;p&gt;
&lt;p&gt;设置标题的字号并且设置一级标题居中并自动换页：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 设置标题格式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set heading(numbering: &amp;quot;1.1&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let heading-font-size = (0pt, 18pt, 16pt, 14pt, 12pt)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show heading: it =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  set text(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    weight: &amp;quot;bold&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    font: heiti,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    size: heading-font-size.at(it.level, default: 12pt)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  set block(spacing: 1.5em)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show heading.where(level: 1): it =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  pagebreak()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  set align(center)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let text = it.body.at(&amp;quot;text&amp;quot;, default: &amp;quot;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (&amp;quot;摘要&amp;quot;, &amp;quot;Abstract&amp;quot;).contains(text) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    special-title(text)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;设置代码块的底色，并且当代码块的高度大于 500pt 时允许代码块折页：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 设置代块码样式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show raw.where(block: true): set par(justify: false, linebreaks: &amp;quot;simple&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show raw.where(block: true): it =&amp;gt; block(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  width: 100%,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  breakable: measure(it).height &amp;gt; 300pt,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fill: luma(240),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  inset: 10pt,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  radius: 4pt,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;设置表格显示为三线表，将表格的说明设置于表格的上方，并且允许表格的折页：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;typst&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;&#x2F; 设置表格样式&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show table.cell.where(y: 0): set text(style: &amp;quot;normal&amp;quot;, weight: &amp;quot;bold&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set table(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  stroke: (&lt;&#x2F;span&gt;&lt;span&gt;_, y) =&amp;gt; if y == 0 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (top: 1.5pt, bottom: 0.75pt)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;else if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;top&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0.75pt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bottom&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0pt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;bottom&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1.5pt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; top&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0pt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show figure.where(kind: table): set figure.caption(position: top)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;show figure.where(kind: table): set block(breakable: true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;最后，在做好相关的准备之后，只需要执行 &lt;code&gt;typst compile thesis.typ&lt;&#x2F;code&gt; 即可生成最终 PDF 格式的论文啦。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;参考&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#参考&quot; aria-label=&quot;Anchor link for: 参考&quot;&gt;参考&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;lua-filters.html&quot;&gt;Pandoc Lua Filters&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;typst.app&#x2F;docs&#x2F;&quot;&gt;Typst Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;werifu&#x2F;HUST-typst-template&quot;&gt;HUST-typst-template&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nju-lug&#x2F;modern-nju-thesis&quot;&gt;modern-nju-thesis&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>使用 Markdown 写论文（一）</title>
          <pubDate>Tue, 27 Feb 2024 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/write-thesis-with-markdown-part1/</link>
          <guid>https://st1020.com/posts/write-thesis-with-markdown-part1/</guid>
          <description xml:base="https://st1020.com/posts/write-thesis-with-markdown-part1/">&lt;p&gt;最近在写毕业论文，本文简单记录一下我的论文写作工作流。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;为什么不用_Microsoft_Word？&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#为什么不用_Microsoft_Word？&quot; aria-label=&quot;Anchor link for: 为什么不用_Microsoft_Word？&quot;&gt;为什么不用 Microsoft Word？&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;实际上，学校提供的论文模版就是 Word 格式的，我相信，绝大多数的同学也都是使用 Word 写论文的。那么我为什么不用 Microsoft Word 编写论文呢？&lt;&#x2F;p&gt;
&lt;p&gt;&lt;del&gt;用 Word 是不可能用 Word 的，这辈子都不可能用 Word 的。&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;p&gt;下面就让我简单列举一下 Word 的“罪状”：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;兼容性。docx 格式几乎完全是微软的私有格式（尽管 Office Open XML 格式已经标准化，但显然微软并没有打算严格遵守），没有任何兼容性保证，不要说用 LibreOffice &#x2F; WPS 之类的第三方软件，就算是不同平台&#x2F;不同版本的 Word 都无法保证渲染出来的一定是一样的。&lt;&#x2F;li&gt;
&lt;li&gt;呈现与内容分离。Word 是完全违反呈现与内容分离的原则的，在编写时必须时刻调整 Word 的样式，这无疑降低了写作的效率。&lt;&#x2F;li&gt;
&lt;li&gt;不是纯文本格式。docx 格式是一个二进制格式，准确来说是一堆 XML 文件的 ZIP 压缩包，导致很难进行版本控制和自动化处理。&lt;&#x2F;li&gt;
&lt;li&gt;对文献引用的支持很糟糕。Word 并不是一个专为论文写作设计的应用，因此，它并没有内建任何对文献引用的支持，尽管 Zotero 等工具可以增强其功能，但是仍然不够好用。&lt;&#x2F;li&gt;
&lt;li&gt;对公式的支持不够好。尽管我的论文中并没有用到很多公式，但是，显然 Word 并没有对公式排版的一流支持，这对于很多理工科论文是致命的。&lt;&#x2F;li&gt;
&lt;li&gt;Word 是一个闭源商业软件。尽管我并没有严重的开源软件洁癖，但是，如果有其他选择的话，我仍然希望我的工作流中尽可能使用开源软件。更不要说 Word 对比其他开源软件完全没有优势。&lt;&#x2F;li&gt;
&lt;li&gt;跨平台支持。Microsoft Word 仅对 Windows 平台提供了一流的支持，它的 Mac 版非常难用且有着各种功能的缺失，而 Linux 则完全没有任何支持。&lt;&#x2F;li&gt;
&lt;li&gt;Word 真的非常难用。除了上面这些问题之外，最重要的是：Word 真的非常难用！它的各种操作就是非常不符合逻辑且难以预测，当我复制一段文本再粘贴时，我完全无法预测它会展示成什么样子。样式调整页实在是太复杂了，并且手动成分太高，尽管有样式系统，很多时候仍然需要手动单独调整样式。或许是我了解的还不够深入，但是我真的觉得 Word 的设计很糟糕。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;为什么不用_LaTeX？&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#为什么不用_LaTeX？&quot; aria-label=&quot;Anchor link for: 为什么不用_LaTeX？&quot;&gt;为什么不用 LaTeX？&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;LaTeX 兼容性好、稳定、呈现与内容分离、是纯文本格式、具有一流的引用和公式支持、开源、跨平台、非常强大，并且是论文排版届的事实标准，那么我为什么不用 LaTeX 呢？&lt;&#x2F;p&gt;
&lt;p&gt;因为 LaTex 仍然有几个众所周知的缺点：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;语法老旧。LaTeX 作为诞生于上世纪 80 年代的古老语言，其语法对比现代标记语言实际上显得有些过于啰嗦和老旧。&lt;&#x2F;li&gt;
&lt;li&gt;安装包巨大。LaTeX 的完整安装包巨大，常常达到数个 GB，即使是仅包含核心组件的版本，下载完必要的插件后，也需要数百 MB。&lt;&#x2F;li&gt;
&lt;li&gt;中文支持一般。LaTeX 自身对中文的支持并不好，需要通过插件支持中文。&lt;&#x2F;li&gt;
&lt;li&gt;编译速度较慢。LaTex 编译生成 PDF 的速度很慢，常常需要数秒到数十秒的时间进行编译，难以做到实时预览。&lt;&#x2F;li&gt;
&lt;li&gt;只能生成 PDF 文件。这在通常情况下不是一个问题，但是在国内，仍然有许多场合只接受 docx 文档。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;为什么不用_Typst？&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#为什么不用_Typst？&quot; aria-label=&quot;Anchor link for: 为什么不用_Typst？&quot;&gt;为什么不用 Typst？&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Typst 作为最新的 LaTeX 替代者，解决了 LaTeX 的大部分缺点，它使用 Rust 编写，具有非常现代的好用的语法，仅需要一个二进制文件就能可以执行，原生支持中文，编译很快。我也使用过 Typst 编写文档，非常好用。唯一的一个问题就是，和 LaTex 一样，只能生成 PDF 文件。我无法确定我们学校是否允许提交 PDF 文件，为了避免不必要的麻烦，我还是决定使用 Markdown，并且 Markdown 也可以很方便地转换为 Typst 文档，如果需要，我也可以直接生成一份 Typst 文档。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;为什么使用_Markdown？&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#为什么使用_Markdown？&quot; aria-label=&quot;Anchor link for: 为什么使用_Markdown？&quot;&gt;为什么使用 Markdown？&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Markdown 是一个非常简单的标记语言，它非常简洁，易于阅读，易于编写。&lt;&#x2F;p&gt;
&lt;p&gt;Markdown 完全没有包含样式，完全做到了呈现与内容分离，编写时可以完全沉浸在内容中，而不会被其他东西干扰。&lt;&#x2F;p&gt;
&lt;p&gt;更重要的是，因为它足够简单，所以可以很方便地作为中间语言被转换为其他格式，借助 Pandoc，它可以轻松转换为包含 docx、LaTeX、Typst 在内的多种格式。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;准备&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#准备&quot; aria-label=&quot;Anchor link for: 准备&quot;&gt;准备&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;为了使用 Markdown 写论文，我的工作流如下：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;code.visualstudio.com&#x2F;&quot;&gt;VS Code&lt;&#x2F;a&gt; - 编辑器&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;Pandoc&lt;&#x2F;a&gt; - Markdown to docx&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.zotero.org&#x2F;&quot;&gt;Zotero&lt;&#x2F;a&gt; - 文献管理&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.drawio.com&#x2F;&quot;&gt;draw.io&lt;&#x2F;a&gt; - 插图绘制&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;使用_Pandoc&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#使用_Pandoc&quot; aria-label=&quot;Anchor link for: 使用_Pandoc&quot;&gt;使用 Pandoc&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Pandoc 自称为标记格式转换的瑞士军刀，它可以做到几乎所有文档格式之间的转换，当然，也支持把 Markdown 转换为 docx。&lt;&#x2F;p&gt;
&lt;p&gt;使用 Pandoc 非常简单：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pandoc&lt;&#x2F;span&gt;&lt;span&gt; [INPUT] -o [OUTPUT]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;例如：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pandoc&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; thesis.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; thesis.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;文献管理和引用&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#文献管理和引用&quot; aria-label=&quot;Anchor link for: 文献管理和引用&quot;&gt;文献管理和引用&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;如果需要手动写文献引用列表，那也太不优雅了，如果修改调换了引用的位置或者添加了新的引用，还需要手动更新引用文献列表和所有引用的编号。&lt;&#x2F;p&gt;
&lt;p&gt;作为一个程序员，任何能够让计算机自动完成的事情就要让计算机自动去完成。&lt;&#x2F;p&gt;
&lt;p&gt;为了自动进行文献引用，需要两个文件：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ref.bib - 文献引用列表&lt;&#x2F;li&gt;
&lt;li&gt;china-national-standard-gb-t-7714-2015-numeric.csl - 文献引用样式&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;china-national-standard-gb-t-7714-2015-numeric.csl 是一个 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;citationstyles.org&#x2F;&quot;&gt;引文风格语言（Citation Style Language）&lt;&#x2F;a&gt;文件，定义了符合 GB&#x2F;T 7714-2015 标准的引文格式，可以从 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.zotero.org&#x2F;styles&quot;&gt;Zotero Style Repository&lt;&#x2F;a&gt; 下载。&lt;&#x2F;p&gt;
&lt;p&gt;ref.bib 是 BibLaTeX 格式的文献引用列表，格式如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;bibtex&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@article&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;kingma2014adam&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span&gt;={Adam: A method for stochastic optimization},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  author&lt;&#x2F;span&gt;&lt;span&gt;={Kingma, Diederik P and Ba, Jimmy},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  journal&lt;&#x2F;span&gt;&lt;span&gt;={arXiv preprint arXiv:1412.6980},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  year&lt;&#x2F;span&gt;&lt;span&gt;={2014}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@article&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;vaswani2017attention&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span&gt;={Attention is all you need},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  author&lt;&#x2F;span&gt;&lt;span&gt;={Vaswani, Ashish and Shazeer, Noam and Parmar, Niki and Uszkoreit, Jakob and Jones, Llion and Gomez, Aidan N and Kaiser, {\L}ukasz and Polosukhin, Illia},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  journal&lt;&#x2F;span&gt;&lt;span&gt;={Advances in neural information processing systems},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  volume&lt;&#x2F;span&gt;&lt;span&gt;={30},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  year&lt;&#x2F;span&gt;&lt;span&gt;={2017}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;其中的 &lt;code&gt;kingma2014adam&lt;&#x2F;code&gt; 和 &lt;code&gt;vaswani2017attention&lt;&#x2F;code&gt; 被称为 citekey，可以 citekey 来引用论文。&lt;&#x2F;p&gt;
&lt;p&gt;通常的论文网站都提供了导出 BibLaTeX 的功能，可以手动复制这些导出的 BibLaTeX 到 ref.bib 文件中。&lt;&#x2F;p&gt;
&lt;p&gt;但是手动复制 BibLaTeX 引用列表还是不够方便的。所以我使用了 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.zotero.org&#x2F;&quot;&gt;Zotero&lt;&#x2F;a&gt; 来管理文献引用，它是目前最流行的开源文献管理软件之一，支持自动收集参考文献，只需要在浏览器中安装 Zotero 插件，当浏览论文相关的网站时，它会自动识别当前的论文信息，点一下就可以添加到文献列表中。&lt;&#x2F;p&gt;
&lt;p&gt;可以使用 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;retorquere&#x2F;zotero-better-bibtex&quot;&gt;Better BibTeX for Zotero&lt;&#x2F;a&gt; 插件来将 Zotero 文献库导出为 BibTeX 格式。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;st1020.com&#x2F;posts&#x2F;write-thesis-with-markdown-part1&#x2F;better_biblatex_for_zotero.png&quot; alt=&quot;Better BibTeX for Zotero&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;原生的 Markdown 不支持文献引用，但是 Pandoc 提供了一个拓展语法 &lt;code&gt;[@citekey]&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Blah blah [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;@doe99&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Blah blah [@doe99; @smith2000; @smith2004].&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;具体可以参考 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#citation-syntax&quot;&gt;Pandoc 文档&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;如果需要 Cite While You Write 的话，可以使用 VSCode 插件 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;marketplace.visualstudio.com&#x2F;items?itemName=notZaki.pandocciter&quot;&gt;Pandoc Citer&lt;&#x2F;a&gt; 或者 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;marketplace.visualstudio.com&#x2F;items?itemName=mblode.zotero&quot;&gt;Citation Picker for Zotero&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;除此之外，如果需要对图表、公式或者表格的交叉引用的话，可以使用 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lierdakil&#x2F;pandoc-crossref&quot;&gt;pandoc-crossref&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;将_Markdown_转换为_docx&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#将_Markdown_转换为_docx&quot; aria-label=&quot;Anchor link for: 将_Markdown_转换为_docx&quot;&gt;将 Markdown 转换为 docx&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;做好了上述准备后，是时候开始用 Markdown 编写论文了。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 使用 Markdown 编写论文&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# lang: zh-CN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;link-citations&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;link-bibliography&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;::: {custom-style=&amp;quot;Title&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| 摘要&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;本文简要介绍了如何使用 Markdown 编写论文。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;**关键词：**&lt;&#x2F;span&gt;&lt;span&gt; Markdown；Pandoc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;::: {custom-style=&amp;quot;Title&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Abstract&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;This article provides a brief introduction to how to write a paper using Markdown.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-bold&quot;&gt;**Keywords:**&lt;&#x2F;span&gt;&lt;span&gt; Markdown; Pandoc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 引言&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&amp;lt;!-- 这里是论文的内容 --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 参考文献&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;::: {#refs}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-markup z-heading&quot;&gt;## 附录&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;&amp;lt;!-- 这里是论文的附录 --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上面的摘要标题使用了 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#output&quot;&gt;custom-style&lt;&#x2F;a&gt; 而非直接使用 &lt;code&gt;##&lt;&#x2F;code&gt; 标题是为了防止被自动编号。使用 &lt;code&gt;{.unnumbered}&lt;&#x2F;code&gt; 尽管可以实现标题不会被编号，但是下一个标题的编号仍然会算上这个标题继续编号，所以使用了 &lt;code&gt;custom-style&lt;&#x2F;code&gt; 直接指定 Word 样式。&lt;&#x2F;p&gt;
&lt;p&gt;上面的 Markdown 示例里，最大的标题等级是从二级标题开始的，而在生成 Word 时我希望全部减少一个标题等级，从一级标题开始。之所以不直接从一级标题开始，是因为一个 Markdown 文档有多个一级标题总感觉有点奇怪，也会让 markdown-lint 警告。我使用了一个 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;lua-filters.html&quot;&gt;Pandoc Lua Filter&lt;&#x2F;a&gt; 来实现：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Header&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;el&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; el&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pandoc 自动生成的 docx 文件显然无法直接用于论文，Pandoc 支持通过 reference.docx 自定义生成的 docx 文件的样式。&lt;&#x2F;p&gt;
&lt;p&gt;首先生成默认的 reference.docx 文件：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pandoc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reference.docx&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --print-default-data-file&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reference.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;然后使用 Word 编辑里面的样式，然后使用 &lt;code&gt;--reference-doc=reference.docx&lt;&#x2F;code&gt; 参数生成 docx 文件即可。&lt;&#x2F;p&gt;
&lt;p&gt;我使用的 reference.docx 模版是基于 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Achuan-2&#x2F;pandoc_word_template&quot;&gt;Achuan-2&#x2F;pandoc_word_template&lt;&#x2F;a&gt; 进行修改得到的。（这里再次吐槽 Word，仅仅是修改模板都实在是太麻烦了！）&lt;&#x2F;p&gt;
&lt;p&gt;于是最终将 Markdown 转换为 docx 的命令如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pandoc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--toc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--number-sections&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--citeproc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--csl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--bibliography&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ref.bib&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--reference-doc=reference.docx&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--lua-filter=filter.lua&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thesis.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; thesis.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上面的参数的含义如下：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--toc&lt;&#x2F;code&gt;：生成目录&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--number-sections&lt;&#x2F;code&gt;：启用标题自动编号（如果使用的模版自带了标题编号，则不加这个参数）&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--citeproc&lt;&#x2F;code&gt;：启用文献引用处理&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--csl china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;code&gt;：指定引文格式&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--bibliography ref.bib&lt;&#x2F;code&gt;：指定文献引用文件&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--reference-doc=reference.docx&lt;&#x2F;code&gt;：指定 docx 模板文件&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--lua-filter=filter.lua&lt;&#x2F;code&gt; 设置 Lua Filter&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;上面的参数有点多，为了方便使用，我创建了一个 &lt;code&gt;defaults.yaml&lt;&#x2F;code&gt; 用于代替这些参数：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;filters&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; filter.lua&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;toc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;number-sections&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;reference-doc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reference.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;citeproc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;bibliography&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ref.bib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;csl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;于是最终我的论文用到了这些文件：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── china-national-standard-gb-t-7714-2015-numeric.csl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── defaults.yaml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── filter.lua&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── images&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── xxx.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── ref.bib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── reference.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── thesis.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── thesis.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;生成 docx 的命令如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pandoc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --defaults=defaults.yaml&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; thesis.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; thesis.docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;参考资料&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#参考资料&quot; aria-label=&quot;Anchor link for: 参考资料&quot;&gt;参考资料&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;MANUAL.html#custom-styles&quot;&gt;Pandoc User’s Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sspai.com&#x2F;post&#x2F;64842&quot;&gt;Markdown 写作，Pandoc 转换：我的纯文本学术写作流程&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sspai.com&#x2F;post&#x2F;57082&quot;&gt;如何用 Markdown 写论文？&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Rust 中生命周期的子类型化和型变</title>
          <pubDate>Wed, 10 Jan 2024 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/rust-subtyping-and-variance-lifetime/</link>
          <guid>https://st1020.com/posts/rust-subtyping-and-variance-lifetime/</guid>
          <description xml:base="https://st1020.com/posts/rust-subtyping-and-variance-lifetime/">&lt;p&gt;众所周知，Rust 使用借用检查代替垃圾收集来进行内存管理。而为了实现借用检查，就需要为变量引入生命周期，在大多数情况下，Rust 编译器会自动决定变量的生命周期，而无需而外指定，有些情况则不然。&lt;&#x2F;p&gt;
&lt;p&gt;引用 Rust 官方文档中提供的例子：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                &#x2F;&#x2F; ---------+-- &amp;#39;a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;                          &#x2F;&#x2F;          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                     &#x2F;&#x2F;          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;        &#x2F;&#x2F; -+-- &amp;#39;b  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;           &#x2F;&#x2F;  |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                     &#x2F;&#x2F; -+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;                          &#x2F;&#x2F;          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;r: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F;          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                         &#x2F;&#x2F; ---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;            &#x2F;&#x2F; ----------+-- &amp;#39;b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;                          &#x2F;&#x2F;           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;           &#x2F;&#x2F; --+-- &amp;#39;a  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;                          &#x2F;&#x2F;   |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;r: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; r&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F;   |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;                          &#x2F;&#x2F; --+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;                         &#x2F;&#x2F; ----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust 正是像上面所示的那样利用变量生命周期避免了悬垂引用。&lt;&#x2F;p&gt;
&lt;p&gt;但是，考虑下面的函数：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt; (&amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a str&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;static str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; t&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;{} {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; println!(&amp;quot;{} {}&amp;quot;, c, d);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;t&lt;&#x2F;code&gt; 函数要求接受两个生命周期为 &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; 的引用，而显然，下面的传入的 &lt;code&gt;a&lt;&#x2F;code&gt; 的生命周期是 &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; 而 &lt;code&gt;b&lt;&#x2F;code&gt; 的生命周期则短于 &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;，两个生命周期并不一致，但程序仍然可以编译运行。除此之外，如果反注释掉最后一行，会发现编译器报错了，这表明借用检查正确生效了，编译器将 &lt;code&gt;c&lt;&#x2F;code&gt; 和 &lt;code&gt;d&lt;&#x2F;code&gt; 的生命周期推断为和较短的 &lt;code&gt;b&lt;&#x2F;code&gt; 相同。&lt;&#x2F;p&gt;
&lt;p&gt;这里的重点在于，为什么明明 &lt;code&gt;t&lt;&#x2F;code&gt; 函数要求接受两个生命周期为 &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; 的引用，但我们传入两个生命周期不同的引用也能通过检查呢？&lt;&#x2F;p&gt;
&lt;p&gt;暂且保留这个疑问，先来介绍一下子类型。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;子类型&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#子类型&quot; aria-label=&quot;Anchor link for: 子类型&quot;&gt;子类型&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在面向对象编程中，子类型是一个基础概念。&lt;&#x2F;p&gt;
&lt;p&gt;比如我们有一个 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 类，它有 &lt;code&gt;Apple&lt;&#x2F;code&gt; 这个子类，那么 &lt;code&gt;Apple&lt;&#x2F;code&gt; 就是 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 的子类型。&lt;&#x2F;p&gt;
&lt;p&gt;让我们更加深入一些，为什么 &lt;code&gt;Apple&lt;&#x2F;code&gt; 是 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 的子类型呢？或者说，子类型到底表示两个类型之间怎样的关系？&lt;&#x2F;p&gt;
&lt;p&gt;用逻辑学的语言来说的话，就是“子类型相比其父类型内涵增加了，而外延收缩了”。&lt;&#x2F;p&gt;
&lt;p&gt;通俗的解释就是说，子类型所包含的特质属性增加了，而涵盖的具体事物范围减少了。对应上面的例子，包含的特质属性增加了是指：苹果这个概念相对于水果这个概念，它不仅包含了水果的全部属性，还包含了苹果的独特属性，比如特定的味道、特定的 DNA 片段等。涵盖的具体事物范围减少了是指：在全部能被称为水果个体中，能被称为苹果的只是一部分。&lt;&#x2F;p&gt;
&lt;p&gt;下面让我们将 &lt;code&gt;Apple&lt;&#x2F;code&gt; 是 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 的子类型记为：&lt;code&gt;Apple &amp;lt;: Fruit&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;在编程中，当需要一个 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 类型时，我们永远可以提供一个 &lt;code&gt;Apple&lt;&#x2F;code&gt; 类型……吗？&lt;&#x2F;p&gt;
&lt;h2 id=&quot;型变&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#型变&quot; aria-label=&quot;Anchor link for: 型变&quot;&gt;型变&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;还是从一个例子开始：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Fruit&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Apple&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Fruit&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Banana&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Fruit&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-primitive z-java&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; addApple&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-java&quot;&gt;List&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;lt;Fruit&amp;gt; fruits) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    fruits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Apple&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-primitive z-java&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-java&quot;&gt;    List&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-generic z-java&quot;&gt;Banana&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bananas&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-java&quot;&gt; ArrayList&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    addApple&lt;&#x2F;span&gt;&lt;span&gt;(bananas);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上面的例子，&lt;code&gt;addApple&lt;&#x2F;code&gt; 函数的参数是一个 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 的列表，因此它当然可以向里面放一个苹果。下面的 &lt;code&gt;test&lt;&#x2F;code&gt; 函数调用了 &lt;code&gt;addApple&lt;&#x2F;code&gt;，因为 &lt;code&gt;addApple&lt;&#x2F;code&gt; 需要一个水果的列表，那我就提供一个香蕉的列表吧！Oops，在 &lt;code&gt;addApple&lt;&#x2F;code&gt; 之后，它就不再是一个香蕉的列表了，我们的类型系统彻底失效了。不过放心，上面的代码当然是不正确的，它是无法通过类型检查的，这里就要引出协变、逆变、不变的概念。&lt;&#x2F;p&gt;
&lt;p&gt;在此之前，类似 &lt;code&gt;List&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 这样的结构，我们一般称之为泛型，或者，我们也可以更加通用地将其称为“类型构造器”，你可以将它理解为一个“关于类型的函数”，它接受一个类型 &lt;code&gt;T&lt;&#x2F;code&gt;，返回一个新的类型。换句话说，这里的 &lt;code&gt;List&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 不是一个真正的类型，而是一个未完成的类型，只有填入了具体类型 &lt;code&gt;T&lt;&#x2F;code&gt; 之后，才是一个类型，比如 &lt;code&gt;List&amp;lt;Apple&amp;gt;&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;现在，我们讨论一下已知 &lt;code&gt;T &amp;lt;: U&lt;&#x2F;code&gt; 对于类型构造器 &lt;code&gt;I&lt;&#x2F;code&gt; 来说 &lt;code&gt;I&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 和 &lt;code&gt;I&amp;lt;U&amp;gt;&lt;&#x2F;code&gt; 是什么关系？&lt;&#x2F;p&gt;
&lt;p&gt;还是让我们用 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 和 &lt;code&gt;Apple&lt;&#x2F;code&gt; 举例吧。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;协变（covariance）：&lt;code&gt;I&amp;lt;Apple&amp;gt; &amp;lt;: I&amp;lt;Fruit&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;逆变（contravariance）：&lt;code&gt;I&amp;lt;Fruit&amp;gt; &amp;lt;: I&amp;lt;Apple&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;不变（invariance）：&lt;code&gt;I&amp;lt;Fruit&amp;gt;&lt;&#x2F;code&gt; 和 &lt;code&gt;I&amp;lt;Apple&amp;gt;&lt;&#x2F;code&gt; 没有关系&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;那么，&lt;code&gt;I&lt;&#x2F;code&gt; 在什么情况下会是协变、逆变和不变呢？&lt;&#x2F;p&gt;
&lt;p&gt;首先，对于最简单的情况，例如我们要做水果沙拉，因此我们需要随便一些水果 &lt;code&gt;List&amp;lt;Fruit&amp;gt;&lt;&#x2F;code&gt;，这时无论提供的都是苹果 &lt;code&gt;List&amp;lt;Apple&amp;gt;&lt;&#x2F;code&gt; 还是都是香蕉 &lt;code&gt;List&amp;lt;Banana&amp;gt;&lt;&#x2F;code&gt;，又或者混合水果 &lt;code&gt;List&amp;lt;Fruit&amp;gt;&lt;&#x2F;code&gt; 都可以。因此，它是协变的。&lt;&#x2F;p&gt;
&lt;p&gt;其次，就是上面 &lt;code&gt;addApple&lt;&#x2F;code&gt; 这个例子。这个函数不管接受的是什么，它只向里面添加一个苹果。这时，它希望得到的是一个 &lt;code&gt;List&amp;lt;Apple&amp;gt;&lt;&#x2F;code&gt; 但我们却可以安全地提供一个 &lt;code&gt;List&amp;lt;Fruit&amp;gt;&lt;&#x2F;code&gt;。因此，它是逆变的。&lt;&#x2F;p&gt;
&lt;p&gt;看出差别了吗？&lt;&#x2F;p&gt;
&lt;p&gt;规律就是，当一个容器类型只读时，他就是协变的，当一个容器类型只写时，他就是逆变的。&lt;&#x2F;p&gt;
&lt;p&gt;而当它既可读又可写时，他就是不变的，也就是说我们无法假定任何他们的关系，否则就可能出错。因此对于类型构造器 &lt;code&gt;List&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 来说，它实际上是不变的。&lt;&#x2F;p&gt;
&lt;p&gt;举一个例子，对于只读容器 &lt;code&gt;ReadOnly&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;，如果我希望能从中读取到一个 &lt;code&gt;Fruit&lt;&#x2F;code&gt;，那么给我给一个 &lt;code&gt;ReadOnly&amp;lt;Apple&amp;gt;&lt;&#x2F;code&gt;，我一定可以读到一个 &lt;code&gt;Apple&lt;&#x2F;code&gt;，而 &lt;code&gt;Apple&lt;&#x2F;code&gt; 是一个 &lt;code&gt;Fruit&lt;&#x2F;code&gt;，所以是可以的。对于只写容器 &lt;code&gt;WriteOnly&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;，如果我希望向里面添加一个 &lt;code&gt;Apple&lt;&#x2F;code&gt;，那么给我一个 &lt;code&gt;WriteOnly&amp;lt;Fruit&amp;gt;&lt;&#x2F;code&gt;，我可以安全地向里面添加一个苹果，因为一个 &lt;code&gt;Apple&lt;&#x2F;code&gt; 一定是一个 &lt;code&gt;Fruit&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;除此之外还存在一种特殊的类型，函数类型。&lt;&#x2F;p&gt;
&lt;p&gt;考虑最简单的一元函数，即接受一个 &lt;code&gt;T&lt;&#x2F;code&gt; 类型的参数，返回一个 &lt;code&gt;U&lt;&#x2F;code&gt; 类型的结果，记为 &lt;code&gt;T -&amp;gt; U&lt;&#x2F;code&gt;，其中 &lt;code&gt;T&lt;&#x2F;code&gt; 是逆变，&lt;code&gt;U&lt;&#x2F;code&gt; 是协变的。&lt;&#x2F;p&gt;
&lt;p&gt;返回值 &lt;code&gt;U&lt;&#x2F;code&gt; 是协变的，因为当我需要一个返回任意水果的函数时，当然可以给我一个返回苹果的函数。&lt;&#x2F;p&gt;
&lt;p&gt;而参数 &lt;code&gt;T&lt;&#x2F;code&gt; 是逆变的，因为当我需要一个能够处理苹果的函数时，也可以给我一个更加通用的能够处理任意水果的函数。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;生命周期的子类型化&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#生命周期的子类型化&quot; aria-label=&quot;Anchor link for: 生命周期的子类型化&quot;&gt;生命周期的子类型化&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;上面我们讨论了面向对象的程序设计中的子类型和型变，可是，Rust 是没有继承的，也就没有子类型。所以它和 Rust 有什么关系呢？&lt;&#x2F;p&gt;
&lt;p&gt;Rust 虽然没有类型系统的继承，但是，它是有生命周期的。生命周期一样有子类型和型变。&lt;&#x2F;p&gt;
&lt;p&gt;子类型只是一种关系，而 Rust 的生命周期是平行于类型系统的另一种变量的属性，它一样也有子类型的关系。&lt;&#x2F;p&gt;
&lt;p&gt;然而，比较反直觉的是，在 Rust 中，大的生命周期是小的生命周期的子类型，即 &lt;code&gt;&#x27;static &amp;lt;: &#x27;big &amp;lt;: small&lt;&#x2F;code&gt;，与 OOP 中 &lt;code&gt;Object&lt;&#x2F;code&gt; 是所有类型的父类型相反，&lt;code&gt;&#x27;static&lt;&#x2F;code&gt; 是所有生命周期的子类型。&lt;&#x2F;p&gt;
&lt;p&gt;我们可以这样理解，当我们需要读取一个 &lt;code&gt;&#x27;small&lt;&#x2F;code&gt; 生命周期的变量时，提供一个 &lt;code&gt;&#x27;big&lt;&#x2F;code&gt; 生命周期的变量通常是可以的，也就是说，通常，我们可以将 &lt;code&gt;&#x27;big&lt;&#x2F;code&gt; 生命周期视为 &lt;code&gt;&#x27;small&lt;&#x2F;code&gt; 生命周期处理，收窄生命周期是安全的，反之，如果我们将 &lt;code&gt;&#x27;small&lt;&#x2F;code&gt; 当作 &lt;code&gt;&#x27;big&lt;&#x2F;code&gt; 则会导致内存不安全。这和我们在读取时可以将 &lt;code&gt;Apple&lt;&#x2F;code&gt; 当作 &lt;code&gt;Fruit&lt;&#x2F;code&gt; 是类似的。而对于 &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; 来说，当需要任意一个生命周期时，我们都可以安全的提供一个 &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;，就好像在 OOP 中存在一个所有类型的子类型，无论需要什么类型都可以提供这个类型。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;Rust_中的型变&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#Rust_中的型变&quot; aria-label=&quot;Anchor link for: Rust_中的型变&quot;&gt;Rust 中的型变&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;根据 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;subtyping.html&quot;&gt;The Rustonomicon&lt;&#x2F;a&gt; 里面的表格。&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;&#x27;a&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;T&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: center&quot;&gt;U&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;amp;&#x27;a T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;amp;&#x27;a mut T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;不变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;UnsafeCell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;不变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;不变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;fn(T) -&amp;gt; U&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;逆变&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;*const T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;协变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;*mut T&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;不变&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: center&quot;&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;让我们来逐条分析一下：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&#x27;a T&lt;&#x2F;code&gt; 对 &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; 和 &lt;code&gt;T&lt;&#x2F;code&gt; 协变，这是因为 &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; 是一个只读容器。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&#x27;a mut T&lt;&#x2F;code&gt; 对 &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; 协变，对 &lt;code&gt;T&lt;&#x2F;code&gt; 不变。对 &lt;code&gt;T&lt;&#x2F;code&gt; 不变很好理解，因为 &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; 是可读写容器，就像前面例子里的 &lt;code&gt;List&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 一样。对 &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; 协变是因为，和类型系统的子类型不同，生命周期不存在读取和写入和区别，它只是指示了变量何时可用，当变量不可用时，即不能读取，也不能写入。所以可以将生命周期视为类型系统里的读取关系，所以它一直是协变的。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 和 &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 对 &lt;code&gt;T&lt;&#x2F;code&gt; 协变，这放在其他语言里是不可能的，但是在 Rust 中，如果当前拥有着一个容器的所有权时，可以保证一定没有其他人能够读取和修改它。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;UnsafeCell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 和 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 是用来实现内部可变性的，因此它是可读写容器，对 &lt;code&gt;T&lt;&#x2F;code&gt; 不变。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;fn(T) -&amp;gt; U&lt;&#x2F;code&gt; 函数类型和前面的函数类型是一样的，特别的是，这里的对函数参数 &lt;code&gt;T&lt;&#x2F;code&gt; 逆变是 Rust 中唯一的逆变。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;*const T&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;*mut T&lt;&#x2F;code&gt; 和 &lt;code&gt;&amp;amp;&#x27;a T&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;&amp;amp;&#x27;a mut T&lt;&#x2F;code&gt; 类似，这里就不再赘述。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;最后，引用 &lt;em&gt;The Rustonomicon&lt;&#x2F;em&gt; 中的例子，稍作修改：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; assign&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; val&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; val&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;    let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;static str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; world&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;world&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; &amp;amp;&amp;#39;world str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        assign&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; hello&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; world&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;{hello}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;很明显，这里是不安全的，无法通过编译，在最后的 &lt;code&gt;println!()&lt;&#x2F;code&gt; 处 &lt;code&gt;world&lt;&#x2F;code&gt; 已经被释放了。&lt;&#x2F;p&gt;
&lt;p&gt;这里的问题在于，调用 &lt;code&gt;assign&lt;&#x2F;code&gt; 时，我们传入的两个类型是 &lt;code&gt;&amp;amp;mut &amp;amp;&#x27;static str&lt;&#x2F;code&gt; 和 &lt;code&gt;&amp;amp;&#x27;world str&lt;&#x2F;code&gt;，根据 &lt;code&gt;&amp;amp;&#x27;a T&lt;&#x2F;code&gt; 对 &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; 协变，所以 &lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt; 是 &lt;code&gt;&amp;amp;&#x27;world str&lt;&#x2F;code&gt; 的子类型。但是 &lt;code&gt;&amp;amp;&#x27;a mut T&lt;&#x2F;code&gt; 对 &lt;code&gt;T&lt;&#x2F;code&gt; 不变，所以这里，编译器不能对它做任何子类型化，因此，按照函数声明中的要求，&lt;code&gt;val&lt;&#x2F;code&gt; 参数的 &lt;code&gt;T&lt;&#x2F;code&gt; 和 &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt; 中的 &lt;code&gt;T&lt;&#x2F;code&gt; 必须“完全相同”，而这里 &lt;code&gt;val&lt;&#x2F;code&gt; 中的 &lt;code&gt;T&lt;&#x2F;code&gt; 是 &lt;code&gt;&amp;amp;&#x27;world str&lt;&#x2F;code&gt;，不是 &lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt;，所以生命周期检查失败了。&lt;&#x2F;p&gt;
&lt;p&gt;如果修改成这样就可以通过检查了：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; assign&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; val&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; val&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;static str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-modifier&quot;&gt;        let mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; world&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;world&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;&#x2F; &amp;amp;&amp;#39;world str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        assign&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; world&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; hello&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;我们传入的两个类型是 &lt;code&gt;&amp;amp;mut &amp;amp;&#x27;world str&lt;&#x2F;code&gt; 和 &lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt;，同样，要求 &lt;code&gt;val&lt;&#x2F;code&gt; 中的 &lt;code&gt;T&lt;&#x2F;code&gt; 和 &lt;code&gt;&amp;amp;mut T&lt;&#x2F;code&gt; 中的 &lt;code&gt;T&lt;&#x2F;code&gt; 完全相同，可是这里传入的也不相同啊？这涉及到了 Rust 的类型自动强转机制，“在函数传参时，实参将自动转换为形参”，允许转换的规则中有一条“子类型可以转换为父类型”，虽然 &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt; 无法进行子类型化，但 &lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt; 是 &lt;code&gt;&amp;amp;&#x27;world str&lt;&#x2F;code&gt; 的子类型，&lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt; 被自动强转为 &lt;code&gt;&amp;amp;&#x27;world str&lt;&#x2F;code&gt;，因此通过了生命周期检查。上面的例子，则无法进行上述的自动强转，所以生命周期检查失败了。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;参考&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#参考&quot; aria-label=&quot;Anchor link for: 参考&quot;&gt;参考&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;subtyping.html&quot;&gt;Subtyping and Variance - The Rustonomicon&lt;&#x2F;a&gt; （&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nomicon.purewhite.io&#x2F;subtyping.html&quot;&gt;中文翻译&lt;&#x2F;a&gt;）&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;subtyping.html&quot;&gt;Subtyping and Variance - The Rust Reference&lt;&#x2F;a&gt; （&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustwiki.org&#x2F;zh-CN&#x2F;reference&#x2F;subtyping.html&quot;&gt;中文翻译&lt;&#x2F;a&gt;）&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;type-coercions.html&quot;&gt;Type coercions - The Rust Reference&lt;&#x2F;a&gt; （&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustwiki.org&#x2F;zh-CN&#x2F;reference&#x2F;type-coercions.html&quot;&gt;中文翻译&lt;&#x2F;a&gt;）&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ioover.net&#x2F;dev&#x2F;variance-and-subtyping&#x2F;&quot;&gt;逆变、协变与子类型，以及 Rust&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>编写现代的 Python</title>
          <pubDate>Tue, 24 Oct 2023 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/writing-modern-python/</link>
          <guid>https://st1020.com/posts/writing-modern-python/</guid>
          <description xml:base="https://st1020.com/posts/writing-modern-python/">&lt;p&gt;好久没写博客了，今天想结合我个人的经验聊一聊如何编写现代的 Python 代码。&lt;&#x2F;p&gt;
&lt;p&gt;在聊这个问题之前，首先要定义一下什么是“现代的 Python”和我为什么想要使用这种方式编写 Python。&lt;&#x2F;p&gt;
&lt;p&gt;或许你听说过“Modern C++”，这通常指的是 C++11 之后的 C++ 标准，现代的 C++ 带来了许多新的特性，如智能指针、auto、更强大的标准库、增强的 for 循环、移动语义、lambda 表达式等，这些新特性使得 C++ 赶上了时代的脚步，大大提高了开发的效率。&lt;&#x2F;p&gt;
&lt;p&gt;而 Python 作为诞生于三十多年前的编程语言，在这三十年间也发生了许多变化，最著名的变化莫过于 Python 2 到 Python 3 的不兼容升级。但本文我想聊的并非所有的 Python 新特性，毕竟 Python 的新特性可以直接在 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;whatsnew&#x2F;index.html&quot;&gt;What’s New in Python&lt;&#x2F;a&gt; 中找到，我想说的是一种编程风格或者说编程范式。&lt;&#x2F;p&gt;
&lt;p&gt;这些思想很大程度上并非我的原创，而是来自于 Rust 语言。自从我开始使用 Rust 语言，它就很大程度上影响了我编写其他语言的的方式，尤其是 Python 语言。&lt;&#x2F;p&gt;
&lt;p&gt;这篇博客还受到了 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kobzol.github.io&#x2F;rust&#x2F;python&#x2F;2023&#x2F;05&#x2F;20&#x2F;writing-python-like-its-rust.html&quot;&gt;Writing Python like it&#x27;s Rust&lt;&#x2F;a&gt; 的启发，其中的很多思想都和我不谋而合 (实际上我是写到一半才发现这篇文章的，感觉他把我想说的都说的差不多了)。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;开始之前：Formatter_and_Linter&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#开始之前：Formatter_and_Linter&quot; aria-label=&quot;Anchor link for: 开始之前：Formatter_and_Linter&quot;&gt;开始之前：Formatter and Linter&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在开始之前，我想先聊一个和本文关系不大的问题，那就是格式化和风格检查。&lt;&#x2F;p&gt;
&lt;p&gt;几乎所有的语言都有官方推荐或社区广泛认同的代码格式和风格，而许多诞生比较晚的现代语言还在工具链中附带了 Formatter 和 Linter，比如 Rust 的 &lt;code&gt;rustfmt&lt;&#x2F;code&gt; 和 &lt;code&gt;clippy&lt;&#x2F;code&gt;。但很遗憾 Python 并没有一个附带的 Formatter 和 Linter。&lt;&#x2F;p&gt;
&lt;p&gt;在所有 Python 的 Formatter 中我一直使用的是 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;psf&#x2F;black&quot;&gt;black&lt;&#x2F;a&gt;，因为它相对比较严格，就像前端届的 Prettier 一样，它是一个“固执己见”(opinionated) 的格式化工具。我觉得 Formatter 的主要作用就是提供一个尽可能统一的格式，以尽可能省去手动格式化和时间和团队协作中对格式的争论，因此，Formatter 越严格越好，至于细节的格式，我并没有特别的偏好，只要不太奇怪，严格和统一就是最好的。&lt;&#x2F;p&gt;
&lt;p&gt;而在 Linter 中我首推 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;ruff&quot;&gt;Ruff&lt;&#x2F;a&gt;，它是一个用 Rust 编写的 Python Linter，因此具有极快的速度。是真的非常快，比传统的 Python Linter 快几个数量级。除此之外，它的规则也比较全，涵盖了代码风格的方方面面，可以完全替代 Flake8 和 isort。除此之外，如果需要更加细致的代码检查的话可以选择 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pylint-dev&#x2F;pylint&quot;&gt;Pylint&lt;&#x2F;a&gt;，它会对代码进行更加深入的静态检查，但代价是很慢，比 Ruff 慢 2-3 个数量级。&lt;&#x2F;p&gt;
&lt;p&gt;在现代语言中，我认为应该永远使用尽可能严格的 Formatter 和 Linter，人是一个不精确的机器，没有人能永远按照最佳实践编写代码，尽管关于软件架构和复杂的逻辑仍然需要人的设计，但至少我们应该在细节的代码格式和风格方面尽可能遵循最佳实践，计算机擅长干的事就不要让人来做，让工具来约束是最简单的。并且尽可能严格的 Formatter 和 Linter 也有助于团队协作时避免风格的差异。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;现代_Python_的哲学&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#现代_Python_的哲学&quot; aria-label=&quot;Anchor link for: 现代_Python_的哲学&quot;&gt;现代 Python 的哲学&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;我认为，在程序设计中的一个很重要的原则就是“承诺”，比如 Rust 的宣传的重点就是它的安全性承诺和零开销抽象承诺，即只要不使用 &lt;code&gt;unsafe&lt;&#x2F;code&gt; 那就不可能出现内存安全问题，以及只需要为用到的功能付出时间、空间代价。&lt;&#x2F;p&gt;
&lt;p&gt;很显然，Python 作为一个有 GC 的语言，已经提供了安全性承诺，而零开销抽象也并非 Python 语言所关注的重点，这里我希望的是通过一种良好的代码风格做到健壮性 (也被翻译为鲁棒性，但我觉得这个翻译很糟糕)。&lt;&#x2F;p&gt;
&lt;p&gt;传统上，我们编写 Python 时很容易写出类似下面的代码：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get_person&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;person_id&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: person_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;Alice&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;permission&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            &amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            &amp;quot;is_admin&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            &amp;quot;user_groups&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; check_permission&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;person&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; person[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;permission&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;is_admin&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt; or&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;root&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; person[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;permission&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;user_groups&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这种代码是不好的，因为它很容易被误用，并且会提高修改、维护和使用的成本。当我们使用 &lt;code&gt;check_permission&lt;&#x2F;code&gt; 这个函数时，在不阅读函数体的情况下，我们无法确定这里需要的 person 参数到底是什么，在编写或修改这个函数时，我们也无法保证正确性，比如出现 person 字典的结构发生变更但忘记修改 &lt;code&gt;check_permission&lt;&#x2F;code&gt; 函数，或者 &lt;code&gt;check_permission&lt;&#x2F;code&gt; 函数里的字段名出现 typo 等。&lt;&#x2F;p&gt;
&lt;p&gt;就像墨菲定律一样，任何可能被误用的，最终一定会被误用。更重要的是，这样的代码没有提供任何健壮性承诺，当一个人 (也可能是自己) 在使用和修改这样的代码时，必须谨小慎微，并且永远无法保证自己没有出错。&lt;&#x2F;p&gt;
&lt;p&gt;因此，我认为，更加现代的 Python 编写风格就是要利用 Python 在近几个版本提供的几个有用的新特性来尽可能避免“不确定性”，提供更多的健壮性承诺，为了做到这一点，我们需要合理地限制 Python 的动态特性、坚持尽可能早的异常 (编译期异常优于运行时异常) 和使非法状态不可表示。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;类型注解_(Type_Hints)&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#类型注解_(Type_Hints)&quot; aria-label=&quot;Anchor link for: 类型注解_(Type_Hints)&quot;&gt;类型注解 (Type Hints)&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;首先，也是最重要的就是为 Python 代码编写类型注解，类型注解是在 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0484&#x2F;&quot;&gt;PEP 484&lt;&#x2F;a&gt; 和 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0483&#x2F;&quot;&gt;PEP 483&lt;&#x2F;a&gt; 中首次引入，并在 Python 3.5 版本正式开始支持的特性。直到现在仍在不断迭代和添加新特性中。&lt;&#x2F;p&gt;
&lt;p&gt;类型注解可以为 Python 提供静态的类型检查，它仅在静态类型检查器中被使用，而没有运行时性能损耗，即 Python 的类型注解会在运行时被忽略 (实际上可以被运行时获取，会被存储在 &lt;code&gt;__annotations__&lt;&#x2F;code&gt; 等魔术字段中，但不会进行检查)。&lt;&#x2F;p&gt;
&lt;p&gt;这相当于为 Python 引入了而外的编译期检查，能够在运行前避免常见的类型问题。常见的静态类型检查工具有 Python 官方提供的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;python&#x2F;mypy&quot;&gt;mypy&lt;&#x2F;a&gt;、微软提供的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;pyright&quot;&gt;pyright&lt;&#x2F;a&gt;、FaceBook 提供的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;facebook&#x2F;pyre-check&quot;&gt;pyre&lt;&#x2F;a&gt; 和 Google 提供的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;pytype&quot;&gt;pytype&lt;&#x2F;a&gt;，他们在一些细节上有不同的处理方式。&lt;&#x2F;p&gt;
&lt;p&gt;需要指出的是，我觉得 Python 的类型注解并不十分强大，与 Rust 这种静态类型语言自然没法比，与 TypeScript 相比也有不小的差距 (TS 的类型系统甚至是图灵完备的)，但是，这也并非是一个缺点，Python 的类型注解系统是十分 Pythonic 的，并且足够简单易用，不会像 TS 一样有非常复杂的类型体操，更重要的是，Python 的类型注解一直在进步，几乎每个版本都有关于类型注解的新特性加入。&lt;&#x2F;p&gt;
&lt;p&gt;很多人觉得为 Python 编写类型注解会影响编码速度。但我认为并非如此，单纯考虑额外编写类型注解的时间当然至少增加了打字的时间。但首先，在大多数情况下，即使不编写类型注解，在编写代码时自己也是清楚变量的类型的，因为类型本身就是程序的一部分，因此，显式写出类型只增加了打字时间而没有增加思考时间，大部分编程的速度瓶颈都不在打字时间上。其次，编写类型注解可以充分利用编辑器的自动提示功能，在很多情况下反而可以加快编码速度。最后，大多数程序都不是只编写一次、只运行一次、长度很短的小脚本，算上修改维护的时间为 Python 编写类型注解绝对是合算的。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;使用数据类_(dataclass)&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#使用数据类_(dataclass)&quot; aria-label=&quot;Anchor link for: 使用数据类_(dataclass)&quot;&gt;使用数据类 (dataclass)&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;数据类是在 Python 3.7 引入的，它基本上相当于 Python 中的结构体，不同于字典这种松散的结构，就像结构体一样，数据类可以限定字段的多少、名称、类型。&lt;&#x2F;p&gt;
&lt;p&gt;开始的例子使用数据类重写后：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; dataclasses&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;@dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Permission&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    is_admin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_groups: list[&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;@dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Person&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    permission: Permission&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get_person&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;person_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Person:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; Person(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=person_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Alice&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        permission&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=Permission(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            is_admin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            user_groups&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=[],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; check_permission&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;person&lt;&#x2F;span&gt;&lt;span&gt;: Person) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; person.permission.is_admin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt; or&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;root&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; person.permission.user_groups&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;使用数据类而非字典的优势是显而易见的，首先，它提供了嵌套类型中的类型提示和检查，避免了类型和字段错误，其次，它非常方便重构，修改字段名称后大部分编辑器都可以自动进行重构。&lt;&#x2F;p&gt;
&lt;p&gt;Python 自带的 &lt;code&gt;dataclasses&lt;&#x2F;code&gt; 并不会进行运行时类型检查，因此不适用于序列化和反序列化场景中，如果需要运行时数据校验的话可以使用 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pydantic&#x2F;pydantic&quot;&gt;Pydantic&lt;&#x2F;a&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;NewType&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#NewType&quot; aria-label=&quot;Anchor link for: NewType&quot;&gt;NewType&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在 Rust 中存在一种被称为 &lt;code&gt;NewType&lt;&#x2F;code&gt; 的用法，可以查看下面的 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;rust-by-example&#x2F;generics&#x2F;new_types.html&quot;&gt;Rust 官方的例子&lt;&#x2F;a&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Years&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Days&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Years&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; to_days&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Days&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Days&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 365&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Days&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F; truncates partial years&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; to_years&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Years&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Years&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 365&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; old_enough&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;age&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Years&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    age&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 18&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; age&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Years&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; age_days&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; age&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_days&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Old enough {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; old_enough&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Old enough {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; old_enough&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;age_days&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_years&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    &#x2F;&#x2F; println!(&amp;quot;Old enough {}&amp;quot;, old_enough(&amp;amp;age_days));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;它可以指定一个和原有的类型完全一致的新类型，但额外指定它的预期用途，比如上面的例子，&lt;code&gt;i64&lt;&#x2F;code&gt; 只表示这是一个 64 位整数而没有任何其他的信息，而 &lt;code&gt;Years&lt;&#x2F;code&gt; 则进一步说明了这是一个用于表示年份的整数。同时 NewType 也限制了新类型的用法，即封装后的类型只有 &lt;code&gt;to_days()&lt;&#x2F;code&gt; 这一个关联方法，而无法再使用对 &lt;code&gt;i64&lt;&#x2F;code&gt; 可以使用的其他方法，因为其他方法对于“年”这个类型来说很可能是没有意义的。&lt;&#x2F;p&gt;
&lt;p&gt;这也是一个防止误用的技巧。如果上面的 &lt;code&gt;old_enough&lt;&#x2F;code&gt; 函数的签名是：&lt;code&gt;fn old_enough(age: &amp;amp;i64) -&amp;gt; bool&lt;&#x2F;code&gt;，那么使用者就无法从函数的读出 &lt;code&gt;age&lt;&#x2F;code&gt; 的单位是秒、天、月还是年，从而可能造成误用。使用 NewType 可以让类型包含更多的信息，进一步明确类型。&lt;&#x2F;p&gt;
&lt;p&gt;在获得上述好处的同时，完全没有任何性能代价，NewType 被编译后完全就是原本的类型，所有的限制都是编译期的，没有任何运行时损耗。&lt;&#x2F;p&gt;
&lt;p&gt;Python 中也提供了 NewType 的支持。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; typing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; NewType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;Years = NewType(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Years&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;Days = NewType(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Days&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; old_enough&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;age&lt;&#x2F;span&gt;&lt;span&gt;: Years) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; age &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 18&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    age = Years(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Old enough &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;old_enough(age)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Python 是支持继承的，因此上面的操作和创建一个 &lt;code&gt;Years&lt;&#x2F;code&gt; 类继承 &lt;code&gt;int&lt;&#x2F;code&gt; 的效果类似，但是，创建子类是有运行时开销的，而 NewType 则没有。NewType 仅在类型检查中被使用，相当于在类型检查中认为是一个子类，在运行时认为是它本身。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;组合优于继承&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#组合优于继承&quot; aria-label=&quot;Anchor link for: 组合优于继承&quot;&gt;组合优于继承&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在 Rust 中是没有类 (class) 的，但存在 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Trait_(computer_programming)&quot;&gt;trait&lt;&#x2F;a&gt; 的概念，类似其他语言的接口 (&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Interface_(object-oriented_programming)&quot;&gt;protocols&#x2F;interfaces&lt;&#x2F;a&gt;)。&lt;&#x2F;p&gt;
&lt;p&gt;因为 Python 支持多继承和抽象基类，因此在 Python 中组合和继承的差别实际上是比较模糊的。&lt;&#x2F;p&gt;
&lt;p&gt;在 Python 中可以利用抽象基类实现组合：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; abc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; ABC, abstractmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Openable&lt;&#x2F;span&gt;&lt;span&gt;(ABC):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    @abstractmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Closable&lt;&#x2F;span&gt;&lt;span&gt;(ABC):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    @abstractmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; File&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt;Openable&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt; Closable&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;open&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;close&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; open_it&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;openable&lt;&#x2F;span&gt;&lt;span&gt;: Openable):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    openable.open()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open_it(File())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;或者利用 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0544&#x2F;&quot;&gt;PEP 544&lt;&#x2F;a&gt; 在 Python 3.8 中引入的 Protocol 和结构子类型：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; typing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Protocol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Openable&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt;Protocol&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Closable&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class&quot;&gt;Protocol&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; File&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;open&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;close&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; open_it&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;openable&lt;&#x2F;span&gt;&lt;span&gt;: Openable):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    openable.open()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open_it(File())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;它们的主要区别在于前者需要显示声明而后者不需要，前者提供了运行时检查 (有运行时开销) 而后者没有。通常认为后者是更加 pythonic 的。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;构造函数&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#构造函数&quot; aria-label=&quot;Anchor link for: 构造函数&quot;&gt;构造函数&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在 Rust 中不存在类似 Python 中 &lt;code&gt;__init__&lt;&#x2F;code&gt; 的默认构造器，取而代之的是使用普通的关联函数进行构造，这有什么好处呢？&lt;&#x2F;p&gt;
&lt;p&gt;这有助于更加明确地实现一个类型有多个构造器的情况，比如：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Rectangle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    width&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    height&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Rectangle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;width&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; height&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; width&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; height&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            width&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; size&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            height&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; size&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Rectangle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Rectangle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;对于 Python 传统上则可能会写成：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; typing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; overload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Rectangle&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    width:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    height:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    @overload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; width&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    @overload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; width&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; height&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; width&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; height&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; height&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-python z-constant z-language&quot;&gt; is None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            height = width&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.width = width&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.height = height&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Rectangle(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Rectangle(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;为什么一个结构体&#x2F;类只能有一个构造函数呢？即使使用了 &lt;code&gt;overload&lt;&#x2F;code&gt; 类型注解，上面的 Python 代码仍然并不利于识读，当一个不熟悉 &lt;code&gt;Rectangle&lt;&#x2F;code&gt; 的人看到类似 &lt;code&gt;Rectangle(1)&lt;&#x2F;code&gt; 的代码，他并无法直接认识到这是用于构造正方形的方法。&lt;&#x2F;p&gt;
&lt;p&gt;因此我认为可以使用下面的方式实现：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; dataclasses&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; typing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; Self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;@dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Rectangle&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    width:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    height:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    @&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt;classmethod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; square&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;cls&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; size&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; Self:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; cls&lt;&#x2F;span&gt;&lt;span&gt;(size, size)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __name__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Rectangle(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Rectangle.square(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;代数数据类型和模式匹配&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#代数数据类型和模式匹配&quot; aria-label=&quot;Anchor link for: 代数数据类型和模式匹配&quot;&gt;代数数据类型和模式匹配&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;代数数据类型 (&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Algebraic_data_type&quot;&gt;algebraic data type(ADT)&lt;&#x2F;a&gt;) 指的是一种复合类型，包括积类型与和类型。&lt;&#x2F;p&gt;
&lt;p&gt;积类型的典型例子就是元组，其可能值是其字段类型可能值的笛卡尔积。&lt;&#x2F;p&gt;
&lt;p&gt;和类型的例子是 Rust 中的 &lt;code&gt;enum&lt;&#x2F;code&gt; 和 Python 中的 &lt;code&gt;Union&lt;&#x2F;code&gt;，其可能值是其字段类型的并集。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; B&lt;&#x2F;span&gt;&lt;span&gt;: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; C&lt;&#x2F;span&gt;&lt;span&gt;: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; D&lt;&#x2F;span&gt;&lt;span&gt;: ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;Type1 = A | B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;Type2 = C | D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;product_type = tuple[Type1, Type2]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# possible values: (A, C) | (A, D) | (B, C) | (B, D)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;sum_type = Type1 | Type2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# possible values: A | B | C | D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ADT 中积类型的应用比较简单，在大多数语言中均有广泛应用，下面重点关注一下和类型。&lt;&#x2F;p&gt;
&lt;p&gt;和类型和继承&#x2F;接口不同在于，继承&#x2F;接口是开放的，而和类型是封闭的，也就是说，如果我们指定一个函数可以接受 A 类型，那么它就可以接受 A 的所有子类型，但我们无从得知这个 A 有几个子类型，因此只能使用定义在 A 中的公共方法。而如果是和类型，则可以显式地得知这个它是由几个字段类型组合而成的，从而对每个字段类型分别进行处理。&lt;&#x2F;p&gt;
&lt;p&gt;结合模式匹配，就可以实现类似下面的例子，可以静态检查是否忘记了处理某种情况。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Node&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    If&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        test&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        consequent&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        alternate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    While&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        test&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Add&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Ident&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; eval&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;node&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Node&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; node&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Node&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;If&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            test&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            consequent&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            alternate&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        } =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; todo!&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Node&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;While&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; } =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; todo!&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Node&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; left&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; } =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; todo!&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Node&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Ident&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ident&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;) =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; todo!&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;对于 Python 来说，Python 在 3.10 引入了模式匹配 &lt;code&gt;match-case&lt;&#x2F;code&gt; 语法：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt; __future__&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; annotations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; dataclasses&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; typing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; NewType, assert_never&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;@dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; If&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    test: Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    consequent: Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    alternate: Node |&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;@dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; While&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    test: Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    body: Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;@dataclass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    left: Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    right: Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;Ident = NewType(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Ident&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;Node = If | While | Add | Ident&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; eval&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;node&lt;&#x2F;span&gt;&lt;span&gt;: Node):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; node:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span&gt; If(test, consequent, alternate):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span&gt; While(test, body):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span&gt; Add(left, right):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span&gt; Ident(ident):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        case&lt;&#x2F;span&gt;&lt;span&gt; _:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            assert_never(node)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;但是，Python 的类型系统并不强制要求匹配完所有可能的分支，因此，需要在最后添加 &lt;code&gt;assert_never&lt;&#x2F;code&gt; 以要求类型检查器在未匹配完成时报错。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;总结&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#总结&quot; aria-label=&quot;Anchor link for: 总结&quot;&gt;总结&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;总之，编写所谓“现代的 Python”的关键就在于利用 Python 的类型系统来保证 Python 的健壮性。很多时候，在业务代码中，我们其实并不需要，也不应该需要 Python 提供的如此大的灵活性。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Absolute freedom mocks at justice. Absolute justice denies freedom. To be fruitful, the two ideas must find their limits in each other.&lt;&#x2F;p&gt;
&lt;p&gt;Albert Camus, The Rebel (1951)，as translated by Anthony Bower&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</description>
      </item>
      <item>
          <title>Powered by Zola</title>
          <pubDate>Mon, 23 Oct 2023 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/powered-by-zola/</link>
          <guid>https://st1020.com/posts/powered-by-zola/</guid>
          <description xml:base="https://st1020.com/posts/powered-by-zola/">&lt;p&gt;在三年前这个博客从 Hexo 迁移到 Hugo 之后，这一次又从 Hugo 迁移到了 Zola。&lt;&#x2F;p&gt;
&lt;p&gt;我之前使用的 Hugo 主题 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dillonzq&#x2F;LoveIt&quot;&gt;LoveIt&lt;&#x2F;a&gt; 已经停止维护好久了 (所以爱是会消失的对吗)，本来我想 fork 一份自己维护一下的，取名为 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;st1020&#x2F;LikeIt&quot;&gt;LikeIt&lt;&#x2F;a&gt;，意为比“Love”少一点，主要就是删除了一些我用不到组件，然后修了一些 Bug(虽然好像引入了一些新的 Bug)。&lt;&#x2F;p&gt;
&lt;p&gt;但在维护的过程中，我是在受不了。Go template 的阴间语法搭配上 Hugo 丰富而复杂的各种特性，再加上 LoveIt 主题本身的复杂性和我本身对 CSS 也不是很熟练，让维护工作十分不顺利。&lt;&#x2F;p&gt;
&lt;p&gt;尤其要点名批评 Go template 这个混沌邪恶的产物，它的语法实在是非常的反直觉了，感觉就像函数式语言和命令式语言的缝合。&lt;&#x2F;p&gt;
&lt;p&gt;除此之外，对于 Hugo 我也有一些抱怨，随着不断的发展，它已经太重了，这使得它的学习成本比较高，具体可以看一下 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mrkaran.dev&#x2F;posts&#x2F;migrating-to-zola&#x2F;&quot;&gt;Migrating my blog to Zola&lt;&#x2F;a&gt; 这篇博客中他迁移的原因。&lt;&#x2F;p&gt;
&lt;p&gt;所以，我觉得是时候换一个新的 SSG 了，对于新的 SSG 我有如下要求：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;拥有一个不那么阴间的模版语法。&lt;&#x2F;li&gt;
&lt;li&gt;使用非脚本语言编写。往往脚本语言编写的 SSG 的速度都不是很理想，并且我也不是很喜欢生成博客时还需要装一个 Node 环境或者 Python 的虚拟环境，这也是多余的开销，我希望新的 SSG 最好零依赖，只有一个二进制文件。&lt;&#x2F;li&gt;
&lt;li&gt;干净简单，约定优于配置，大多数功能都是可选的。&lt;&#x2F;li&gt;
&lt;li&gt;满足上述条件的前提下，有尽可能多的使用人数和持续良好的维护。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;综合上述条件，我最终找到了 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;。它是用 Rust 语言编写的，因此可以做到零依赖，并且性能比宣称“The world’s fastest framework for building websites”的 Hugo 还要好。它的模版引擎使用的是同一个作者开发 Tera，这是一个语法高度类似 Jinja 的模块引擎，也是 Rust 生态中最热门的模版引擎之一。更重要的它很简单清晰，Page、Section 的结构非常简单易懂。&lt;&#x2F;p&gt;
&lt;p&gt;但是，由于用户基数还不是很大，我并没有找到心仪的主题，也是防止新的主题再次停止维护，Zola 本身编写一个主题也十分简单，这次，我选择直接编写一个主题。&lt;&#x2F;p&gt;
&lt;p&gt;可我对自己的 UI 设计能力并没有自信，所以最终还是选择移植一个 Hugo 主题，并在它的基础上修改。&lt;&#x2F;p&gt;
&lt;p&gt;最终，我选择了 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nanxiaobei&#x2F;hugo-paper&quot;&gt;hugo-paper&lt;&#x2F;a&gt;，它是 Hugo 最热门的主题 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;adityatelange&#x2F;hugo-PaperMod&quot;&gt;hugo-PaperMod&lt;&#x2F;a&gt; 的前身，足够简洁美观，代码量也非常少，并且使用了 TailwindCSS。&lt;&#x2F;p&gt;
&lt;p&gt;我把 hugo-paper 移植到了 Zola 之后还做了不少的修改，比如增加了目录、项目页面、存档页面、分类页面、Mermaid 支持、Admonition shortcode 等，还做了不少样式的调整，多亏了 TailwindCSS 和 Zola，修改起来非常容易。&lt;&#x2F;p&gt;
&lt;p&gt;我将新的主题命名为 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;st1020&#x2F;kita&quot;&gt;Kita&lt;&#x2F;a&gt;，这个玩了一个三语梗，Zola 在中文中读起来就像“走啦”，而 Kita 是日语“来た”(来了) 的罗马音，同时也致敬了孤独摇滚里的“归去来兮女士”喜多郁代 (Kita Ikuyo) 的名字。&lt;&#x2F;p&gt;
&lt;p&gt;这次应该是最后一次迁移了 (如果 Zola 本身不停止维护的话，虽然即使停止维护功能也足够稳定和完整了)，有了自己的主题也方便之后随时修改啦。&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>修复 MacOS 升级后 VSCode LLDB 调试错误</title>
          <pubDate>Wed, 18 Oct 2023 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/fix-vscode-lldb-debug-error/</link>
          <guid>https://st1020.com/posts/fix-vscode-lldb-debug-error/</guid>
          <description xml:base="https://st1020.com/posts/fix-vscode-lldb-debug-error/">&lt;p&gt;最近升级了 MacOS 14 之后，发现无法使用 VSCode 调试 Rust 程序了，点击调试后程序直接闪退。调试控制台输出 &lt;code&gt;Process exited with code -1.&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;初步判断是 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vadimcn&#x2F;codelldb&quot;&gt;CodeLLDB&lt;&#x2F;a&gt; 拓展的问题，并在它的 GitHub 仓库里找到了解决方案。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vadimcn&#x2F;codelldb&#x2F;discussions&#x2F;456&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;vadimcn&#x2F;codelldb&#x2F;discussions&#x2F;456&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vadimcn&#x2F;codelldb&#x2F;issues&#x2F;999&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;vadimcn&#x2F;codelldb&#x2F;issues&#x2F;999&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;看起来是一个老问题了，从 MacOS 12 开始就一直存在，修复的方法也很简单，只需要删除拓展目录下的 &lt;code&gt;vadimcn.vscode-lldb-1.x.x&#x2F;lldb&#x2F;bindebugserver&lt;&#x2F;code&gt; 即可，删除 &lt;code&gt;bindebugserver&lt;&#x2F;code&gt; 后拓展会自动使用系统提供的 &lt;code&gt;bindebugserver&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;根据作者的说法，CodeLLDB 捆绑的 debugserver 来自 XCode 10，但最新的 XCode 已经更新到 15 了，应该是新版本 MacOS 和老版本 debugserver 存在兼容性问题。&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Git 重写历史和修复提交日期</title>
          <pubDate>Sun, 15 Aug 2021 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/git-rewrite-history-and-fix-commit-date/</link>
          <guid>https://st1020.com/posts/git-rewrite-history-and-fix-commit-date/</guid>
          <description xml:base="https://st1020.com/posts/git-rewrite-history-and-fix-commit-date/">&lt;p&gt;前几天，我发现之前项目中的一个历史提交的 commit 消息写错了，想要进行修改，记录一下修改的过程。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;修改最后一次提交&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#修改最后一次提交&quot; aria-label=&quot;Anchor link for: 修改最后一次提交&quot;&gt;修改最后一次提交&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;修改最后一次提交很简单，git 已经提供了一个命令进行更改：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; commit&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --amend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上述命令会打开一个编辑器，可以在编辑器中编辑要修改的 commit 消息，然后退出即可保存。&lt;&#x2F;p&gt;
&lt;p&gt;可惜的是，我并不是这种情况，而是许多个提交之前的历史提交。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;修改历史提交&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#修改历史提交&quot; aria-label=&quot;Anchor link for: 修改历史提交&quot;&gt;修改历史提交&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;假设我们当前的提交记录是这样的：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit c9837cd063d3591d86505d3ab095744173b863b2 (HEAD -&amp;gt; master)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author: st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Date:   Sun Aug 15 21:51:39 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    test commit 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit 98a8bb09d823c5800f1b9ffbe8e2cb40fc8a456c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author: st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Date:   Sun Aug 15 21:51:10 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    test commit 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit de14f7451ede9600a3172ef99f652d231791b16f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author: st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Date:   Sun Aug 15 21:50:34 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Init Commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;需要将 &lt;code&gt;test commit 1&lt;&#x2F;code&gt; 这条提交消息更改为 &lt;code&gt;first commit&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;首先，需要找到要修改的提交的前一个提交，即 &lt;code&gt;de14f74&lt;&#x2F;code&gt;，执行变基：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rebase&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; de14f74&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;执行上述命令会进入文本编辑器，应该会得到类似下面的信息：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pick 98a8bb0 test commit 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pick c9837cd test commit 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# 变基 de14f74..c9837cd 到 de14f74（2 个提交）&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# 命令：&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# p, pick &amp;lt;提交&amp;gt; = 使用提交&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# r, reword &amp;lt;提交&amp;gt; = 使用提交，但编辑提交说明&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# e, edit &amp;lt;提交&amp;gt; = 使用提交，但停止以便在 sh 中修补提交&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# s, squash &amp;lt;提交&amp;gt; = 使用提交，但挤压到前一个提交&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# f, fixup [-C | -c] &amp;lt;提交&amp;gt; = 类似于 &amp;quot;squash&amp;quot;，但只保留前一个提交&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#                    的提交说明，除非使用了 -C 参数，此情况下则只&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#                    保留本提交说明。使用 -c 和 -C 类似，但会打开&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#                    编辑器修改提交说明&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# x, exec &amp;lt;命令&amp;gt; = 使用 sh 运行命令（此行剩余部分）&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# b, break = 在此处停止（使用 &amp;#39;git rebase --continue&amp;#39; 继续变基）&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# d, drop &amp;lt;提交&amp;gt; = 删除提交&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# l, label &amp;lt;label&amp;gt; = 为当前 HEAD 打上标记&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# t, reset &amp;lt;label&amp;gt; = 重置 HEAD 到该标记&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# m, merge [-C &amp;lt;commit&amp;gt; | -c &amp;lt;commit&amp;gt;] &amp;lt;label&amp;gt; [# &amp;lt;oneline&amp;gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# .       创建一个合并提交，并使用原始的合并提交说明（如果没有指定&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# .       原始提交，使用注释部分的 oneline 作为提交说明）。使用&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# .       -c &amp;lt;提交&amp;gt; 可以编辑提交说明。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# 可以对这些行重新排序，将从上至下执行。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# 如果您在这里删除一行，对应的提交将会丢失。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# 然而，如果您删除全部内容，变基操作将会终止。&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;我们现在需要把要修改的那次提交前的 &lt;code&gt;pick&lt;&#x2F;code&gt; 更改为 &lt;code&gt;edit&lt;&#x2F;code&gt; 或者 &lt;code&gt;e&lt;&#x2F;code&gt;，之后 &lt;code&gt;:wq&lt;&#x2F;code&gt; 保存退出：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edit 98a8bb0 test commit 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pick c9837cd test commit 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;会输出以下信息：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;停止在 98a8bb0... test commit 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;您现在可以修补这个提交，使用&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  git commit --amend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;当您对变更感到满意，执行&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  git rebase --continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;修改完成后，执行 &lt;code&gt;git commit --amend&lt;&#x2F;code&gt; 进入编辑器编辑提交消息，或者直接使用 &lt;code&gt;git commit --amend -m &quot;first commit&quot;&lt;&#x2F;code&gt; 提交。&lt;&#x2F;p&gt;
&lt;p&gt;之后，只需执行 &lt;code&gt;git rebase --continue&lt;&#x2F;code&gt; 即可完成修改。&lt;&#x2F;p&gt;
&lt;p&gt;再次查看 &lt;code&gt;git log&lt;&#x2F;code&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit 6118ceb757f15b602eff73db5adccb293a2d6821 (HEAD -&amp;gt; master)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author: st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Date:   Sun Aug 15 21:51:39 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    test commit 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit 3bf6a7f2d1d493e5d7c831f2bb2922796e8ca380&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author: st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Date:   Sun Aug 15 21:51:10 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit de14f7451ede9600a3172ef99f652d231791b16f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author: st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Date:   Sun Aug 15 21:50:34 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Init Commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;会发现提交消息已经被修改了，并且因为变基，这次修改的提交及其之后的提交的 SHA-1 全都发生了改变。&lt;&#x2F;p&gt;
&lt;p&gt;如果已经将这些提交推送到了远程仓库，那么可以执行 &lt;code&gt;git push -f&lt;&#x2F;code&gt; 强制推送。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;修复提交日期&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#修复提交日期&quot; aria-label=&quot;Anchor link for: 修复提交日期&quot;&gt;修复提交日期&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;但是，当我强制推送到了 github 远程仓库后却发现，github 提交记录中被修改的提交后的提交的日期是全都变成了今天，但是 &lt;code&gt;git log&lt;&#x2F;code&gt; 中的明明没有问题啊？&lt;&#x2F;p&gt;
&lt;p&gt;经过一番查找，我最终发现，git 的 commit 的日期实际上包含了两个日期，分别是 &lt;code&gt;AuthorDate&lt;&#x2F;code&gt; 和 &lt;code&gt;CommitDate&lt;&#x2F;code&gt;，&lt;code&gt;git log&lt;&#x2F;code&gt; 中默认显示的是 &lt;code&gt;AuthorDate&lt;&#x2F;code&gt; 而 github 的提交记录中显示的则是 &lt;code&gt;CommitDate&lt;&#x2F;code&gt;，上述的变基操作不会改变 &lt;code&gt;AuthorDate&lt;&#x2F;code&gt; 但却改变了 &lt;code&gt;CommitDate&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;我们可以通过 &lt;code&gt;git log --pretty=fuller&lt;&#x2F;code&gt; 命令查看：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit 6118ceb757f15b602eff73db5adccb293a2d6821 (HEAD -&amp;gt; master)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author:     st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AuthorDate: Sun Aug 15 21:51:39 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Commit:     st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CommitDate: Sun Aug 15 22:09:37 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    test commit 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit 3bf6a7f2d1d493e5d7c831f2bb2922796e8ca380&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author:     st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AuthorDate: Sun Aug 15 21:51:10 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Commit:     st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CommitDate: Sun Aug 15 22:07:22 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;commit de14f7451ede9600a3172ef99f652d231791b16f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Author:     st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AuthorDate: Sun Aug 15 21:50:34 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Commit:     st1020 &amp;lt;stone_1020@qq.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CommitDate: Sun Aug 15 21:50:34 2021 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Init Commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;或者通过 &lt;code&gt;git log --format=format:&quot;%h %ai %ci&quot;&lt;&#x2F;code&gt; 方便地比较 &lt;code&gt;AuthorDate&lt;&#x2F;code&gt; 和 &lt;code&gt;CommitDate&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;6118ceb 2021-08-15 21:51:39 +0800 2021-08-15 22:09:37 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3bf6a7f 2021-08-15 21:51:10 +0800 2021-08-15 22:07:22 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;de14f74 2021-08-15 21:50:34 +0800 2021-08-15 21:50:34 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;第一种方法&lt;&#x2F;strong&gt;是，我们可以在前面的提交步骤中，将命令修改为：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;GIT_COMMITTER_DATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;2021-08-15 21:51:10 +0800&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; commit&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --amend -m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;first commit&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这里的 &lt;code&gt;GIT_COMMITTER_DATE&lt;&#x2F;code&gt; 要设置成这次提交的 &lt;code&gt;AuthorDate&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;但是即使这样做，这次提交之后的提交的日期也会变化，得到的 &lt;code&gt;git log --format=format:&quot;%h %ai %ci&quot;&lt;&#x2F;code&gt; 会类似这样：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ff6edfd 2021-08-15 21:51:39 +0800 2021-08-15 22:31:06 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;699345c 2021-08-15 21:51:10 +0800 2021-08-15 21:51:10 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;de14f74 2021-08-15 21:50:34 +0800 2021-08-15 21:50:34 +0800&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;我们需要类似之前修改提交消息的方法，通过变基再去修改它的后一条消息的提交时间，提交时的命令使用：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;GIT_COMMITTER_DATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;2021-08-15 21:51:39 +0800&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; commit&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --amend --no-edit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;但如果要修改的消息的提交后有很多的提交，就需要反复执行上面的操作，非常麻烦，所以显然不是什么好办法。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;第二种方法&lt;&#x2F;strong&gt;就简单了很多，我们可以直接执行下面的命令即可将所有的提交的 &lt;code&gt;CommitDate&lt;&#x2F;code&gt; 修改为 &lt;code&gt;AuthorDate&lt;&#x2F;code&gt;。虽然 &lt;code&gt;filter-branch&lt;&#x2F;code&gt; 指令因为有很多的坑已经不推荐使用了，但像我们这种简单的操作还是没问题的。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; filter-branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-option&quot;&gt; --env-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;export GIT_COMMITTER_DATE=&amp;quot;$GIT_AUTHOR_DATE&amp;quot;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;参考资料&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#参考资料&quot; aria-label=&quot;Anchor link for: 参考资料&quot;&gt;参考资料&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;zh&#x2F;v2&#x2F;Git-%E5%B7%A5%E5%85%B7-%E9%87%8D%E5%86%99%E5%8E%86%E5%8F%B2&quot;&gt;Git - 重写历史&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;bfoz&#x2F;568898&quot;&gt;Force GIT_COMMITTER_DATE = GIT_AUTHOR_DATE&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-filter-branch&quot;&gt;Git - git-filter-branch Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;pretty-formats&quot;&gt;Git - pretty-formats Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-commit#_commit_information&quot;&gt;Git - git-commit Documentation - COMMIT INFORMATION&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Python 异步 IO 实用教程</title>
          <pubDate>Tue, 10 Aug 2021 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/python-asyncio-practical-tutorial/</link>
          <guid>https://st1020.com/posts/python-asyncio-practical-tutorial/</guid>
          <description xml:base="https://st1020.com/posts/python-asyncio-practical-tutorial/">&lt;p&gt;网络上大部分关于 Python 异步 IO 的教程受制于历史原因，往往都是从基于生成器的协程开始讲起的，但是，基于生成器的协程在 Python 3.8 版本中已经被弃用并且将在 Python 3.10 版本中被移除，从 Python 3.7 版本开始，异步 IO 库也发生了许多更改，添加了许多便于使用的高层级 API，但许多教程仍只涉及低层级 API，使初学者非常迷惑，觉得异步 IO 是一个很难使用的东西。为了尝试解决这些问题，我写了这篇教程，本篇仅涉及 Python 异步 IO 的基本概念和常用的非常简单的使用方法。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;异步_IO_与并发执行&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#异步_IO_与并发执行&quot; aria-label=&quot;Anchor link for: 异步_IO_与并发执行&quot;&gt;异步 IO 与并发执行&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;首先我们要明白的异步 IO 的本质是什么。&lt;&#x2F;p&gt;
&lt;p&gt;如果我们希望一个代码能够并发执行，有这几种方式，多进程，多线程和协程，它们在 Python 中分别对应了 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;zh-cn&#x2F;3&#x2F;library&#x2F;multiprocessing.html&quot;&gt;multiprocessing&lt;&#x2F;a&gt;，&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;zh-cn&#x2F;3&#x2F;library&#x2F;threading.html&quot;&gt;threading&lt;&#x2F;a&gt; 和 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;zh-cn&#x2F;3&#x2F;library&#x2F;asyncio.html&quot;&gt;asyncio&lt;&#x2F;a&gt; 库，在历史上，进程曾是大部分分时系统中程序运行的基本单位，而在现代操作系统中，进程是线程的容器。通俗的来讲，系统中运行的每一个程序都是一个进程，而每个进程有包含多个线程。每个线程都可以并行运行。&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid bg-inherit&quot;&gt;
  
graph TD;
    操作系统--&amp;gt;进程1;
    操作系统--&amp;gt;进程2;
    进程1--&amp;gt;线程1-1;
    进程1--&amp;gt;线程1-2;
    进程2--&amp;gt;线程2-1;

&lt;&#x2F;pre&gt;
&lt;p&gt;但是，实际上它们真的在并行运行吗？答案是不确定的，这取决于 CPU 的核心数，在“远古”时代，CPU 只有一个核心，所以在物理层面上，进程与线程并没有办法并行执行，于是操作系统用一个方法“骗过”了用户，通过快速地切换运行的进程来产生一种它们正在并行运行的错觉，所以如果你的电脑只有一个核心，并且你的程序只涉及单纯的 CPU 计算，那么多线程或多进程并不会提高运行的效率，反而可能会因为调度过程中的损耗而浪费部分 CPU 资源。但好在现在的 CPU 都有多个核心了，每个线程可以在独立的 CPU 上运行，所以多线程技术可以显著加快计算的速度。不过 Python 语言的最常用实现 CPython 由于 GIL 的存在，并不能很好的利用多线程，所以对于 CPU 密集型的程序需要使用多进程代替多线程。&lt;&#x2F;p&gt;
&lt;p&gt;实际上，计算机的 CPU 的运算速度远远大于网络或磁盘等 IO(输入&#x2F;输出)。在很多情境下，我们的程序都不是 CPU 密集型，而是 IO 密集型的，也就是频繁地访问网络或磁盘，而对于 CPU 计算消耗的时间不是很敏感。&lt;&#x2F;p&gt;
&lt;p&gt;传统的同步 IO，在 IO 操作过程中当前线程会被挂起，线程会等待 IO 操作完成在继续完成下面的代码。举一个例子，我们的程序要下载 100 个文件，如果我们使用同步 IO，程序向服务器发送一个网络请求，等 1 秒才能获得返回的信息，程序会等待返回信息后再继续进行下一个请求，100 个文件就需要至少 100 秒。所以我们必须使用多线程或多进程来并行下载，100 个线程同时发出网络请求，然后一起等 1 秒，一共只需要消耗 1 秒。&lt;&#x2F;p&gt;
&lt;p&gt;但是这里使用多线程或者多进程也许有些浪费，毕竟多线程会造成额外的系统资源开销，进程和线程数量也不能无限多下去，并且稍有不慎还会造成各种奇怪的 bug。或许我们可以试图从源头解决问题，那就是为什么 IO 操作一定要阻塞线程呢？可以想象这样的一种情况，程序发送一个网络请求，但不等待它返回结果就继续发送第二个网络请求，以此类推，发送请求是 CPU 操作，100 个请求可能只需要 1 毫秒就能完成，然后等待它们返回后再进行处理，同样，一共也只需要 1s 就能完成！这就是异步 IO，为了更好地发挥异步 IO 的威力，Python 引入了协程的概念。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;协程&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#协程&quot; aria-label=&quot;Anchor link for: 协程&quot;&gt;协程&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;协程 (Coroutines) 又叫纤程 (Fiber)。我们暂且将协程理解为一种特殊的子程序 (函数)。&lt;&#x2F;p&gt;
 &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-(--admonition-bg)&quot;
  style=&quot;--admonition-bg: rgba(0, 191, 165, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-(--admonition-bg) p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0px] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;tip.svg)&quot;
    &gt;
      tip
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Tip&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;实际上，上面的那句话是错误的，正确的是：子程序是协程的一种特例。&lt;&#x2F;p&gt;
&lt;p&gt;不过大多数语言都有子程序的概念，但不一定有协程的概念，在 Python 中函数也并不是协程的子类。&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;在 Python 中协程用 &lt;code&gt;async&#x2F;await&lt;&#x2F;code&gt; 语法进行声明：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; foo()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;end&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;hello&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; asyncio.sleep(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;asyncio.run(main())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;协程在声明时需要使用 &lt;code&gt;async def&lt;&#x2F;code&gt; 代替 &lt;code&gt;def&lt;&#x2F;code&gt;，而在调用时需要使用 &lt;code&gt;await&lt;&#x2F;code&gt; 来代替直接调用。不使用 &lt;code&gt;await&lt;&#x2F;code&gt; 直接调用一个协程并不会使它运行，只会得到一个协程对象。&lt;&#x2F;p&gt;
&lt;p&gt;在最外层则需要通过 &lt;code&gt;asyncio.run()&lt;&#x2F;code&gt; 来运行一个协程。&lt;&#x2F;p&gt;
&lt;p&gt;上面的程序的运行结果应该类似于：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    foo()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;end&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;hello&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    time.sleep(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;main()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;那么我们多写了那么多代码到底有什么用呢？虽然它们运行的效果是相同的，但是原理却并不相同，前者在调用 &lt;code&gt;await asyncio.sleep(1)&lt;&#x2F;code&gt; 时它实际上是挂起了当前的&lt;strong&gt;任务&lt;&#x2F;strong&gt;，以允许其他任务的运行，当然这里并没有其他的任务。后者的 &lt;code&gt;time.sleep(1)&lt;&#x2F;code&gt; 则是挂起 (阻塞) 了当前的&lt;strong&gt;线程&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;可等待对象&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#可等待对象&quot; aria-label=&quot;Anchor link for: 可等待对象&quot;&gt;可等待对象&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;上面我们提到了 &lt;code&gt;await&lt;&#x2F;code&gt; 语句用于运行协程，实际上它表示的是等待协程运行完毕，就像同步程序一样，所以上面的两个程序效果是相同。&lt;&#x2F;p&gt;
&lt;p&gt;在 Python 中所有可以被 &lt;code&gt;await&lt;&#x2F;code&gt; 语句等待的对象都叫做可等待对象，协程就是一种可等待对象。可等待对象有三种主要类型：协程 (coroutine)，任务 (Task) 和 Future。&lt;&#x2F;p&gt;
&lt;p&gt;其中 Future 是一种低层级的可等待对象，我们暂且不讨论，下面我们来了解一下任务。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;任务&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#任务&quot; aria-label=&quot;Anchor link for: 任务&quot;&gt;任务&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;在 Python 中任务被用来“并行的”调度协程。通过 &lt;code&gt;asyncio.create_task()&lt;&#x2F;code&gt; 函数来将协程封装为一个任务，并&lt;strong&gt;自动调度运行&lt;&#x2F;strong&gt;。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Running foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; asyncio.sleep(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;End foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Started at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    task_list = []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        task_list.append(asyncio.create_task(foo(i)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; task&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; task_list:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;        print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt; task)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Finished at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;asyncio.run(main())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;运行上述代码，会发现，程序只用了 1 秒就运行完成了。&lt;&#x2F;p&gt;
&lt;p&gt;我们来具体解读一下，首先在 &lt;code&gt;main()&lt;&#x2F;code&gt; 协程中先创建了 10 个任务，并储存在 &lt;code&gt;task_list&lt;&#x2F;code&gt; 列表中，然后再依次等待这些任务完成。&lt;&#x2F;p&gt;
&lt;p&gt;如果没有后面的等待的话，程序就会在那些任务还没有完成的情况下结束。如：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Running foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; asyncio.sleep(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;End foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Started at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        asyncio.create_task(foo(i))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Finished at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;asyncio.run(main())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;因为最外层是 &lt;code&gt;asyncio.run(main())&lt;&#x2F;code&gt; 当 &lt;code&gt;main()&lt;&#x2F;code&gt; 协程执行完毕程序就会结束，而不会管其他任务是否已经完成。&lt;&#x2F;p&gt;
&lt;p&gt;Python 还提供了一个函数用于替代上面的写法：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Running foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    await&lt;&#x2F;span&gt;&lt;span&gt; asyncio.sleep(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;End foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; i +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Started at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    coroutine_list = [foo(i)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    result =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; asyncio.gather(*coroutine_list)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(result)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Finished at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;asyncio.run(main())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt; &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-(--admonition-bg)&quot;
  style=&quot;--admonition-bg: rgba(0, 191, 165, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-(--admonition-bg) p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0px] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;tip.svg)&quot;
    &gt;
      tip
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Tip&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;&lt;code&gt;asyncio.gather()&lt;&#x2F;code&gt; 的内部实现和之前的代码并不相同，只是效果类似。&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;上面所有例子中的 &lt;code&gt;asyncio.sleep(1)&lt;&#x2F;code&gt; 都可以换成真实的 IO 操作，比如下面的使用 &lt;code&gt;httpx&lt;&#x2F;code&gt; 库获取网页的例子。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; asyncio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; httpx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; foo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;Running foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    async with&lt;&#x2F;span&gt;&lt;span&gt; httpx.AsyncClient()&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; client:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        r =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; await&lt;&#x2F;span&gt;&lt;span&gt; client.get(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;https:&#x2F;&#x2F;www.example.org&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;End foo &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;async def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Started at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    coroutine_list = [foo(i)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    result =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt; await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; asyncio.gather(*coroutine_list)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(result)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Finished at &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;time.strftime(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;%X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;asyncio.run(main())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;再次强调，协程不是多线程，上面的所有操作都是在一个线程中完成的，它之所以可以实现类似于并行执行的效果，是因为它没有等待 IO 操作完成，在上面的例子中程序发送了对 &lt;code&gt;https:&#x2F;&#x2F;www.example.org&#x2F;&lt;&#x2F;code&gt; 的第一次请求后，没有等待服务器响应，而是挂起了当前任务，于是第二个任务拿到了控制权，并进行了第二次网络请求，以此类推，这些发送请求全都发生在很短的时间内，然后当其中一个任务的请求有了回应，这个任务便会被唤醒，并继续执行剩下的代码。&lt;&#x2F;p&gt;
&lt;p&gt;你会发现，这种多个任务“并行”执行的方式很像之前提到的在只有一个 CPU 的情况下多线程的模式，使用协程的好处与多线程这种让系统去调度每个线程何时运行相比，我们可以自己决定何时切换任务，更加的高效和灵活，即只在发生需要耗费时间的 IO 操作时我们使用 &lt;code&gt;await&lt;&#x2F;code&gt; 等待它完成并挂起当前任务，切换至未处理的任务。&lt;&#x2F;p&gt;
&lt;p&gt;我们可以用下图清晰地表示使用多线程和协程任务进行并发处理的不同：&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid bg-inherit&quot;&gt;
  
gantt
    dateFormat  DD
    axisFormat  %d
    todayMarker off
    title 协程任务
    section Task 1
    网络请求    :crit, done,   task11, 01, 1d
    等待响应    :      active, task12, after task11, 15d
    处理响应    :crit, done,   task13, after task12, 1d
    section Task 2
    网络请求    :crit, done,   task21, 02, 1d
    等待响应    :      active, task22, after task21, 15d
    处理响应    :crit, done,   task23, after task22, 1d
    section Task 3
    网络请求    :crit, done,   task31, 03, 1d
    等待响应    :      active, task32, after task31, 15d
    处理响应    :crit, done,   task33, after task32, 1d

&lt;&#x2F;pre&gt;
&lt;pre class=&quot;mermaid bg-inherit&quot;&gt;
  
gantt
    dateFormat  DD
    axisFormat  %d
    todayMarker off
    title 多线程&amp;#x2F;多进程（线程&amp;#x2F;进程数 &amp;lt; CPU 核心数）
    section Task 1
    网络请求    :crit, done,   task11, 01, 1d
    等待响应    :      active, task12, after task11, 15d
    处理响应    :crit, done,   task13, after task12, 1d
    section Task 2
    网络请求    :crit, done,   task21, 01, 1d
    等待响应    :      active, task22, after task21, 15d
    处理响应    :crit, done,   task23, after task22, 1d
    section Task 3
    网络请求    :crit, done,   task31, 01, 1d
    等待响应    :      active, task32, after task31, 15d
    处理响应    :crit, done,   task33, after task32, 1d

&lt;&#x2F;pre&gt;
&lt;p&gt;看上面的图，你可能觉得还是多线程效率更高些，但事实并非如此，首先，上面的图并非真实的比例，真实情况下，等待响应的时间会远远大于网络请求和处理响应的时间，上面的差距可以忽略不计。其次，上面的图有一个前提就是线程&#x2F;进程数小于 CPU 核心数，若大于的话也并不会进一步提高效率，往往并行 IO 操作数量都是大于用户的 CPU 核心数的。最后，切换进程是会耗费额外的资源的，相比之下，协程切换任务的消耗则要小一些。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;总结&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#总结&quot; aria-label=&quot;Anchor link for: 总结&quot;&gt;总结&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;同步 IO 和异步 IO&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;同步 IO 在进行 IO 操作时会阻塞当前进程，而异步 IO 则不阻塞。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;可等待对象&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid bg-inherit&quot;&gt;
  
    graph TD;
        可等待对象--&amp;gt;A[协程 coroutine];
        可等待对象--&amp;gt;B[任务 Task];
        可等待对象--&amp;gt;C[Future];
    
&lt;&#x2F;pre&gt;
&lt;p&gt;任务 (Task) 是由协程 (coroutine) 使用 &lt;code&gt;asyncio.create_task()&lt;&#x2F;code&gt; 函数封装而成的，用于并行调度协程。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;运行一个协程&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;asyncio.run()&lt;&#x2F;code&gt; 函数：用于运行最高级入口点，如 &lt;code&gt;main()&lt;&#x2F;code&gt; 协程。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;await&lt;&#x2F;code&gt; 语句：等待一个协程，等待这个协程返回结果后继续运行下面代码。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;asyncio.create_task()&lt;&#x2F;code&gt; 函数：将一个协程包装为一个任务并且并发地调度协程。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
 &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-(--admonition-bg)&quot;
  style=&quot;--admonition-bg: rgba(68, 138, 255, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-(--admonition-bg) p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0px] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;note.svg)&quot;
    &gt;
      note
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;如果你使用了异步 IO，请尽量在程序的所有地方都使用协程，网络请求等 IO 库也要使用支持异步 IO 的库，如 &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.aiohttp.org&#x2F;&quot;&gt;aiohttp&lt;&#x2F;a&gt;，&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.python-httpx.org&#x2F;&quot;&gt;httpx&lt;&#x2F;a&gt; 等。&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;参考&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#参考&quot; aria-label=&quot;Anchor link for: 参考&quot;&gt;参考&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;建议参考以下内容：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;zh-cn&#x2F;3&#x2F;library&#x2F;asyncio-task.html&quot;&gt;协程与任务 - Python 文档&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;zh-cn&#x2F;3&#x2F;library&#x2F;asyncio-sync.html&quot;&gt;同步原语 - Python 文档&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;zh-cn&#x2F;3&#x2F;library&#x2F;asyncio-eventloop.html&quot;&gt;事件循环 - Python 文档&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>C 语言小技巧</title>
          <pubDate>Thu, 03 Dec 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/c-lang-tips/</link>
          <guid>https://st1020.com/posts/c-lang-tips/</guid>
          <description xml:base="https://st1020.com/posts/c-lang-tips/">&lt;p&gt;C 语言有许多可以提高编程效率，简化代码，提高代码可读性的小技巧。这里列出几个小技巧及其应用，抛砖引玉，供大家参考。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;逗号运算符&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#逗号运算符&quot; aria-label=&quot;Anchor link for: 逗号运算符&quot;&gt;逗号运算符&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;C 语言提供了一种特殊的运算符——逗号运算符，又称顺序求值运算符，可以用它将两个表达式连接起来。&lt;&#x2F;p&gt;
&lt;p&gt;逗号表达式的一般形式如下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Exp1, Exp2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;其计算过程为：&lt;&#x2F;p&gt;
&lt;p&gt;先计算 &lt;code&gt;Exp1&lt;&#x2F;code&gt;，再计算 Exp2，然后将 &lt;code&gt;Exp2&lt;&#x2F;code&gt; 的返回值作为整个逗号表达式的值。&lt;&#x2F;p&gt;
&lt;p&gt;如 &lt;code&gt;1+1, 2+2&lt;&#x2F;code&gt;，这个表达式的值是 4。&lt;&#x2F;p&gt;
&lt;p&gt;需要注意，逗号运算符的优先级是所有运算符中最低的，比如：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;a =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;表示将变量 &lt;code&gt;a&lt;&#x2F;code&gt; 赋值为 &lt;code&gt;1+2&lt;&#x2F;code&gt;，然后计算 &lt;code&gt;3*4&lt;&#x2F;code&gt; 作为整个表达式的值，但这个值并没有被使用。&lt;&#x2F;p&gt;
&lt;p&gt;所以，这个表达式有什么用呢？&lt;&#x2F;p&gt;
&lt;p&gt;可以看以下几个例子：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; n;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scanf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;n), n) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, n);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;如果不用逗号表达式，上述代码就需要写成：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; n =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (n) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        scanf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;n);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, n);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;还有：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; n;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    scanf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;n);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; i =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, j = n; i &amp;lt; j; ++i, --j) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d %d %d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, n, i, j);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;如果不用逗号表达式，上述代码就需要写成：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; n;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    scanf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, &amp;amp;n);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; i =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;, j = n; i &amp;lt; j; ++i) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d %d %d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, n, i, j);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        --j;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;多了一行……好吧，实际上都没有多多少代码，但能少一行是一行嘛，并且，这样写代码的可读性提高了不少。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;数组的部分初始化&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#数组的部分初始化&quot; aria-label=&quot;Anchor link for: 数组的部分初始化&quot;&gt;数组的部分初始化&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;当我们声明一个数组并对其进行初始化时，我们可以仅对其部分进行初始化，如：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = {[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;]=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;]=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;]=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr2&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; = {[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;9&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;] =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;19&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;] =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 20&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;29&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;] =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 30&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;上面的例子很简单，应该没有什么可说的，这也算是 C 语言的一个很少有人知道的一个小特性吧。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;C_语言的预处理器&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#C_语言的预处理器&quot; aria-label=&quot;Anchor link for: C_语言的预处理器&quot;&gt;C 语言的预处理器&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;C 语言的预处理器不是编译器的组成部分，而是编译过程中一个单独的步骤。实际上，我们可以把它理解为一个在开始编译源码之前的一个文本替换工具。最常用的预处理指令就是 &lt;code&gt;#include&lt;&#x2F;code&gt;，用于包含另一个源码文件，当我们在程序开头加上下面这行时，&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;预处理器就会在程序开始的地方引入 &lt;code&gt;stdio.h&lt;&#x2F;code&gt; 的全部内容，这样我们就可以使用这个头文件中包含的函数了。&lt;&#x2F;p&gt;
&lt;p&gt;另一个常用的预处理指令就是 &lt;code&gt;#define&lt;&#x2F;code&gt;，定义宏，如&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-preprocessor&quot;&gt; PI&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3.1415927&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;实际上就是将下面所有出现 &lt;code&gt;PI&lt;&#x2F;code&gt; 的地方替换为 &lt;code&gt;3.1415927&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;完整的预处理指令如下：&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;指令&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;描述&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#define&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;定义宏&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#include&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;包含一个源代码文件&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#undef&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;取消已定义的宏&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#ifdef&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;如果宏已经定义，则返回真&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#ifndef&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;如果宏没有定义，则返回真&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#if&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;如果给定条件为真，则编译下面代码&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#else&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;#if 的替代方案&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#elif&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;如果前面的 #if 给定条件不为真，当前条件为真，则编译下面代码&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#endif&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;结束一个 #if……#else 条件编译块&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#error&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;当遇到标准错误时，输出错误消息&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;#pragma&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;使用标准化方法，向编译器发布特殊的命令到编译器中&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;ANSI C 标准还定义了许多宏。在编程中我们可以使用这些宏，但是不能直接修改这些预定义的宏。&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;宏&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;描述&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;__DATE__&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;当前日期，一个以“MMM DD YYYY”格式表示的字符常量。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;__TIME__&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;当前时间，一个以“HH:MM:SS”格式表示的字符常量。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;__FILE__&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;这会包含当前文件名，一个字符串常量。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;__LINE__&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;这会包含当前行号，一个十进制常量。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;__STDC__&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;当编译器以 ANSI 标准编译时，则定义为 1。&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;例：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;File :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, __FILE__);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Date :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, __DATE__);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Time :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, __TIME__);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;Line :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, __LINE__);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;ANSI :&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, __STDC__);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;通过巧用预处理指令，我们可以有效的简化代码，比如，我们可以用预处理指令来定义求较大值、求较小值、转大写和求数组元素数的函数。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-preprocessor z-meta z-preprocessor&quot;&gt; MAX(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;) (((x)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;(y))&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (x)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (y))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-preprocessor z-meta z-preprocessor&quot;&gt; MIN(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;) (((x)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (y))&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (x)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (y))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-preprocessor z-meta z-preprocessor&quot;&gt; UPCASE(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;) (((c)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;a&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (c)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;z&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; ((c)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit z-constant z-numeric&quot;&gt; 0x20&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt; (c))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-preprocessor z-meta z-preprocessor&quot;&gt; ARR_SIZE(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor z-keyword z-operator z-sizeof&quot;&gt;)  (sizeof((a))&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-sizeof z-meta z-preprocessor&quot;&gt;sizeof((&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-preprocessor&quot;&gt;])))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</description>
      </item>
      <item>
          <title>Python 实现的 Brainfuck 语言解析器</title>
          <pubDate>Mon, 14 Sep 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/a-brainfuck-language-interpreter-implemented-in-python/</link>
          <guid>https://st1020.com/posts/a-brainfuck-language-interpreter-implemented-in-python/</guid>
          <description xml:base="https://st1020.com/posts/a-brainfuck-language-interpreter-implemented-in-python/">&lt;h2 id=&quot;BrainFuck&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#BrainFuck&quot; aria-label=&quot;Anchor link for: BrainFuck&quot;&gt;BrainFuck&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;BrainFuck 语言是一种深奥的编程语言 (Esoteric programming language，Esolang)，由 Urban Müller 于 1993 年创造。目的是为了创造一个简单的、最小的、符合图灵完全的编程语言。正如它的名字，BrainFuck 因为对人类极度不友好而广为人知。但是作为一种图灵完备的编程语言，理论上任何其他编程语言能够实现的程序都可以由 BrainFuck 实现。&lt;&#x2F;p&gt;</description>
      </item>
      <item>
          <title>关于停机问题与自指性悖论</title>
          <pubDate>Tue, 21 Jul 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/halting-problem-and-self-reference-paradox/</link>
          <guid>https://st1020.com/posts/halting-problem-and-self-reference-paradox/</guid>
          <description xml:base="https://st1020.com/posts/halting-problem-and-self-reference-paradox/">&lt;p&gt;停机问题是是逻辑数学中可计算性理论的一个很经典的问题，该问题内容为：是否存在一个程序 H，对于任意输入的程序 P，能够判断 P 会在有限时间内结束或者死循环。&lt;&#x2F;p&gt;
&lt;p&gt;答案是否定的，证明如下：&lt;&#x2F;p&gt;
&lt;p&gt;假设停机问题有解，即存在一个程序能够判断程序 P 在输入 I 的情况下是否可停机 (即是否会进入死循环)。我们假设该程序为函数 &lt;code&gt;H&lt;&#x2F;code&gt;，即：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; H&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; I&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;若函数 &lt;code&gt;P&lt;&#x2F;code&gt; 在输入 &lt;code&gt;I&lt;&#x2F;code&gt; 时不会进入死循环，则 &lt;code&gt;H&lt;&#x2F;code&gt; 返回 &lt;code&gt;True&lt;&#x2F;code&gt;，否则返回 &lt;code&gt;False&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;然后我们定义另一个函数 &lt;code&gt;U&lt;&#x2F;code&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; H(P, P):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        while&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;            pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;    else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;也就是说当 &lt;code&gt;H&lt;&#x2F;code&gt; 判断 &lt;code&gt;P(P)&lt;&#x2F;code&gt; 会停机时，&lt;code&gt;U&lt;&#x2F;code&gt; 就进入死循环，否则正常返回。&lt;&#x2F;p&gt;
&lt;p&gt;那么，当 &lt;code&gt;U&lt;&#x2F;code&gt; 输入 &lt;code&gt;U&lt;&#x2F;code&gt;，也就是 &lt;code&gt;U(U)&lt;&#x2F;code&gt; 会不会停机呢？既然 &lt;code&gt;H&lt;&#x2F;code&gt; 能够判断任何程序是否会停机，那么应该也能回答这个问题，也就是：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;H(U, U)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;那么问题就来了，如果 &lt;code&gt;H&lt;&#x2F;code&gt; 认为 &lt;code&gt;U(U)&lt;&#x2F;code&gt; 会停机，即 &lt;code&gt;H(U, U)&lt;&#x2F;code&gt; 返回 &lt;code&gt;True&lt;&#x2F;code&gt;，那么实际上 &lt;code&gt;U(U)&lt;&#x2F;code&gt; 就会进入死循环，并不会停机。如果 &lt;code&gt;H&lt;&#x2F;code&gt; 认为 &lt;code&gt;U(U)&lt;&#x2F;code&gt; 不会停机，即 &lt;code&gt;H(U, U)&lt;&#x2F;code&gt; 返回 &lt;code&gt;False&lt;&#x2F;code&gt;，那么实际上 &lt;code&gt;U(U)&lt;&#x2F;code&gt; 就会进入死循环，并不会停机。这就推出了矛盾，也就是说 &lt;code&gt;H&lt;&#x2F;code&gt; 并不能永远给出停机问题的准确答案。&lt;&#x2F;p&gt;
&lt;p&gt;由此可以证明，不存在能够判断任意程序在特定输入下是否会在有限时间内停机的程序，停机问题无解。&lt;&#x2F;p&gt;
&lt;p&gt;与此类似的还有“理发师悖论”：一位理发师的原则是当且仅当一个人不为自己理发时他为其理发，那么这位理发师能为自己理发吗？这里“理发师悖论”实际上是罗素悖论的一个比喻，也即：对于集合 $A=\{x \mid x \notin A\}$ 判断 $A \in A$ 是否成立。&lt;&#x2F;p&gt;
&lt;p&gt;这个悖论的根本性问题为集合的自指，所以我们只要拒绝集合的自指即可解决该问题，也就是认为不存在像 $A=\{x \mid x \notin A\}$ 的集合。&lt;&#x2F;p&gt;
&lt;p&gt;同样，对于停机问题我们也可以有类似的解释，产生悖论的原因正是这个能够判断其他程序是否能停机的程序也是一个程序，那么当它判断涉及自己的程序时就可能会产生悖论，最终证明一个程序不可能判断其他所有程序是否停机。&lt;&#x2F;p&gt;
&lt;p&gt;类似的还有“全能悖论”：上帝全知全能，那么祂能创造一个自己搬不起来的石头吗？如果能，那么说明其在力量方面并非全能，如果不能，说明其在创造方面并非全能。这同样是因为自指导致的悖论，当我们将上帝的全能性作用于其本身时就会导致悖论，从而说明全能的上帝是不存在的。&lt;&#x2F;p&gt;
&lt;p&gt;此外还有一个最常见的悖论——“说谎者悖论”：“这个语句为假”是否为真。对此有许多解释，比如曾有人提出应拒绝与排中律有关的二值原理，也就是拒绝“所有语句要么为真要么为假”的主张，认为其非真非假。但是，对于另一个问题：“这个语句不为真”是否为真，也同样无法解决，类似的主张如认为其又真又假也存在无法回答的问题，即”这个语句只为假“是否为真。对此的解决比较好的有 Arthur Prior 提出的观点：语句都包含对自己真值的隐含断言，即“一加一等于二”隐含了“一加一等于二为真”的真值断言，任何一句话“A”都可以改写为“A 且这句话为真”，那么同样，“这句话为假”等价与“这句话为真且这句话为假”，而这句话本身就包含了矛盾，就像“这个东西是苹果且这个东西不是苹果”一样，所以说谎者悖论实质上是由一个一开始就含有矛盾的假语句而推导出的另一个矛盾，并不是一个悖论。不过我认为这实质上是从语言上回避了这个这个问题，是因为自然语言的不严谨导致的，并无法用来解释罗素悖论等其他涉及自指的悖论。&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Powered by Hugo</title>
          <pubDate>Wed, 15 Jul 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/powered-by-hugo/</link>
          <guid>https://st1020.com/posts/powered-by-hugo/</guid>
          <description xml:base="https://st1020.com/posts/powered-by-hugo/">&lt;p&gt;由于各种原因，已经很久没有更新博客了...鸽子真快乐。总之，从今天起，本博客正式迁移至 Hugo！&lt;&#x2F;p&gt;
&lt;p&gt;其实在开始建立这个博客的时候我就已经想要使用 Hugo 作为静态博客生成器了，只是一直没有找到满意的主题，所以就搁置了下来，直到最近我终于找到了一个可以说非常完美的主题：&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dillonzq&#x2F;LoveIt&quot;&gt;LoveIt&lt;&#x2F;a&gt;，于是果断将博客迁移到了 Hugo 上了。&lt;&#x2F;p&gt;
&lt;p&gt;Hugo 在很多方面都要比 Hexo 更加方便，首先，Hugo 的环境配置十分简单，只需要一个 Go 语言编译的可执行文件即可执行，而 Hexo 则需要安装 Node.js 环境。其次，Hugo 的运行速度更快，相比于 Hexo 最短也要几秒到几十秒的构建时间，Hugo 只需要几百毫秒即可完成构建。其三，Hugo 的目录配置更加合理，Hugo 的没有像 Hexo 那样的使用 node_modules 管理插件，主题目录与站点目录结构相同，文章与静态文件分开存放，不区分站点与主题配置文件，使用文件系统结构来组织文章等等。&lt;&#x2F;p&gt;
&lt;p&gt;当然，Hexo 也并非一无是处，其主题资源相较 Hugo 要更加丰富，用户数量也更多。但是综合考虑我还是选择了 Hugo。&lt;&#x2F;p&gt;
&lt;p&gt;最后，再见 Hexo，你好 Hugo！&lt;&#x2F;p&gt;
&lt;p&gt;Farewell Hexo, Hello Hugo!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Arch Linux 安装记录</title>
          <pubDate>Wed, 08 Apr 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/arch-install/</link>
          <guid>https://st1020.com/posts/arch-install/</guid>
          <description xml:base="https://st1020.com/posts/arch-install/">&lt;p&gt;前几天打开好久没用的电脑，一更新把之前图省事装的 Manjaro 滚挂了，也懒得去解决，于是决定安装一个 Arch Linux，在这里记录一下安装过程。&lt;&#x2F;p&gt;
&lt;p&gt;本人是非常喜欢 Arch Linux 的，因为其高度自定义化、遵循 KISS 原则 (Keep It Simple, Stupid)、滚动更新并且以用户为中心。但是，由于其理念为以用户为中心但不是用户友好，所以对很多人来说安装 Arch 还是有一定难度的。读者也可以参考本篇教程从零开始安装一个属于自己的 Arch。&lt;&#x2F;p&gt;</description>
      </item>
      <item>
          <title>Hexo-NexT 主题个性化定制</title>
          <pubDate>Wed, 08 Apr 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/hexo-next-theme-customization/</link>
          <guid>https://st1020.com/posts/hexo-next-theme-customization/</guid>
          <description xml:base="https://st1020.com/posts/hexo-next-theme-customization/">&lt;p&gt;本篇文章主要谈一谈我是如何个性化定制 Hexo 的 NexT 主题的。&lt;&#x2F;p&gt;
&lt;p&gt;Hexo 的主题有许多种，其中最知名的莫过于 NexT 主题了，我也选择了这款主题作为我的博客的默认主题。实际上，我本来是打算使用 Hugo 来搭建博客的，但苦于没有找到喜欢的主题，只好作罢。如果未来找到了足够好的主题，我应该会将博客迁移到 Hugo 上吧。本篇也是作为我折腾 Hexo 的一篇记录。&lt;&#x2F;p&gt;</description>
      </item>
      <item>
          <title>Hello World</title>
          <pubDate>Mon, 06 Apr 2020 00:00:00 +0000</pubDate>
          <author>st1020</author>
          <link>https://st1020.com/posts/hello-world/</link>
          <guid>https://st1020.com/posts/hello-world/</guid>
          <description xml:base="https://st1020.com/posts/hello-world/">&lt;h2 id=&quot;Hello_World!&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#Hello_World!&quot; aria-label=&quot;Anchor link for: Hello_World!&quot;&gt;Hello World!&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;今天这个博客正式建立了！&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
