¿Qué quiere decir la gente cuando dice esto? ¿Cuáles son las implicaciones para los programadores y compiladores?¿Qué quiere decir la gente cuando dice que C++ tiene "gramática indecidible"?
Respuesta
Esto se relaciona con el hecho de que el sistema de plantillas de C++ es Turing complete. Esto significa (teóricamente) que puede calcular cualquier cosa en tiempo de compilación con plantillas que podría usar con cualquier otro lenguaje o sistema completo de Turing.
Esto tiene el efecto secundario de que algunos programas C++ aparentemente válidos no se pueden compilar; el compilador nunca podrá decidir si el programa es válido o no. Si el compilador pudiera decidir la validez de todos los programas, podría resolver el Halting problem.
Tenga en cuenta que esto no tiene nada que ver con la ambigüedad de la gramática C++.
Editar: Josh Haberman señaló en los comentarios a continuación y en una blog post con un excelente ejemplo de que la construcción de un árbol de análisis sintáctico para C++ realidad es acotable. Debido a la ambigüedad de la gramática, es imposible separar el análisis de sintaxis del análisis semántico, y dado que el análisis semántico es indecidible, también lo es el análisis de sintaxis.
Ver también (enlaces de entrada de Josh):
divertido, el sistema completo de plantillas turing en C++ es lo que considero una de sus mayores fortalezas. –
Esto fue nuevo para mí, pero lo vi totalmente en la primera frase, ¡brillante! @Evan - sí, pero ser indecidible no es necesariamente un "defecto" - es así; al igual que la lógica axiomática no es "defectuosa" solo porque está incompleta (Gödel). –
@Evan, será una fortaleza para los programadores de C++ en que puede calcular cosas en tiempo de compilación. Sin embargo, hace que sea más difícil escribir un buen compilador de C++. –
Lo que probablemente significa es que la gramática de C++ es sintácticamente ambigua, que puede escribir un código que podría significar cosas diferentes, según el contexto. (La gramática es una descripción de la sintaxis de un lenguaje. Es lo que determina que a + b
es una operación de suma, que involucra variables a y b.)
Por ejemplo, foo bar(int(x));
, como está escrito, podría ser una declaración de una variable llamada bar, de tipo foo, con int (x) siendo un inicializador. También podría ser una declaración de una función llamada bar, tomando un int y devolviendo un foo. Esto se define dentro del lenguaje, pero no como parte de la gramática.
La gramática de un lenguaje de programación es importante. En primer lugar, es una forma de entender el idioma y, en segundo lugar, es parte de la compilación lo que puede hacerse rápidamente. Por lo tanto, los compiladores C++ son más difíciles de escribir y más lentos de usar que si C++ tuviera una gramática no ambigua. Además, es más fácil crear ciertas clases de errores, aunque un buen compilador proporcionará suficientes pistas.
Si lo convierte en 'foo * bar (int (x))', puede ser: (a) una expresión, (b) una declaración de objeto o (c) una declaración de función. –
La implicación para quienes usamos el lenguaje es que los mensajes de error pueden ser muy extraños, muy rápidos (en la práctica, esto no es un problema. Los errores de la biblioteca STL suelen ser peores que las cosas con las que termina debido a la gramática del lenguaje).
La implicación para quienes escriben los compiladores es que tienen que gastar mucho tiempo y esfuerzo en compilar el idioma.
Si "algunas personas" incluye Yossi Kreinin, a continuación, basado en lo que escribe here ...
Considere este ejemplo:
x * y(z);
en dos contextos diferentes:
int main() { int x, y(int), z; x * y(z); }
y
int main() { struct x { x(int) {} } *z; x * y(z); }
... que significa "Usted no puede decidir por mirar en x * y (z) ya sea t es una expresión o una declaración ". En el primer caso, significa "llamar a la función y con el argumento z, luego invocar operador * (int, int) con xy el valor de retorno de la llamada de función, y finalmente descartar el resultado". En el segundo caso, significa que "y es un puntero a una estructura x, inicializado para apuntar a la misma dirección (bomba de tiempo & basura) como lo hace z".
Supongamos que ha tenido un ataque de COBOLmania y ha agregado DECLARAR al idioma. Entonces el segundo se convertiría en
int main() {
DECLARE struct x { x(int) {} } *z;
DECLARE x * y(z);
}
y la decidability aparecería. Tenga en cuenta que ser decidible no hace desaparecer el problema del puntero a la basura.
Por supuesto, esto no se limita a C++ - considere BASIC, por ejemplo - ¿es "x = 1" una tarea o una prueba? Solo en contexto puedes decirlo. –
Yossi Kreinin habla sobre "el problema que hace que la gramática de C++ sea indecidible", pero eso es una mierda; de hecho, el mismo sitio web en otro lugar, mientras explica que C++ tiene una gramática indecidible, dice que "Esto muestra (en un nivel intuitivo) que la gramática de C++ es bastante sensible al contexto". http://yosefk.com/c++fqa/defective.html#defect-2 – Blaisorblade
@anon: en BASIC es suficiente saber contra qué producción está haciendo coincidir "y = 1", es decir, si es una expresión o una declaración. C++ es más complejo, ya que la misma secuencia de caracteres, en la misma posición y en el mismo contexto inmediato puede significar cosas totalmente diferentes. – Blaisorblade
'Gramática indecidible' es una elección muy pobre de palabras. Una gramática verdaderamente indecidible es tal que no existe un analizador para la gramática que terminará en todas las entradas posibles. Lo que probablemente quieren decir es que la gramática de C++ no está libre de contexto, pero incluso esto es una cuestión de gusto: ¿dónde trazar la línea entre la sintaxis y la semántica? Cualquier compilador admitirá solo un subconjunto adecuado de aquellos programas que pasen la etapa del analizador sin errores de sintaxis y solo un subconjunto adecuado de esos programas realmente se ejecute sin errores, por lo tanto, ningún idioma es verdaderamente libre de contexto o incluso decidable (salvo tal vez algunos lenguajes esotéricos) .
Hay una variedad de términos, pero aquí no importa si el programa finaliza. En los lenguajes formales, un lenguaje es decidible si un algoritmo puede decidir si una palabra pertenece al idioma. En términos simples, si un programa lo compila, pertenece al lenguaje, sin importar los resultados en tiempo de ejecución. Además, el cálculo lambda simplemente tipado es un ejemplo bastante simple de un lenguaje en el que cada programa termina y existen muchas otras variaciones más complejas. – Blaisorblade
- 1. ¿Qué quiere decir la gente cuando dice "Perl es muy bueno en el análisis"?
- 2. ¿qué quiere decir FOO?
- 3. ¿Qué quiere decir crockford cuando dice que indefinido no puede ser un valor de propiedad?
- 4. ¿Qué quiere decir uint32_t?
- 5. Java: ¿Qué quiere decir ~
- 6. ¿Qué quiere decir 'git commit' cuando dice 'crear modo ...' en stdout?
- 7. ¿Qué quiere decir la gente con "DOM Manipulation" y cómo lo haría?
- 8. ¿Qué quiere la gente en un diccionario .NET persistente?
- 9. ¿Qué quiere decir "U" en una lista?
- 10. ¿Por qué la gente dice que Java es más escalable que Python?
- 11. Rebase y lo que quiere decir refinanciar commit commits
- 12. HTTP no tiene estado, entonces, ¿qué quiere decir con keep-alive?
- 13. ¿Por qué Python dice que pow solo tiene 2 argumentos?
- 14. lo que quiere decir pss en/proc/PID/smaps
- 15. ¿Qué quiere decir "u" después de un número?
- 16. ¿Qué quiere decir "1 cuando GetType(). Nombre en un tipo genérico?
- 17. ¿Qué está haciendo Eclipse cuando dice que está actualizando índices?
- 18. ¿Qué quiere decir con registrar una función de devolución de llamada en C?
- 19. ¿Por qué la gente dice que javascript eval() es malo pero no objeta contra setTimeout y setInterval, etc.?
- 20. ¿Qué es '=>'? (Pregunta de gramática C#)
- 21. WF, WCF y Servicios declarativos (o: ¿Qué quiere decir Microsoft con "declarativo"?)
- 22. ¿Qué piensa la gente del fósil DVCS?
- 23. ¿Por qué insertar desde std :: map no quiere actualizar? [C++]
- 24. ¿Las interfaces derivan de System.Object? La especificación de C# dice que sí, Eric dice que no, la realidad dice que no
- 25. C# ANTLR gramática?
- 26. ¿Por qué Dialyzer me dice que este divertido contrato tiene dominios superpuestos?
- 27. En Java, ¿por qué la gente antepone campos con `this`?
- 28. ¿Por qué la mayoría de la gente dice que los servicios de datos y la base de datos son las partes más importantes de un sistema?
- 29. ¿Para qué usa la gente la carga de clases?
- 30. ObjectSpace: ¿qué es y cómo lo usa la gente?
cual gente? ¿Dónde lo están diciendo? –
Sospecho que la mayoría de las personas aquí no saben lo que significa "indecidible" en ciencias de la computación. Echa un vistazo al artículo de Wikipedia: http://en.wikipedia.org/wiki/Undecidable_problem –
La mayoría de las cosas que puedo buscar en google sobre C++ teniendo gramática "indecidible" meramente afirman que el significado de una declaración depende de las definiciones anteriores, es decir, de su contexto. Wow, ¡qué indecidible! Esto es como decir que una jugada de baloncesto es "indeciblemente" buena o mala porque depende de quién está adelante y cuál es el tiempo restante. –