Почему язык программирования требует ключевых слов?

Например (в C):

int break = 1; int for = 2; 

Почему у компилятора вообще есть какие-либо проблемы при выводе того, что break и for являются переменными здесь?


Итак, нам нужны ключевые слова, потому что

  • мы хотим, чтобы программы были удобочитаемыми
  • мы не хотим чрезмерно усложнять работу уже сложных компиляторов сегодня
  • но, что наиболее важно, язык намного эффективнее, если некоторые ключевые слова зарезервированы для некоторых специальных действий. Затем язык может думать о том, чтобы быть полезным на более высоком уровне, а не умереть в попытке реализовать цикл for в однозначном ключе.

Тогда что будет делать компьютер, когда дело доходит до утверждения вроде:

 while(1) { ... if (condition) break; } 

Должно ли это на самом деле ломаться? Или следует рассматривать его как 1; ?

В некоторых случаях язык станет двусмысленным, или вам нужно будет создать очень умный парсер, который может вывести тонкий синтаксис, и это просто лишняя дополнительная работа.

Это не обязательно – Фортран не оставлял никаких слов, поэтому такие вещи, как:

 if if .eq. then then if = else else then = if endif 

являются законными. Это не только затрудняет язык для компилятора , но часто почти невозможно, чтобы человек мог читать или обнаруживать ошибки. например, рассмотрим classический Fortran (скажем, через Fortran 77 – я не использовал его в последнее время, но, по крайней мере, надеюсь, что они исправили несколько подобных вещей в более поздних стандартах). Цикл Fortran DO выглядит следующим образом:

 DO 10 I = 1,10 

Если они не будут бок о бок, вы, вероятно, увидите, как вы пропустите, как это было иначе:

 DO 10 I = 1.10 

К сожалению, последний не является циклом DO вообще – это простое присвоение значения 1.10 переменной с именем DO 10 I (да, это также позволяет пробелы в имени). Поскольку Fortran также поддерживает неявные (необъявленные) переменные, это (или было) все совершенно законно, и некоторые компиляторы даже принимают его без предупреждения!

Они этого не делают. PL / 1 classно не имеет ключевых слов; каждое «ключевое слово» (BEGIN, DO, …) также может использоваться имя переменной. Но разрешая это, вы можете написать действительно неясный код: ЕСЛИ DO> BEGIN THEN PRINT: = CALL-GOTO; Сохранение «ключевых слов в заявлении», поскольку язык обычно не является потерей, если этот набор имен является скромным (как и в каждом langauge, который я когда-либо видел, кроме PL / 1 :-).

В APL также нет ключевых слов. Но у него есть набор из 200 удивительных знаковых символов, в которых можно писать сложные операторы. (оператор «домино» [не спрашивать!] представляет собой квадратную коробку с индексом деления калькулятора посередине). В этом случае дизайнеры langauge просто использовали значки вместо ключевых слов. Следствием этого является то, что APL имеет репутацию языка «только для записи».

Итог: не требование, но он стремится сделать программы более читаемыми, если ключевые слова являются зарезервированными идентификаторами из небольшого набора, известного программистам. (Некоторые langauges настаивали на том, что «ключевые слова» начинаются с специального символа пунктуации типа «.», Чтобы можно было использовать все возможные идентификаторы, но это не стоит лишней неприятности для ввода или беспорядка на странице; избегайте «идентификаторов», которые соответствуют ключевым словам, когда набор ключевых слов невелик).

Поскольку он помечен C, исходный язык C был таким, что по умолчанию любая переменная была определена как тип int .

Это означает, что foo; объявит переменную типа int .

Предположим, вы break; , Итак, как компилятор знает, хотите ли вы объявить переменную с именем break или использовать break ключевого слова?

некоторые причины:

  • Ключевые слова могут показаться недвусмысленными в ваших образцах. Но это не единственное место, где вы бы использовали переменную «break» или переменную «for».

  • писать синтаксический анализатор было бы намного сложнее, а ошибка была бы склонна к небольшому выигрышу.

  • использование ключевого слова как функции или имени процедуры в библиотеке может иметь нежелательные, возможно связанные с безопасностью, побочные эффекты.

Как говорили другие, это упрощает анализ исходного кода компилятором. Но я хотел бы сказать немного больше: он также может сделать ваш исходный код более удобочитаемым; рассмотрим этот пример:

если (если> 0), то тогда = 10 заканчивается, если

Второе «если» и второе «затем» являются переменными, а другие – нет. Я думаю, что этот код не читается. 🙂

Если мы говорим о C ++ – у него уже есть очень сложная грамматика. Например, использование ключевых слов в качестве имен переменных сделает его еще более сложным.

У компилятора возникнут проблемы, если вы напишете что-то вроде этого:

 while(*s++); return(5); в while(*s++); return(5); 

Это цикл или вызов функции с именем while ? Вы хотите вернуть значение 5 из текущей функции или вы хотите вызвать функцию с именем return ?

Это часто упрощает вещи, если конструкции со специальным значением просто имеют специальные имена, которые могут быть использованы для однозначного обращения к ним.

Потому что мы хотим сохранить то, что у нас есть немного:

 void myfunction(bool) { .. }; funcp while = &myfunction; while(true); 

Я думаю, это выглядит очень странно, если не невозможно написать парсер. Например

 int break = 1; while (true) { // code to change break if (!break) break; // not very readable code. } 

В зависимости от определения языка компилятор может или не нуждаться в ключевых словах. Когда он не знает, что делать, он может попытаться применить правила приоритета или просто потерпеть неудачу.
Пример:

 void return(int i){printf("%d",i);} public int foo(int a) { if(a > 2)return (a+1)*2; return a + 3; } 

Что произойдет, если a больше 2?

  • Спецификация языка может потребовать, чтобы компилятор отказался
  • Спецификация языка может потребовать, чтобы компилятор использовал функцию возврата
  • Спецификация языка может потребовать от компилятора возврата

Вы можете определить язык, который не использует ключевые слова. Вы даже можете определить язык, который позволит вам заменить все символы (поскольку они являются очень короткими ключевыми словами).
Проблема заключается не в компиляторе, если ваша спецификация завершена и без ошибок она будет работать. Проблема в PEBCAD, программы, использующие эту функцию языка, будут трудно читать, поскольку вам необходимо отслеживать определения символов.

FWIW, Tcl не имеет зарезервированных слов. Вы можете иметь переменные и функции с именем «if», «break» и т. Д. Интерпретация токена полностью зависит от контекста. Тот же токен может представлять собой команду в одном контексте, переменную в другой или литеральную строку в другой.

Во многих случаях компилятор мог бы интерпретировать ключевые слова как обычные идентификаторы, например, в вашем примере:

 int break = 1; int for = 2; 

На самом деле, я просто написал компилятор для простого сборочного языка игрушек, который делает это, но предупреждает пользователя в таких случаях.

Но иногда синтаксис определяется таким образом, что ключевые слова и идентификаторы неоднозначны:

 int break; while(...) { break; // <-- treat this as expression or statement? } 

И самая очевидная причина в том, что редакторы будут подчеркивать ключевые слова, чтобы код был более читабельным для людей. Разрешение ключевых слов, которые будут обрабатываться как идентификаторы, сделает выделение кода более сложным, а также приведет к плохой читаемости вашего кода.