ほとんどのプログラミング言語は、数字で始まる識別子を宣言できないように設計されているようです。理由を知りたいだけです。私はすでにウェブを検索しましたが、満足のいく説明を見つけることができませんでした。
ほとんどのプログラミング言語は、数字で始まる識別子を宣言できないように設計されているようです。理由を知りたいだけです。私はすでにウェブを検索しましたが、満足のいく説明を見つけることができませんでした。
回答:
C / C ++では、文字の後に続く数字は数値定数と見なされ、その後に続く文字列は定数の型を修飾します。したがって、たとえば(これらはVC ++であり、それらがどの程度標準であるかはわかりません):
したがって、a)Danielが言ったようにレクサーにとっては簡単ですが、b)0yは変数かもしれませんが0uは決してないので、明示的に区別します。さらに、「i64」などのその他の修飾子が「l」または「u」よりもずっと後に追加され、必要に応じて追加するオプションを開いたままにしておきたいと考えています。
レクサーを実装する人々の利便性。(いいえ、真剣に、それについてです。さまざまな言語には他の理由がありますが、最終的にはそれが原因です。)
0flu
リテラルであり0glu
ローカル識別子である場合、それは非常に厄介です。
int 0u = 5; unsigned int x = 0u;
あなたは(おそらくX == 0またはX == 5のいずれか)。このコードの解釈を定義することを選択しかし、人々は混乱しようとしているがあいまいさのため。この方法でコンパイラを実装することは簡単であったとしても、優れた設計者はおそらくそれを行わないでしょう。
次の2つのケースを考慮してください。
識別子が数字で始まると仮定しましょう。
したがって、次のようなステートメントは有効です(識別子には1文字以上を含めることができるため)。
int 3;
上記の変数をプログラムで使用しようとすると、コンパイラーのあいまいさが生じます。
int 3、a;
3 = 5;
a = 3;
ステートメントでa=3
は、3の役割は何ですか(値5の変数ですか、それとも数値3です)?
上記の例とは対照的に、言語は、数字で始まる識別子を実際に許可する一方で、数字を識別子として使用することをまだ許可しないと仮定します。これにより、次の問題が発生する可能性があります。
変数が1つ以上の文字で構成できると言う変数に関する言語規則は、次のような複雑な規則に再定義する必要があります。数字(など)で始まる場合、1文字の長さにすることはできません。
コンパイラは、すべての数字(333など)と有効なアルファベットの接尾辞(34Lなど)が変数名として使用されている場合、エラーをチェックして報告する必要があります。変数を宣言せずにオンザフライで使用できるPythonやJSなどの緩やかに型付けされた言語if (33==5)
では、すべての数字に関連する特殊なケースをチェックすることさえできない場合があります。たとえば、33はユーザーが宣言した誤った未宣言変数です ただし、コンパイラはこれを識別してエラーを報告することはできません。
この制限を行うと、プログラマーは識別子名として数字を使用できなくなります。
int char = float
ことが起こるか想像できますか?
int
は識別子ではなくキーワードをどのように認識していますか?まあ、int
数字の語彙素が持つように、より高い優先順位を持っています。
int 3,a; 3=5; a=3;
てください。ステートメントa = 3で、3は識別子または数字として解釈されますか?これによりあいまいさが生じます。それが明確であることを願っています。
ほとんどの場合、これはコンパイラの作成者と解析の効率を容易にすることとは関係ありませんが、読みやすく明確なコードを促進する構文の設計と関係があります。
その言語設計者は、数字1のような数値リテラルを単なるプレーン1として書くことができたらいいと思っていました。
ナンバーワンのためのnumbericリテラルは次のようにエンコードされたように、数値リテラルは、たとえば、tildasためのいくつかの方法で引用された言語の構文設計することは十分可能だろう〜1〜と何もないキーワードや変数名として扱われていた引用符で囲まれていないが。
したがって、次のようなステートメントをコーディングできます。
1 = ~2~
two = 1 * ~2~
だけでなく:
2 = ~3~
six = 2 + 2
どのような構文を選択しても、あいまいでコードに従うのは避けられません。
C言語と、Cに由来するほとんどの「中括弧」言語も、プログラマが8進および16進リテラルを直接コーディングできるようにし、これが重要な場合はリテラルのタイプを指定することをお勧めします。そう
010 // Octal 10 = 8;
0x10 // Hexadecimal 10 = 16;
5l // long integer with decimal value 5
2.0d // double float with value 2
そのため、変数名が数字で始まり、その後に少なくとも1文字を含む数字と文字の組み合わせが続く場合でも、特定のグループが変数名を形成するか、数値リテラルを形成するかを決定する問題をプログラマーに提示します。
2lll = 22 // OK
2ll = 2 // compiler error
このようなあいまいさは、プログラムを書いたり読んだりするのに役立ちません。
密接に関連する実世界の例として、デザイナーがキーワードを変数名として使用できることをお勧めすると考えているPL / 1言語を見ることができます。
IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;
IF IF THEN ELSE = IF; ELSE THEN = ELSE;
DO WHILE (WHILE = DO); END = WHILE + DO; END;
コンパイルして実行する有効なコードです。
Fortranは、後の言語の設計方法に大きな影響を与えました。早い段階で(これらの問題の一部は修正されました)Fortranには、識別子に付ける名前を制限するルールがほとんどありませんでした。これにより、コンパイラーとプログラマーの両方の言語の解析が非常に難しくなりました。以下に典型的な例を示します。
if if .eq. then then = else else else = endif endif
K I K K I I K I I K
ここでは、「言語のキーワード」にKと識別子(変数名)Iを付けました。スペルに違いがないことを考えると、これがいかに混乱しやすいかをおそらく理解できると思います。もちろん、これは極端な例であり、意図的にこのようなコードを書いた人はいないでしょう。しかし、人々は言語のキーワードを識別子名として「リサイクル」することがありました。多くの場合、単純なタイプミスにより、まったく意図されていなかったにもかかわらず、言語仕様がこの方法で解析されるコードが生成されることがありました。別の有名な例については、これを比較してください:
do 10 i = 1,10
これに:
do 10 i = 1.10
1つはdoループです。コードのブロックを10回繰り返します。ただし、2番目はコンマが小数点に変更されている1.10
ため、という名前の変数に値を割り当てていますdo 10 i
。
これは、Fortranパーサーの記述が比較的困難であることも意味しました。do
行の終わりに到達するまで行の先頭が本当にキーワードであることを確信できず、aの他のすべての要素を検証しました。do
ループが存在しました。パーサーは一般に「バックトラック」する準備ができていて、最初から行を再解析して、実際に存在するものの「正しい」(ただし、意図しない)答えに到達する必要がありました。
数年後、言語設計者(とにかくほとんど)は反対の極端な方向に進みました-ユーザーがあまり文句を言うことなく、言語に関するほぼすべてを可能な限り制限しました。
たとえば、初期のBASICは基本的に、キーワードを識別子の一部として使用することすらできないと言っていました。たとえば、(つまり、ループではなく、割り当ての始まりfora=1
としてfor a = 1
)解析されます。それは明らかに長続きしないほど十分な苦情を生み出しました。数字で識別子を開始することに関するルールは、多くの苦情を発生させていないようであるため、(少なくともほとんどの言語で)引き続き使用されています。for
これは、プログラミング言語に論理的に必要な規則ではなく、多くの言語設計者が使用する規則にすぎません。
識別子にすべての文字を使用できる根本的に異なる言語を設計できます。すべてのコード行について、最初の20文字がステートメントタイプを記述し、次の20文字がステートメントの最初のシンボルを定義し、次の20文字がステートメントのオペランドです。この言語はスタックプロセッサで実行されます。
01234567890123456789 01234567890123456789 01234567890123456789
decl symbol 12345
assign value 12345 12345
decl symbol 99999
assign value 99999 12345
push 12345
push 99999
add
print top
このコードは、以下のようにCで翻訳できます。
int i12345 = 12345;
int i99999 = 12345;
printf("%d", i12345+i9999);
それで全部です。それは無意味であり、識別子に番号を付けないというルールも論理的には無意味です。
この質問に対する答えは、正規表現を定義するオートマトンまたはより正確には有限オートマトンにあります。ルールは...コンパイラは、解析するすべての文字で決定するための正確なアルゴリズムまたはルールを必要とします。識別子が数字で始まることを許可されていた場合、コンパイラは修正中です....トークンの性質について...それは数字または識別子になります...コンパイラが以前の位置に戻ることができないため。 .so ..次のトークンが正確に識別子または数字であることをコンパイラーに明らかにするために...この制限があります...これの...コンパイラーは、次のトークンを最初の文字をスキャンするだけで知っています識別子または番号です。