%x dqstring
WORD [^{}|&$;<> \t\n'"#]+
-VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
+DELIM [ \t]+
+BLANK ["]{2}|[']{2}
+NUMBER 0|[1-9][0-9]*
+VARNAME ([[:alpha:]][_[:alnum:]]*|{NUMBER}|[\?@\*#])
%%
- /* discard leading & trailing whitespace, but keep inter-word delimeters */
-^[ \t]+ ;
-[ \t]+$ ;
-[ \t]+ return TOKEN_DELIM;
+ /* discard whitespace, unless we're looking for inter-word delimiters */
+{DELIM} { if (yyget_extra(yyscanner)->inter_word) return TOKEN_DELIM; }
/* reserved words */
"[[" return TOKEN_LDSQBRACKET;
"until" return TOKEN_UTIL;
"while" return TOKEN_WHILE;
+ /* ignore quoted empty strings */
+{BLANK} {
+ yylval->word = create_word_text(yyget_extra(yyscanner), "");
+ yyget_extra(yyscanner)->inter_word = true;
+ return TOKEN_WORD;
+ }
/* anything that's not a metachar: return as a plain word */
{WORD} {
yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
yytext++;
yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
true);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
}
<sqstring>[^']+ {
yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
}
<dqstring>([^"\$]|\\\")+ {
yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
<dqstring>\${VARNAME} |
yytext++;
yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
false);
+ yyget_extra(yyscanner)->inter_word = true;
return TOKEN_WORD;
}
/* blocks */
-"{" return '{';
-"}" return '}';
+"{" { yyget_extra(yyscanner)->inter_word = false; return '{'; }
+"}" { yyget_extra(yyscanner)->inter_word = false; return '}'; }
/* end-of-line */
-[ \t]*(;|\n)[ \t]* return TOKEN_EOL;
+[ \t]*(;|\n)[ \t]* {
+ yyget_extra(yyscanner)->inter_word = false;
+ return TOKEN_EOL;
+ }
/* strip comments */
#.* ;