c++ boost-spirit boost-spirit-qi

c++ - Boost Spirit: "Las acciones semánticas son malas"?



boost-spirit boost-spirit-qi (1)

Estoy seguro de que Hartmut responderá en un segundo. Hasta entonces, esta es mi opinión:

No, eso no es un punto oficial.

Las acciones semánticas tienen algunos inconvenientes

  • La desventaja más simple de las acciones semánticas es la noción estilística de separación de preocupaciones . Desea expresar la sintaxis en un lugar y la semántica en otro. Esto ayuda a mantener (especialmente en lo que respecta a los largos tiempos de compilación para compilar Spirit Grammars)

  • Implicaciones más complicadas si tienen efectos secundarios (que a menudo es el caso). Imagine retroceder desde un nodo analizado cuando la acción semántica tiene un efecto secundario : el estado del analizador se revierte, pero los efectos externos no lo son.

    En cierto modo, usar atributos solo es como usar funciones puras deterministas en un programa funcional, es más fácil razonar sobre la corrección de un programa (o, en este caso, la máquina de estado gramatical ) cuando está compuesto solo de funciones puras.

  • Las acciones semánticas tienen una tendencia (pero no necesariamente) a introducir más copias por valor; esto, en combinación con un retroceso pesado, podría reducir el rendimiento . Por supuesto, si la acción semántica es ''pesada'' esto, en sí mismo, va a obstaculizar la ejecución del análisis sintáctico.

Las acciones semánticas son buenas para varios propósitos. De hecho, si necesita analizar gramáticas no triviales con sensibilidad al contexto, no puede escapar de ellas.

  1. Considere el uso de qi::locals<> y atributos heredados (código de la muestra Mini XML - ASTs! ) - implican acciones semánticas:

    xml = start_tag [at_c<0>(_val) = _1] >> *node >> end_tag(at_c<0>(_val)) // passing the name from the // ... start_tag as inherited attribute ;

    O uno usando qi :: locals :

    rule<char const*, locals<char> > rl; rl = alpha[_a = _1] >> char_(_a); // get two identical characters test_parser("aa", rl); // pass test_parser("ax", rl); // fail

    OMI, estas acciones semánticas generalmente representan un problema menor, porque cuando se vuelven a retroceder, la próxima vez que la ejecución pase (la misma) acción semántica, lo local se sobrescribirá con el valor nuevo y correcto.

  2. Además, algunos trabajos son realmente ''rápidos y sucios'' y no garantizan el uso de utree o un tipo de AST enrollado a mano:

    qi::phrase_parse(first, last, // imagine qi::istream_iterator... intesting_string_pattern // we want to match certain patterns on the fly [ log_interesting_strings ], // and pass them to our logger noise_skipper // but we skip all noise );

    Aquí, la acción semántica es el núcleo de la función de analizadores. Funciona, porque no hay retroceso implicado en el nivel de los nodos con acciones semánticas.

  3. Las acciones semánticas son una imagen especular de acciones semánticas en el Espíritu Karma, donde generalmente plantean menos problemas que en Qi; por lo tanto, aunque solo sea para la consistencia de la interfaz / API, las acciones semánticas son "buenas" y mejoran la usabilidad de Boost Spirit en general.

Leer y ver esta presentación: http://boost-spirit.com/home/2011/06/12/ast-construction-with-the-universal-tree/
Descubrí esta afirmación: básicamente, se nos sugiere no usar acciones semánticas.

Debo admitir que ya sentí algo así: las gramáticas con acciones semánticas se ven realmente feas. y, cuando necesité extenderlos / cambiarlos, tomó mucha "microgestión" exactamente con acciones semánticas. El enfoque con la gramática de atributos, demostrado en la presentación, parece ser mucho más elegante y prometedor.

Entonces me gustaría preguntar: ¿este es un punto "oficial"? ¿Debo aprender a trabajar con la gramática de atributos y evitar las acciones semánticas con más detalle? Si es así, me gustaría pedir algunos ejemplos básicos (incluso triviales) que demuestren tal enfoque: el intérprete de LISP es demasiado complejo para que lo pueda masticar ...