Dear all,<br>  I wrote a little VC++ Parser using the Boost/Spirit Parser Framework [1] based in the Squeak EBNF grammar, which I took from the swiki [2]. I wonder if anyone here could tell what&#39;s the best way to run an automated test suite against a parser for Smalltalk from outside an image. <br>
  I want to isolate some expressions resulting in recursion loops for my parser, I include the source below just in case anybody wants to take a look. Sorry for the long e-mail or uncorrect mailing list.<br><br>[1] <a href="http://spirit.sourceforge.net/">http://spirit.sourceforge.net/</a><br>
[2] <a href="http://wiki.squeak.org/squeak/409">http://wiki.squeak.org/squeak/409</a><br><br>//   Requires -  Spirit version 1.6.0 or later<br>#define BOOST_SPIRIT_DEBUG  ///$$$ DEFINE THIS WHEN DEBUGGING $$$///<br><br>#include &lt;boost/spirit/core.hpp&gt;<br>
#include &lt;boost/spirit/symbols/symbols.hpp&gt;<br>#include &lt;boost/spirit/utility/lists.hpp&gt;<br>#include &lt;boost/spirit/utility/confix.hpp&gt;<br>#include &lt;iostream&gt;<br>#include &lt;fstream&gt;<br>#include &lt;vector&gt;<br>
#include &lt;string&gt;<br><br>////////////////////////////////<br>using namespace boost::spirit;<br>using namespace std;<br>//--------------------------------------------<br>//  Start grammar definition<br>//--------------------------------------------<br>
struct st_grammar :<br>    public grammar&lt;st_grammar&gt;<br>{<br>    template &lt;typename ScannerT&gt;<br>    struct definition<br>    {<br>        definition(st_grammar const&amp; self)<br>        {<br>            chlit&lt;&gt;    SUM(&#39;+&#39;);<br>
            chlit&lt;&gt; SUB(&#39;-&#39;);<br>            chlit&lt;&gt;    MOD(&#39;\\&#39;);<br>            chlit&lt;&gt;    DIV(&#39;/&#39;);<br>            chlit&lt;&gt;    MUL(&#39;*&#39;);<br>            chlit&lt;&gt;    NOT(&#39;~&#39;);<br>
            chlit&lt;&gt;    LT(&#39;&lt;&#39;);<br>            chlit&lt;&gt;    GT(&#39;&gt;&#39;);<br>            chlit&lt;&gt;    EQ(&#39;=&#39;);<br>            chlit&lt;&gt;    AT(&#39;@&#39;);<br>            chlit&lt;&gt;    PC(&#39;%&#39;);<br>
            chlit&lt;&gt;    COMMA(&#39;,&#39;);<br>            chlit&lt;&gt; CARET(&#39;^&#39;);<br><br>program = method | block | expression;<br><br>method = message_pattern <br>        &gt;&gt; !temporaries <br>        &gt;&gt; !primitive_declaration <br>
        &gt;&gt; !statements;<br><br>message_pattern = unary_selector<br>        | binary_selector &gt;&gt; argument_name <br>        | +(keyword &gt;&gt; argument_name);<br><br>temporaries = confix_p(&#39;|&#39;, *variable_name, &#39;|&#39;);<br>
<br>primitive_declaration = confix_p(&#39;&lt;&#39;, str_p(&quot;primitive:&quot;) &gt;&gt; +digit_p, &#39;&gt;&#39;);<br><br>identifier = lexeme_d [ alpha_p &gt;&gt; *(alnum_p | digit_p) ];<br><br>binary_selector = SUM | SUB | MOD | DIV | MUL | NOT | LT | GT | EQ | AT | PC | COMMA;<br>
keyword = identifier &gt;&gt; ch_p(&#39;:&#39;);<br>argument_name = identifier;<br><br>block = <br>    confix_p(&#39;[&#39;, <br>    !(+(ch_p(&#39;:&#39;) &gt;&gt; argument_name) &gt;&gt; &#39;|&#39;) &gt;&gt; <br>          *temporaries &gt;&gt; *statements, &#39;]&#39;);<br>
<br>statements = *(expression &gt;&gt; ch_p(&#39;.&#39;)) <br>            &gt;&gt; !CARET <br>            &gt;&gt; expression <br>            &gt;&gt; !ch_p(&#39;.&#39;);<br><br>expression = *(variable_name &gt;&gt; assignment_op) <br>
    &gt;&gt; ( cascaded_message_expression <br>    | message_expression <br>    | primary );<br><br>primary = confix_p(&#39;(&#39;, expression, &#39;)&#39;) <br>        | block <br>        | literal <br>        | argument_name <br>
        | variable_name;<br><br>variable_name = identifier;<br><br>literal = array_constant <br>        |  strng <br>        | character_constant <br>        | symbol_constant <br>        | number;<br><br>message_expression = keyword_expression <br>
        | binary_expression <br>        | unary_expression;<br><br>unary_selector = identifier &gt;&gt; ~eps_p(&#39;:&#39;);<br>unary_expression = primary &gt;&gt; +unary_selector;<br>unary_object_description = unary_expression | primary;<br>
<br>binary_object_description = binary_expression <br>            | unary_object_description;<br><br>binary_expression = unary_object_description <br>        &gt;&gt; binary_selector <br>        &gt;&gt; unary_object_description;<br>
<br>// keyword_expression = binary_object_description % keyword;<br>keyword_expression = binary_object_description &gt;&gt; +(keyword &gt;&gt; binary_object_description);<br><br>cascaded_message_expression = message_expression <br>
    &gt;&gt; +(ch_p(&#39;;&#39;) <br>        &gt;&gt; ( unary_selector<br>        | binary_selector &gt;&gt; unary_object_description<br>        | +(keyword &gt;&gt; binary_object_description)));<br><br>character_constant = ch_p(&#39;$&#39;) <br>
        &gt;&gt; (ch_p(&#39;\&#39;&#39;) <br>        | ch_p(&#39;\&quot;&#39;) <br>        | anychar_p);<br><br>array_constant = ch_p(&#39;#&#39;) &gt;&gt; array;<br>array = confix_p(&#39;(&#39;, *( number | symbol | strng | character_constant | array), &#39;)&#39;);<br>
<br>symbol_constant = ch_p(&#39;#&#39;) &gt;&gt; symbol;<br>symbol = identifier <br>        | binary_selector <br>        | +(keyword) <br>        | strng;<br><br>any_inumber = int_p | uint_p;<br>any_rnumber = real_p | ureal_p;<br>
<br>number <br>    = !any_inumber <br>    &gt;&gt; !ch_p(&#39;r&#39;) <br>    &gt;&gt; (any_inumber ^ any_rnumber) <br>    &gt;&gt; !(ch_p(&#39;e&#39;) &gt;&gt; (any_inumber));<br><br>strng = confix_p(&#39;\&quot;&#39;, *(anychar_p - ch_p(&#39;\&quot;&#39;)), &#39;\&quot;&#39;);<br>
<br>assignment_op = str_p(&quot;:=&quot;);<br><br>BOOST_SPIRIT_DEBUG_NODE(program);<br>BOOST_SPIRIT_DEBUG_NODE(method);<br>BOOST_SPIRIT_DEBUG_NODE(message_pattern);<br>BOOST_SPIRIT_DEBUG_NODE(temporaries);<br>BOOST_SPIRIT_DEBUG_NODE(primitive_declaration);<br>
BOOST_SPIRIT_DEBUG_NODE(identifier);<br>BOOST_SPIRIT_DEBUG_NODE(variable_name);<br>BOOST_SPIRIT_DEBUG_NODE(unary_selector);<br>BOOST_SPIRIT_DEBUG_NODE(binary_selector);<br>BOOST_SPIRIT_DEBUG_NODE(keyword);<br>BOOST_SPIRIT_DEBUG_NODE(argument_name);<br>
BOOST_SPIRIT_DEBUG_NODE(statements);<br>BOOST_SPIRIT_DEBUG_NODE(expression);<br>BOOST_SPIRIT_DEBUG_NODE(message_expression);<br>BOOST_SPIRIT_DEBUG_NODE(assignment_op);<br>BOOST_SPIRIT_DEBUG_NODE(primary);<br>BOOST_SPIRIT_DEBUG_NODE(cascaded_message_expression);<br>
BOOST_SPIRIT_DEBUG_NODE(literal);<br>BOOST_SPIRIT_DEBUG_NODE(block);<br>BOOST_SPIRIT_DEBUG_NODE(message_expression);<br>BOOST_SPIRIT_DEBUG_NODE(unary_expression);<br>BOOST_SPIRIT_DEBUG_NODE(binary_expression);<br>BOOST_SPIRIT_DEBUG_NODE(keyword_expression);<br>
BOOST_SPIRIT_DEBUG_NODE(binary_object_description);<br>BOOST_SPIRIT_DEBUG_NODE(unary_object_description);<br>BOOST_SPIRIT_DEBUG_NODE(strng);<br>BOOST_SPIRIT_DEBUG_NODE(number);<br>BOOST_SPIRIT_DEBUG_NODE(symbol);<br>BOOST_SPIRIT_DEBUG_NODE(symbol_constant);<br>
BOOST_SPIRIT_DEBUG_NODE(array);<br>BOOST_SPIRIT_DEBUG_NODE(array_constant);<br>BOOST_SPIRIT_DEBUG_NODE(character_constant);<br>BOOST_SPIRIT_DEBUG_NODE(any_rnumber);<br>BOOST_SPIRIT_DEBUG_NODE(any_inumber);<br>};<br><br>rule&lt;ScannerT&gt; const&amp; start() const { return program; }<br>
<br>rule&lt;ScannerT&gt; <br>  program, method, message_pattern, temporaries, <br>  primitive_declaration, identifier,<br>  variable_name, unary_selector, binary_selector, keyword, argument_name,<br>  statements, expression, message_expression, primary, cascaded_message_expression,<br>
  literal, block, assignment_op, unary_expression, binary_expression,<br>  keyword_expression, binary_object_description, unary_object_description, <br>  character_constant, array_constant, symbol_constant, array, symbol, number, strng,<br>
  any_inumber, any_rnumber;<br>    };<br>};<br><br>int main(int /*argc*/, char* /*argv[]*/) {<br>    cout &lt;&lt; &quot;Write code in just a line\n\n&quot; ;<br><br>    st_grammar g;<br>    BOOST_SPIRIT_DEBUG_NODE(g);<br>
<br>    string str;<br>    while (getline(cin, str))<br>    {<br>        if (str[0] == &#39;z&#39; || str[0] == &#39;Z&#39; )<br>            break;<br><br>        if (parse(str.c_str(), g, space_p).full)<br>        {<br>            cout &lt;&lt; &quot;parsing succeeded\n&quot;;<br>
        }<br>        else<br>        {<br>            cout &lt;&lt; &quot;parsing failed\n&quot;;<br>        }<br>    }<br>    cout &lt;&lt; &quot;Bye... :-) \n\n&quot;;<br>    return 0;<br>}<br><br>Cheers,<br><br>Hernán<br>