Try   HackMD

リダイレクションの構文 - シェルもどきをgoで自作する #7

おさらい

これまで

シェルもどき「oreshell」を自作している。
現状のoreshellはリダイレクションを行うとエラーになるのでリダイレクションできるように修正する。
前回はリダイレクションをどこまで対応するかを決めた。

今回は対応するリダイレクションの「構文」を決める。

え、構文ってなに?

構文は、正しく構造化されたコードを構成する文字の必要な組み合わせと順序を指定します。
MDN Web Docs用語集

構文 = シンタックス

シンタックスとは、統語論、構文(論)という意味の英単語で、ITの分野ではプログラミング言語などの人工言語の仕様として定められた文法や表記法、構文規則などのルールを指す。
処理系が正しいコードとして解釈可能な文字や記号の並べ方、単語や文の組み合わせ方などの規則の総体である。
プログラミング言語の場合、例えば「複数の文を並べる場合はセミコロンで区切る」「変数は使用前に型と変数名を宣言する」などがシンタックスにあたる。
IT用語辞典

今回の場合は、シェル(oreshell)が解釈可能な単語や文の組み合わせ方の規則を表す。
(厳密には解釈可能な文字や記号の並べ方も定義する必要があるが今回は記述をサボっている。)

構文定義の表現方法

単語や文の組み合わせ方を日本語でダラダラと書くと曖昧さを生むことがあるので、今回はBNF/EBNFを使って定義する。

BNF、EBNF

バッカス・ナウア記法(英: Backus–Naur form)とは、文脈自由文法を定義するのに用いられるメタ言語のことで、一般にBNFやBN記法と略される。
現在はこのBNFを拡張したEBNF (Extended BNF) が一般的に使われている。
EBNFでは正規表現を用いてより簡単に記述でき、プロトコル規定言語であるASN.1や、XMLの構文定義にも利用されている。
パーサジェネレータを使用して構文解析器を生成する際に、構文を定義するためにも使う。
wikipedia

ソフトウェア開発で構文を定義するときは、BNFやEBNFやそれ以外のBNF拡張を使う事が多い。
(余談:ANTLRも文法の記述方法は、EBNFに似た形式となっている。)

railroad diagram

railroad diagram (syntax diagram)

Syntax diagrams (or railroad diagrams) are a way to represent a context-free grammar. They represent a graphical alternative to Backus–Naur form, EBNF, Augmented Backus–Naur form, and other text-based grammars as metalanguages.
BNF is text-based, and used by compiler writers and parser generators. Railroad diagrams are visual, and may be more readily understood by laypeople, sometimes incorporated into graphic design.
構文図 (または構文図) は、文脈自由文法を表す方法です。これらは、メタ言語として、Backus–Naur形式、EBNF、Augmented Backus–Naur形式、およびその他のテキストベースの文法のグラフィカルな代替を表します。
BNFはテキストベースであり、コンパイラライタやパーサジェネレータで使用されます。鉄道図面は視覚的なものであり、素人でも容易に理解することができ、時にはグラフィックデザインに組み込まれる。
wikipedia
みらい翻訳

railroad diagramはBNF/EBNFの記述を鉄道の線路に似せた図で表現したもの。

以下のサイトでEBNFからrailroad diagramを作成することができる。
Railroad Diagram Generator

リダイレクション対応前の構文

リダイレクション対応前は、コマンドの後に続けてコマンド引数群のみ指定できる。
ざっくり日本語で説明すると以下の通り。

コマンド名 引数1 引数2 ... 引数n

これを以降でBNFとEBNFとrailroad diagramで表す。
(同じ内容をBNFやEBNFで記述する方法はこれ以外にも幾通りもあるが今回のoreshellリダイレクション対応はこの方法で表す。)

コマンド部分の構文

BNF:

simple_command :: cmd_name
                | cmd_name word_list

EBNF:

simple_command ::= cmd_name word_list?

railroad diagram:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

「コマンド引数群(word_list)を指定することもできるし、指定しないこともできる」ということを表している。

railroad diagramの説明。
左末端が始発駅、右末端が終着駅を表している。
分岐した線路を描くことでが「選択」を表している。

あわせて、BNFとEBNFにおける「選択」の表現方法の違いについてもよく見てみるとおもしろい。

コマンド引数群部分(word_list)の構文

BNF:

word_list ::           word
           | word_list word

EBNF:

word_list ::= word+

railroad diagram:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

「コマンド引数(word)は複数指定できる」ということを表している。

railroad diagramの説明。
ぐるぐるとループできるよう線路に描くことで「繰り返し(複数)」を表している。

あわせて、BNFとEBNFにおける「繰り返し」の表現方法の違いについてもよく見てみるとおもしろい。

全体の構文

全部くっつけると以下の通り。(BNFは省略)

EBNF:

simple_command_all ::= cmd_name (word+)?

railroad diagram:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

リダイレクション対応後の構文

リダイレクション対応後は、コマンドの後に続けてコマンド引数群とリダイレクション群を指定できる。
ざっくり日本語で説明すると以下の通り。

コマンド名 引数1 引数2 ... 引数n <リダイレクション1> <リダイレクション2> ... <リダイレクションn>

これを以降でBNFとEBNFとrailroad diagramで表す。

コマンド部分の構文

BNF:

simple_command :: cmd_name
                | cmd_name cmd_suffix

EBNF:

simple_command ::= cmd_name cmd_suffix?

railroad diagram:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

「コマンド引数/リダイレクション群(cmd_suffix)を指定することもできるし、指定しないこともできる」ということを表している。

コマンド引数/リダイレクション群部分(cmd_suffix)の構文

BNF:

cmd_suffix       ::            io_redirect
                  | cmd_suffix io_redirect
                  |            WORD
                  | cmd_suffix WORD

EBNF:

cmd_suffix ::= (word | io_redirect)+

「コマンド引数(WORD)とリダイレクション(io_redirect)は複数指定できる」ということを表している。

リダイレクション部分(io_redirect)の構文

BNF:

io_redirect      ::           io_file
                  | IO_NUMBER io_file

EBNF:

io_redirect ::= IO_NUMBER? io_file

railroad diagram:

IO_NUMBERはファイルディスクリプタ番号を表す。
「ファイルディスクリプタ番号を指定することもできるし、指定しないこともできる」ということを表している。

リダイレクション方向とファイル名部分(io_file)の構文

BNF:

io_file          :: '<'       filename
                 |  '>'       filename

EBNF:

io_file ::= ('<' | '>') filename

railroad diagram:

「リダイレクション方向として「>」または「<」を指定でき、そのあとファイル名を指定する」ということを表している。

全体の構文

全部くっつけると以下の通り。(BNFは省略)

EBNF:

simple_command ::= cmd_name ((word | (IO_NUMBER? ('<' | '>') filename))+)?

railroad diagram: