Chapter 2. The Big Picture^3

2.3 You Can't Put Too Much Water into a Nuclear Reactor

曖昧な句、文は複数の解釈を持つもの。言い換えると、複数の文法構造に当てはまる語ということ。自然言語では曖昧さは面白いが、コンピュータベースの言語アプリでは問題を引き起こす。句を解釈あるいは変換するため、プログラムは一意に意味を特定する必要がある。これは入力句を正確に一意に照合できる曖昧でない文法を、生成する構文解析器へ提供する必要がある、ということを意味する。

いくつかの曖昧な文法はわかりやすい。

stat : ID '=' expr ';'	// match an assigment; can match "f();"
     | ID '=' expr ';'	// oops! an exact duplicate of previous alternative
     :
expr : INT ;

しかし、ほとんど場合、曖昧さは巧妙になる。以下の文法は、規則statの両方の構文候補経由で、関数呼び出しにマッチできる。

stat : expr ';'		// expression statement
     | ID '(' ')' ';'	// function call statement
     ;
expr : ID '(' ')'
     | INT
     ;

このため、たいていの言語開発者は曖昧さがないよう構文を設計する、曖昧な文法はプログラムバグに類似している(同質である)。私たちは文法を、各入力句に対する単一の選択肢を構文解析器へを与えるものと認識する必要がある。もし構文解析器が曖昧な句を検出したら、構文解析器は成功しそうな構文候補を1つ選ぶ必要がある。ANTLRは、決定に関与する最初の構文候補を選ぶことで、曖昧さを解決する。この場合構文解析器は、stat→expr→f()の解釈を選択する。

曖昧さは構文解析器同様、字句解析器でも起こる。しかしANTLRは、規則が自然に振る舞ってそれを解決する。ANTLRは字句的な曖昧さを、入力文字列と文法で最初に指定された規則をマッチングすることで解決する。これがどのように働くか、多くの言語で共通な曖昧さである、キーワードと識別子の規則で見てみよう。キーワードbigin(後ろに文字が続かない)は、少なくとも字句的には識別子でもあるため、字句解析器はb-e-g-i-nを両方の規則にマッチできる。

BEGIN : 'begin' ;	// match b-e-g-i-n sequence; ambiguity resolve to BEGIN
ID    : [a-z]+ ;	// match one or more of any lowercase letter

字句解析器は各トークンを最長にできる文字列とマッチさせようとすることに注意。これはbeginnerは規則IDにだけマッチすることを意味する。字句解析器はbeginnerをBEGINにID(nerがマッチング)が続いたものとしてマッチさせない。

しばしば言語の構文は明らかに曖昧で、どんなに文法を再編成しても変えられない。たとえば、自然な文法の算術式は、1+2*3のような数式を2通りに解釈できる;左から右へ操作を実行する(Smalltalkがするように)、優先順位に基づく(たいていの言語がするように)。

由緒あるC言語は、識別子がどのように定義されているかというような文脈情報を使って解決できる別な種類の曖昧さを見せる。i*jというコードの断片を考えてみる、構文的には式のように見えるが、その意味するところは、iが型名なのか変数なのかに依存する。もしiが型名なら、(式ではなく)i型のポインタ変数jの宣言である。

from The Definitive ANTLR4 Reference by Terence Parr