Ok, I managed to get this to work, and ultimately it was quite easy. First you do this in flex:
'.* { yylval.s = g_string_new(strndup(yytext + 1, yyleng - 1)); return QUOTEREM; } // short form in MS !.* { yylval.s = g_string_new(strndup(yytext + 1, yyleng - 1)); return BANGREM; } // later MS allow bang as well Then in your bison you do this: statements: statement { $$ = g_list_prepend(NULL, $1); } | statement ':' statements { $$ = g_list_prepend($3, $1); } | statements QUOTEREM { $$ = g_list_prepend($1, NULL); } | statements BANGREM { $$ = g_list_prepend($1, NULL); } ; and finally: | REM { statement_t *new = make_statement(REM); new->parms.rem = yylval.s; $$ = new; } | QUOTEREM { statement_t *new = make_statement(QUOTEREM); new->parms.rem = yylval.s; $$ = new; } | BANGREM { statement_t *new = make_statement(BANGREM); new->parms.rem = yylval.s; $$ = new; } Presto! More work than I would have liked, but doesn't really upset the syntax too badly and is still self-documented to a good degree.