文や数式の構造を階層的な木で表したもの
構文木(syntax tree)とは、文や数式の構造を階層的な木の形で表したものです。演算子を上の方(根や枝)に、計算される数値を末端(葉)に置き、「どれを先に計算するか」という構造を一目で表します。
身近な例えで言うと、構文木は会社の組織図に似ています。社長(根)の下に部長がいて、その下に課員(葉)がいるように、上のノードが下のノードを「まとめる」関係になっています。数式 1 + 2 × 3 なら、× が 2 と 3 をまとめ、+ がその結果と 1 をまとめる、という階層になります。
上のツールで数式を選び▶ボタンを押すと、葉(数値・青)が先に現れ、演算子(オレンジ)が子をまとめながら木が下から組み上がっていく様子を確認できます。計算の順序が木の形そのものになっていることに注目してください。
木構造には専用の用語があります。
・根(root, ルート):一番上の親を持たないノード。式全体を代表する
・葉(leaf, リーフ):一番下の子を持たないノード。数式では数値そのもの
・内部ノード:根と葉の間にある、子を持つノード。数式では演算子
・親・子:上下に直接つながったノードの関係
階層構造が表すのは「優先順位」と「まとまり」です。木の下にあるノードほど先に計算されます。これは演算子の優先順位(× ÷ は + − より先)やカッコの効果を、木の形だけで正しく表現できるということです。
たとえば 1 + 2 × 3 と (1 + 2) × 3 は同じ数字を使っていますが、木の形が変わります。前者は × が下、後者は + が下に来るため、計算順が変わり結果も 7 と 9 で異なります。カッコの意味が木の形に吸収されるのがポイントです。
構文木は、構文解析(=文字列が文法に従っているか調べ、構造を明らかにする処理)の成果物です。コンパイラはソースコードを受け取ると、まず構文解析を行い、その結果として構文木を作ります。
処理の流れは「文字列 → 構文解析 → 構文木 → 評価(計算・コード生成)」という順になります。構文木ができてしまえば、あとは木をたどるだけで計算したりプログラムに翻訳したりできます。木の形が計算の順序を保証してくれるからです。
ちなみに、木のたどり方(走査)によって元の式をいろいろな記法で表せます。この数式(( 1 + 2 ) × 3)では次のようになります。
・中順(左→根→右):1 + 2 * 3(中置記法に近い)
・後順(左→右→根):1 2 + 3 *(後置記法=逆ポーランド記法)
・前順(根→左→右):* + 1 2 3(前置記法)
このように、後順走査が後置記法(逆ポーランド記法)に対応します。