La mayoría de los lenguajes de programación parecen estar diseñados para no permitir que uno declare un identificador que comienza con un número. Tenía curiosidad por saber la razón. Ya he buscado en la web, pero no pude encontrar una explicación satisfactoria.
32
Respuestas:
En C / C ++, un número seguido de una letra se considera una constante numérica y la cadena que sigue califica el tipo de la constante. Entonces, por ejemplo (estos son VC ++, no estoy seguro de qué tan estándar son):
Entonces a) es más fácil para el lexer como dijo Daniel, pero también b) hace una distinción explícita ya que 0y podría ser una variable pero 0u nunca lo sería. Además, otros calificadores, como "i64", se agregaron mucho más tarde que "l" o "u" y quieren mantener abierta la opción de agregar más si es necesario.
fuente
La conveniencia de las personas que implementan el lexer. (No, en serio, de eso se trata. Varios idiomas tienen otras razones, pero finalmente se reduce a eso).
fuente
0flu
fuera un literal y0glu
un identificador local.int 0u = 5; unsigned int x = 0u;
Sin embargo, usted elige definir la interpretación de este código (probablemente x == 0 o x == 5), las personas se confundirán por la ambigüedad Incluso si fuera trivial implementar el compilador de esta manera, un buen diseñador probablemente no lo haría.Considere los siguientes 2 casos:
Caso 1
Supongamos que un identificador podría comenzar con un número.
Por lo tanto, una declaración como la siguiente sería válida (ya que un identificador puede tener 1 o más caracteres):
Cuando trato de usar la variable anterior en un programa, resultará en la ambigüedad del compilador:
En el enunciado,
a=3
¿cuál es el papel de 3 (¿es una variable con valor 5 o es el número 3)?Caso 2
A diferencia del ejemplo anterior, supongamos que un idioma permitiría en realidad identificadores que comiencen con un número sin permitir que los números se usen como identificadores. Esto puede causar los siguientes problemas:
Las reglas del lenguaje con respecto a la variable que dice que una variable puede constar de 1 o más caracteres deberán redefinirse a una regla compleja como: Una variable puede tener uno o más caracteres y debe ser única si no comienza con un número mientras no puede tener una longitud de un solo carácter al comenzar con un número (etc.)
El compilador tendrá que verificar y reportar casos de error cuando todos los números (ej. 333) y sufijos válidos del alfabeto (ej. 34L) se estén utilizando como nombres de variables. En lenguajes poco escritos como Python y JS donde puede usar variables sobre la marcha sin declararlas, incluso puede ser imposible verificar los casos especiales que involucran todos los números, por ejemplo
if (33==5)
, Aquí, 33 podría ser una variable errónea no declarada que el usuario ha declarado. Pero el compilador no podrá identificar esto e informar el error.Hacer esta restricción evitará que el programador use números como nombres de identificación.
fuente
int char = float
que sería?int
es una palabra clave y no un identificador? Bueno,int
tiene mayor precedencia tal como lo tendrían los lexemas numéricos.int 3,a; 3=5; a=3;
en el enunciado a = 3, ¿se interpreta 3 como un identificador o como un número? Esto causa ambigüedad. Espero que esté claro.En su mayor parte, esto no tiene nada que ver con facilitar a los escritores del compilador y la eficacia del análisis, sino más bien con el diseño de una sintaxis que fomente un código claro, legible y sin ambigüedades.
Los diseñadores de lenguaje pensaron que sería bueno poder escribir literales numéricos como el número 1 como simplemente 1 .
Sería bastante posible diseñar una sintaxis de lenguaje donde los literales numéricos se citaran de alguna manera, por ejemplo tildas, de modo que el literal numérico para el número uno se codificara como ~ 1 ~ y cualquier cosa que no fuera una palabra clave y no se incluyera entre comillas se tratara como un nombre variable .
Para que pueda codificar declaraciones como:
Pero también:
Cualquiera sea la sintaxis que elija, el código ambiguo y difícil de seguir es inevitable.
El lenguaje C y la mayoría de los lenguajes de "llaves" descendientes de C también consideraron una buena idea permitir que los programadores codifiquen los literales Octal y Hexadecimal directamente, y especificar el tipo del literal si esto fuera importante. Asi que
Entonces, incluso si permitía que los nombres de variables comenzaran con un número seguido de una combinación de números y letras que incluía al menos una letra, le presentaría al programador el problema de decidir si un grupo dado formó un nombre de variable o un literal numérico
Tal ambigüedad no ayudaría a nadie a escribir o leer un programa.
Para ver un ejemplo del mundo real estrechamente relacionado, podría ver el lenguaje PL / 1 cuyos diseñadores pensaron que poder usar palabras clave como nombres de variables era una buena idea para que:
Es un código válido que compila y ejecuta.
fuente
Fortran tuvo un gran efecto en cómo se diseñaron los idiomas posteriores. Al principio (algunos de estos problemas se han solucionado desde entonces) Fortran casi no tenía reglas que restringieran el nombre que se le podía dar a un identificador. Esto hizo que el lenguaje fuera extremadamente difícil de analizar tanto para los compiladores como para los programadores. Aquí hay un ejemplo clásico:
Aquí he marcado las "palabras clave del lenguaje" con K y los identificadores (nombres de variables) I. Dado que no hay diferencia en la ortografía, creo que probablemente puedas entender lo confuso que puede ser. Por supuesto, este es un ejemplo extremo, y es poco probable que alguien haya escrito un código como este a propósito. Sin embargo, a veces las personas "reciclaban" las palabras clave del idioma como nombres de identificación, y en muchos casos un error tipográfico simple podía generar un código que la especificación del lenguaje decía que debería analizarse de esta manera, aunque no fuera para nada. Para otro ejemplo bien conocido, compare esto:
a esto:
El primero es un bucle do: iterar un bloque de código 10 veces. El segundo, sin embargo, ha cambiado la coma a un punto decimal, por lo que está asignando el valor
1.10
a una variable llamadado 10 i
.Esto también significaba que escribir un analizador Fortran era relativamente difícil: no se podía estar seguro de que
do
al principio de la línea era realmente una palabra clave hasta llegar al final de la línea y verificar que todos los demás elementos de undo
loop estaban presentes. El analizador generalmente tenía que estar listo para "retroceder", volviendo a analizar la línea desde el principio para llegar a la respuesta "correcta" (pero a menudo involuntaria) de lo que realmente estaba allí.Después de unos años de esto, los diseñadores de idiomas (la mayoría de ellos de todos modos) se dirigieron al extremo opuesto, restringiendo casi todo lo posible sobre el idioma sin que los usuarios se quejen demasiado .
Early BASIC, por ejemplo, básicamente decía que ni siquiera podía usar una palabra clave como parte de un identificador; por ejemplo,
fora=1
se analizaría comofor a = 1
(es decir, el comienzo de unfor
bucle, no una asignación). Al parecer, eso generó suficientes quejas de que no duró mucho. La regla sobre comenzar un identificador con un dígito aparentemente no ha generado muchas quejas, por lo que continúa utilizándose (al menos en la mayoría de los idiomas).fuente
Probablemente, esta convención ha evolucionado a partir de decisiones de diseño de lenguaje histórico muy tempranas, ya que en las primeras máquinas todo el compilador, incluido el análisis léxico, tenía que ejecutarse en unos pocos kWords, menos memoria que incluso el caché de datos del procesador de primer nivel en los dispositivos móviles actuales, por lo tanto, los nombres de variables permitidos eran muy limitados y tenían que ser fáciles de distinguir de las constantes numéricas en muy pocos códigos operativos.
Por lo tanto, la convención se convirtió en lo que las generaciones de programadores están acostumbrados.
fuente
No es una regla requerida lógicamente para el lenguaje de programación, sino solo la convención utilizada por muchos diseñadores de lenguaje.
Puedo diseñar un lenguaje radicalmente diferente que permita todos los caracteres para los identificadores. Para todas las líneas de código, los primeros 20 caracteres describirán el tipo de declaración, luego los siguientes 20 caracteres definirán el primer símbolo para la declaración, y los siguientes 20 caracteres son operandos para la declaración. Este lenguaje se ejecutará en un procesador de pila.
Este código podría traducirse en C de la siguiente manera:
Eso es todo. No tiene sentido y la regla de no-número-en-identificadores tampoco tiene sentido en un terreno lógico.
fuente
Además de "conveniencia para el lexer", creo que también vale la pena considerar "conveniencia para el lector".
Al leer el código, debe identificar rápida y repetidamente qué palabras son identificadores y cuáles son números. Buscar un dígito al principio es más fácil en nuestra coincidencia visual de patrones; sería una tarea ardua si tuviéramos que revisar cuidadosamente todos los personajes para asegurarnos.
fuente
La respuesta a esta pregunta radica en autómatas o, más precisamente, autómatas finitos que definen la expresión regular. La regla es ... los compiladores necesitan algoritmos o reglas exactas para decidir en cada personaje que analizan. Si se permitiera que los identificadores comenzaran con un número, entonces el compilador estará en una solución ... sobre la naturaleza del token que viene ... será un número o un identificador ... y como los compiladores no pueden retroceder a posiciones anteriores ... .so..para dejar en claro al compilador que el token que viene es precisamente un identificador o un número ... esta restricción está ahí ... porque de esto ... el compilador sabe simplemente escaneando el primer carácter que el token que viene es un identificador o un número.
fuente