To top this thread off, I went with this:
/* DATA statements convert everything to a string */ <DATA_STATEMENT>{ [^,:\n]* { // eat any leading and trailing whitespace yytext = str_trim(yytext); // and quotes yytext = str_unquote(yytext); yylval.s = str_new(yytext); return STRING; } [,] { return ','; } // triggers the exprlist syntax /* colons or line-ends end the data statement and reset the state */ [:] { BEGIN(INITIAL); return ':'; } [\n] { BEGIN(INITIAL); return '\n'; } } It's worked with everything I've thrown at it from every book I could find. Hans noted that it would be best to do this in the patterns, and I agree, but working is a feature! Now I just have to get my matrix inversion working and we're good to release.