1. 程式人生 > 其它 >LaTeX繪圖備忘之編譯原理相關例圖繪製一

LaTeX繪圖備忘之編譯原理相關例圖繪製一

此文是為了方便以後繪製類似圖形而寫。本示例中使用了tikz巨集包來繪製主體圖形,使用qtree巨集包繪製語法樹。

示例圖選自《編譯原理》第2版第1章“圖1-7 一個賦值語句的翻譯”。下面是完整的示例程式碼:

% 部落格園,繁星間漫步,陸巍的部落格
\documentclass{article}

% 注意巨集包順序,有可能會報錯
\usepackage{ctex}% 中文支援
\usepackage{geometry}% 用於頁面設定
\usepackage{booktabs}% 增強表格功能
\usepackage{colortbl}% 表格顏色
\usepackage{multirow}% 支援表格的多行合併
\usepackage{longtable}% 支援長表格跨頁
\usepackage{tikz}% 繪圖
\usepackage{qtree}% 繪製語法分析樹

% 載入tikz中的各種功能庫
\usetikzlibrary{arrows.meta, chains, graphs}

% 設定為A4紙,邊距適中模式(參考永中office)
\geometry{
  a4paper,
  left = 19.1mm,
  right = 19.1mm,
  top = 25.4mm,
  bottom = 25.4mm
}

% 定義表格對齊方式
\newcolumntype{L}[1]{>{\raggedright\arraybackslash}p{#1}}
\newcolumntype{C}[1]{>{\centering\arraybackslash}p{#1}}
\newcolumntype{R}[1]{>{\raggedleft\arraybackslash}p{#1}}


% tikz圖形樣式定義
% rectangle
\tikzset{
  rect1/.style = {
    shape = rectangle,
    draw = black,
    thick,
    align = center,
    minimum height = 5ex,
  }
}


% ------------------ 開始 -------------------
\begin{document}
\small
\begin{center}
  \begin{tikzpicture}[
      start chain = going below,
      node distance = 2.5ex,
      rect1,
      every node/.style = {
        text width = 14em,
        minimum height = 3ex
      },
      >={Latex[length = 2mm, width = 1mm]},
    ]
    \node[on chain](a){position = initial + rate * 60};
    \node[draw, on chain](b){詞法分析器};
    \node[on chain, text width = 18em](c){
      〈id, 1〉 〈=〉 〈id, 2〉 〈+〉 〈id, 3〉 〈*〉 〈60〉
    };
    \node[draw, on chain](d){語法分析器};
    \node[on chain](e){
      \Tree [.=
        {〈id, 1〉} [.+
          {〈id, 2〉} [.*
            {〈id, 3〉} 60 ]
        ]
      ]
    };
    \node[draw, on chain](f){語義分析器};
    \node[on chain, text width = 18em](g){
      \Tree [.=
        {〈id, 1〉} [.+
          {〈id, 2〉} [.*
            {〈id, 3〉} [.inttofloat 60 ]
          ]
        ]
      ]
    };
    \node[draw, on chain](h){中間程式碼生成器};
    \node[on chain, align = left, text width = 10em](i){
      t1 = inttofloat(60)\\
      t2 = id3 * t1\\
      t3 = id3 + t2\\
      id1 = t3
    };
    \node[draw, on chain](j){程式碼優化器};
    \node[on chain, align = left, text width = 10em](k){
      t1 = id3 * 60.0\\
      id1 = id2 + t1
    };
    \node[draw, on chain](l){程式碼生成器};
    \node[on chain](m){
      \begin{tabular}{p{3em}p{10em}}
        LDF & R2, id3\\
        MULF & R2, R2, \#60.0\\
        LDF & R1, id2\\
        ADDF & R1, R1, R2\\
        STF & id1, R1
      \end{tabular}
    };
    \node[left = 10em of f, text width = 9em]{
      \begin{tabular}{p{1em}|p{4em}|C{2em}|}
        \cline{2-3}
        1 & position & ...\\
        \cline{2-3}
        2 & initial & ...\\
        \cline{2-3}
        3 & rate & ...\\
        \cline{2-3}
        & &\\
        \cline{2-3}
        \multicolumn{3}{c}{}\\
        \multicolumn{3}{c}{符號表}
      \end{tabular}
    };
    \graph [use existing nodes]{
      a->b->c->d->e->f->g->h->i->j->k->l->m;
    };
  \end{tikzpicture}

  \normalsize 圖1-7\quad 一個賦值語句的翻譯
\end{center}

\end{document}

生成效果如下:

注意事項:
1、注意其中使用的tikz中的三個庫:arrows.meta、chains與graphs。其中使用graphs庫後,可以在編寫箭頭時更為簡潔。例如,在未使用graphs庫之前,編寫箭頭時是使用\draw命令來逐個實現,使用graphs庫後,就可以像示例程式碼中那樣一連串的寫出;
2、注意chains庫的使用方法;
3、注意箭頭形狀的定義方法:

>={Latex[length = 2mm, width = 1mm]}

4、注意繪製語法樹時經常會被遺忘的空格:

\Tree [.=
  {〈id, 1〉} [.+
    {〈id, 2〉} [.*
      {〈id, 3〉} 60 ]
    ]
  ]

程式碼中60與]之間一定要有空格。
5、注意繪製左側“符號表”時的表格相關命令:\cline、\multicolumn。靈活使用這些命令可以繪製複雜的表格。