2011-02-18 8 views
7

Tengo una gramática que, hasta ahora, ha estado utilizando el patrón boost::spirit::ascii::space/boost::spirit::ascii::space_type skipper.Boost Spirit Qi Restablecer omisión con skip gramática personalizada

que tienen algunas reglas que utilizan el capitán y algunos que no lo hacen, como

qi::rule<Iterator, PTR<Expression>(), ascii::space_type> expression; 
qi::rule<Iterator, PTR<Term>()> term; 

Cuando utilizo un no saltarse no terminal (como term) en el interior de un saltarse no terminal (como expression), todo funciona como esperaba: el espacio en blanco solo importa dentro del term no terminal.

Además, hasta ahora, he estado bien incluyendo no terminales que utilizan el patrón dentro de no terminales que no utilizan qi::skip a reestablecer saltar, como

index = (qi::lit('[') >> qi::skip(ascii::space)[explist >> qi::lit(']')]); 

De esta manera, los espacios en blanco no es significativa en el interior de los apoyos [], pero está afuera.

Sin embargo, ahora quiero agregar mi propio patrón personalizado (quiero hacer nuevas líneas significativas y más tarde añadir comentario-omitir). Mi gramática patrón se parece a:

struct skip_grammar : qi::grammar<Iterator> { 
    qi::rule<Iterator> start; 
    skip_grammar() : skip_grammar::base_type(start) { 
    start = qi::char_("\t\r "); 
    } 
}; 

he podido agregar en mis definiciones de reglas bien como

qi::rule<Iterator, PTR<Expression>(), skip_grammar> expression; 

Pero me parece que no puede encontrar la manera de usar mi gramática salto como un argumento a qi::skip (y reemplace ascii::space). Intenté usar el tipo, una variable de instancia local y una variable de instancia global. Lo más lejos que he conseguido es hacer clang para quejarse de que mi skip_grammar necesita un constructor de copias. Así que traté de agregar un constructor de copia a mi gramática omitida, pero aparentemente la clase base boost::noncopyable está ahí por una razón, porque mi binario segfaulted casi de inmediato.

¿Cómo debo usar esto?

Gracias

Respuesta

7

Un qi::grammar es sólo un contenedor para qi::rules. No tiene un constructor de copia porque esto podría crear inadvertidamente referencias colgantes en las expresiones del analizador en el lado derecho de esas reglas.

Usar una gramática como patrón, como quiera hacer, es un poco complicado y equivale a pasar la regla de inicio de la gramática al analizador de saltos. Puede ser más fácil simplemente crear una instancia de regla para eso (especialmente si tiene un único patrón de regla).

En cualquier caso, la regla tiene que ser pasado al patrón de referencia (llamando a la función miembro de la regla alias()):

skip_grammar skippper; 
index = '[' >> qi::skip(skipper.start.alias())[explist >> ']']; 

o simplemente:

rule<iterator> skipper = qi::char_("\t\r "); 
index = '[' >> qi::skip(skipper.alias())[explist >> ']']; 

El aliasing es necesario debido a los detalles de lo que significa copiar una regla. Se describe con más detalle en las preguntas frecuentes de Spirit here.

+0

Bien fantástico. Gracias de nuevo por toda su increíble ayuda. Como un aparte, ¿debería usar reglas en lugar de gramáticas para omitir?No pensé que phrase_parse tomara el tipo de regla para el patrón. – jtolds

+0

Cualquier componente analizador se puede utilizar como patrón para phrase_parse - sin limitaciones. – hkaiser

+0

+1, el alias() era lo que estaba buscando, no estaba seguro de cómo usarlo para una gramática, pero aplicarlo a la regla de inicio en skip() tiene sentido. El diagnóstico MSVC es inútil aquí; solo se refiere a C2248 sin rastreo de origen. – namezero

Cuestiones relacionadas