<div> </div><div>All, help. I've R'd TFM all week trying to figure this out, but am still confused (so please pardon the potential n00bness.) </div><div> </div><div>I have to parse a config file for an app I'm working on, whose format is basically of the format:</div>
<div>group MyGroup {</div><div>  tcpclient( host: foo, port: 49152 );</div><div>  udp( host: bar, port: 49152 ) > tcpserver( port: 11111 );</div><div>  udp:foo:49152.nonblocking = true;</div><div>}</div><div> </div><div>
>From what I've read on the Intertubes, it seems that the SOP for processing this is to define a main := which will match a particular line of the text and then upon matching call a another machine to "scan" the message. However, I'm not sure how to do that because it seem that regardless of whether I define main as a matcher or a scanner, executing the parser always seems to consume the text as it matches. For instance, when I parse the group definition, I can simply match on the word "group" and then pass the rest of the line (up to the {) in to the scanner and I can get 'MyGroup' out relatively easily. However, when I try to parse the first encapsulated line, I don't know whether I'm dealing with a string of the first line form or third line form (or if the command is "chained" as in the second line) until I've done a kleene star match of the entire line (up to the ;) at which point it seems that the parser has already consumed the entire line and when I pass it into a scanner the pointers are already at the next line. Do I need the store the starting pointer before the first main scan (and if so, how?) and then how would I tell the downstream scanner where to start? I thought of making a number of nested c++ "parser objects" but that just seem inherently wrong.</div>
<div> </div><div>Below is what I've written so far--just enough to hopefully pass the first two cases. Again, I don't know if I'm only a character or so off or if my mindset is completely off. Any help would be appreciated.</div>
<div> </div><div>--<br clear="all">Rob Harris<br>  Technological Pragmatist<br>  rob period harris shift-2 gmail decimal-point com<br>  "The universe tends towards maximum irony." --Jamie Zawinsky<br>
</div><div> </div><div><font face="courier new,monospace"> %%{ <br>    machine sas_scanner;</font></div><div><font face="courier new,monospace">    ml_comment = '/*' ( any )* :>> '*/';<br>    sl_comment = '//' [^\n]* '\n';<br>
    comment    = ml_comment | sl_comment;<br>    wspace     = comment | space+ ;</font></div><div><font face="courier new,monospace">    integer    = [0-9]*;<br>    float      = [0-9]* '.' [0-9]*;<br>    identifier = [a-zA-Z][a-zA-Z0-9]*;<br>
    fqsm       = [a-zA-Z] ( [a-zA-Z0-9:][a-zA-Z0-9_] )*; <br>    sqstring   = '\'' [^\n]* :>> '\'';<br>    dqstring   = '\"' [^\n]* :>> '\"';<br>    strvalue   = ( integer | float | identifier | sqstring | dqstring );</font></div>
<div><font face="courier new,monospace">    action DEBUG { fprintf( stderr, "state: %4d, char: %c\n", cs, *p ); }</font></div><div><font face="courier new,monospace">    action RESET { reset(); }<br>    action CRLF  { std::cout << std::endl << std::endl; }</font></div>
<div><font face="courier new,monospace">    action NAME  { m_name.append( 1, fc ); }<br>    action KEY   {  m_key.append( 1, fc ); }<br>    action VAL   {  m_val.append( 1, fc ); }<br>    action QKV <br>    {   <br>      printf( "[%s]=>[%s]\n", m_key.c_str(), m_val.c_str());<br>
      m_kvMap[ m_key ] = m_val;<br>      m_key.clear();<br>      m_val.clear();<br>    }   <br>    action SNAME { printf( "NAME: [%s]\n", m_name.c_str() ); }</font></div><div><font face="courier new,monospace">    kvpair = ( identifier space* ':' space* strvalue );</font></div>
<div><font face="courier new,monospace">    kvlist = ( space+ | kvpair | ',' space+ kvpair );</font></div><div><font face="courier new,monospace">    instantiation = ( identifier '(' kvlist* ')' );</font></div>
<div><font face="courier new,monospace"></font> </div><div><font face="courier new,monospace">    instantiation_chain = ( <br>      instantiation $NAME ( space* '>' space* instantiation )*<br>      ) $NAME >RESET ';' @SNAME;</font></div>
<div><font face="courier new,monospace"></font> </div><div><font face="courier new,monospace">    inst_chain_scanner :=<br>    |*  <br>      space+;<br>      identifier => { diff(); };<br>      strvalue => { diff(); };<br>
    *|; </font></div><div><font face="courier new,monospace"></font> </div><div><font face="courier new,monospace">    group_name = ( 'g' 'r' 'o' 'u' 'p' );</font></div><div><font face="courier new,monospace">    group_id = ( identifier - group_name ) @NAME;</font></div>
<div><font face="courier new,monospace">    group_line = ( group_name space+ group_id :>> space* '{' );</font></div><div><font face="Courier New"></font> </div><div><font face="courier new,monospace">    group_scanner :=<br>
    |*  <br>      space+ => { m_name.clear(); };<br>      group_name;<br>      group_id => { printf( ">> %s\n", m_name.c_str() ); };<br>      '{' => { fret; };<br>    *|; </font></div><div>
<font face="Courier New"></font> </div><div><font face="courier new,monospace">    main :=<br>    |*  <br>      wspace+;<br>      group_name => { fcall group_scanner; };<br>      instantiation_chain => { fcall inst_chain_scanner; };<br>
    *|; <br></font></div>