example definicion java c parsing grammar

definicion - ¿Qué hace que Java sea más fácil de analizar que C?



java graphics (1)

Estoy familiarizado con el hecho de que las gramáticas de C y C ++ son contextuales y , en particular, se necesita un "haxer hack" en C. Por otro lado, tengo la impresión de que se puede analizar Java solo 2 tokens de anticipación, a pesar de la considerable similitud entre los dos idiomas.

¿Qué tendrías que cambiar sobre C para que sea más manejable analizar?

Lo pregunto porque todos los ejemplos que he visto sobre la sensibilidad al contexto de C son técnicamente permisibles pero terriblemente extraños. Por ejemplo,

foo (a);

podría estar llamando a la función void foo con el argumento a . O bien, podría estar declarando que a es un objeto de tipo foo , pero igual podría deshacerse de las parantheses. En parte, esta rareza se produce porque la regla de producción del "declarante directo" para la gramática C cumple el doble propósito de declarar funciones y variables.

Por otro lado, la gramática de Java tiene reglas de producción separadas para declaración de variable y declaración de función. Si tú escribes

foo a;

entonces sabes que es una declaración de variables y foo puede analizarse sin ambigüedades como un nombre de tipo. Puede que este código no sea válido si la clase foo no se ha definido en algún lugar del alcance actual, pero ese es un trabajo para el análisis semántico que se puede realizar en un pase de compilación posterior.

Lo he visto decir que C es difícil de analizar debido a typedef, pero también puedes declarar tus propios tipos en Java. ¿Qué reglas de gramática C, además de direct_declarator , tienen la culpa?


El análisis C ++ es cada vez más difícil. El análisis Java es cada vez más difícil.

Vea esta respuesta SO que explica por qué C (y C ++) es "difícil" de analizar . El breve resumen es que las gramáticas C y C ++ son inherentemente ambiguas; le darán múltiples análisis y debe usar el contexto para resolver las ambigüedades. La gente comete el error de asumir que tiene que resolver ambigüedades al analizar; no es así, mira abajo. Si insistes en resolver ambigüedades al analizar, tu analizador se vuelve más complicado y mucho más difícil de construir; pero esa complejidad es una herida autoinfligida.

IIRC, la gramática "obvia" LALR (1) de Java 1.4 no era ambigua, por lo que era "fácil" de analizar. No estoy tan seguro de que la Java moderna no tenga al menos ambigüedades locales de larga distancia; siempre existe el problema de decidir si "... >>" cierra dos plantillas o si es un "operador de desplazamiento a la derecha". Sospecho que Java moderno ya no analiza el LALR (1) .

Pero uno puede superar el problema de análisis mediante el uso de analizadores potentes (o analizadores débiles y hacks de recopilación de contexto como los frontales C y C ++ lo hacen en la mayoría de los casos), para ambos lenguajes. C y C ++ tienen la complicación adicional de tener un preprocesador; estos son más complicados en la práctica de lo que parecen. Una afirmación es que los analizadores C y C ++ son tan difíciles que deben escribirse a mano. No es verdad; puedes construir analizadores Java y C ++ sin problemas con los generadores de analizadores GLR.

Pero el análisis no es realmente donde está el problema.

Una vez que analice, querrá hacer algo con el árbol AST / parse. En la práctica, necesita saber, para cada identificador, cuál es su definición y dónde se usa ("nombre y tipo de resolución", sin cuidado, construyendo tablas de símbolos). Esto resulta ser MUCHO más trabajo que tener el analizador sintáctico correcto, compuesto por herencia, interfaces, sobrecarga y plantillas, y confundido por el hecho de que la semántica de todo esto está escrita en un lenguaje natural informal repartido entre decenas y cientos de páginas del estándar de lenguaje. C ++ es realmente malo aquí. Java 7 y 8 están llegando a ser bastante horribles desde este punto de vista. (Y las tablas de símbolos no son todo lo que necesita, vea mi biografía para un ensayo más largo sobre "La vida después de analizar").

La mayoría de la gente lucha con la parte de análisis puro (a menudo nunca termina, comprueba SO por las muchas, muchas preguntas sobre cómo construir analizadores de trabajo para lenguajes reales), para que nunca vean la vida después del análisis. Y luego obtenemos teoremas populares sobre lo que es difícil de analizar y ninguna señal sobre lo que sucede después de esa etapa.

La corrección de la sintaxis de C ++ no te llevará a ningún lado.

Con respecto al cambio de la sintaxis de C ++: encontrará que debe parchear muchos lugares para encargarse de la variedad de ambigüedades locales y reales en cualquier gramática de C ++. Si insistes, la siguiente lista podría ser un buen punto de partida . Sostengo que no tiene sentido hacer esto si no eres el comité de estándares de C ++; si lo hiciste, y construiste un compilador usando eso, nadie en su sano juicio lo usaría. Hay demasiado invertido en las aplicaciones existentes de C ++ para cambiar la conveniencia de los chicos que crean analizadores sintácticos; además, su dolor ha terminado y los analizadores existentes funcionan bien.

Es posible que desee escribir su propio analizador. OK eso está bien; simplemente no espere que el resto de la comunidad le permita cambiar el idioma que debe usar para que sea más fácil para usted. Todos quieren que sea más fácil para ellos, y eso es utilizar el lenguaje tal como está documentado e implementado.