multiline support for strings

This commit is contained in:
BVK Chaitanya 2010-06-11 13:59:07 +05:30
parent 0ea7c4f93c
commit e2413da901
1 changed files with 91 additions and 23 deletions

View File

@ -58,6 +58,7 @@
#define YY_INPUT(buf,res,max) do { res = 0; } while (0)
/* forward declarations */
static int resplit (const char *input, yyscan_t yyscanner);
static void grub_lexer_yyfree (void *, yyscan_t yyscanner);
static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner);
static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner);
@ -120,14 +121,19 @@ NAME [[:alpha:]_][[:alnum:][:digit:]_]*
ESC \\.
VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\}
DQSTR \"([^\\\"]|{ESC})*\"
SQSTR \'[^\']*\'
DQSTR \"([^\"]|{ESC})*\"
SQSTR \'([^\'])*\'
WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
DQSTR2 {WORD}?\"({ESC}|[^\"])*\n
SQSTR2 {WORD}?\'({ESC}|[^\'])*\n
%x SPLIT
%x DQUOTE
%x SQUOTE
%x VAR
%x DQMULTILINE
%x SQMULTILINE
%%
@ -173,26 +179,55 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
{NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; }
{WORD} {
RECORD;
/* resplit yytext */
grub_dprintf ("lexer", "word: [%s]\n", yytext);
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
if (yy_scan_string (yytext, yyscanner))
{
yyextra->lexerstate->merge_start = 1;
yy_push_state (SPLIT, yyscanner);
}
else
{
grub_script_yyerror (yyextra, 0);
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
if (resplit (yytext, yyscanner))
{
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
}
{DQSTR2} {
yy_push_state (DQMULTILINE, yyscanner);
grub_script_lexer_ref (yyextra->lexerstate);
yymore ();
}
<DQMULTILINE>{
\"{WORD}? {
RECORD;
grub_script_lexer_deref (yyextra->lexerstate);
yy_pop_state (yyscanner);
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
if (resplit (yytext, yyscanner))
{
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
}
{ESC} { yymore(); }
[^\"] { yymore(); }
}
{SQSTR2} {
yy_push_state (SQMULTILINE, yyscanner);
grub_script_lexer_ref (yyextra->lexerstate);
yymore ();
}
.|\n {
grub_script_yyerror (yyextra, "unrecognized token");
return GRUB_PARSER_TOKEN_BAD;
<SQMULTILINE>{
\'{WORD}? {
RECORD;
grub_script_lexer_deref (yyextra->lexerstate);
yy_pop_state (yyscanner);
yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner);
if (resplit (yytext, yyscanner))
{
yypop_buffer_state (yyscanner);
return GRUB_PARSER_TOKEN_WORD;
}
}
{ESC} { yymore(); }
[^\'] { yymore(); }
}
/* Split word into multiple args */
@ -270,6 +305,7 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
(.|\n) { COPY (yytext, yyleng); }
}
. { /* ignore */ }
<<EOF>> {
yypop_buffer_state (yyscanner);
if (! grub_script_lexer_yywrap (yyextra))
@ -278,9 +314,29 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
return GRUB_PARSER_TOKEN_EOF;
}
}
%%
#if 0
int
yywrap (yyscan_t yyscanner)
{
char *line = 0;
struct grub_lexer_param *lexerstate = yyget_extra(yyscanner)->lexerstate;
grub_printf ("yywrap\n");
if (lexerstate->getline)
{
lexerstate->getline (&line, 1);
if (! line)
return 1;
yy_scan_string (line, yyscanner);
return 0;
}
return 1;
}
#endif
static void
grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused)))
{
@ -300,8 +356,6 @@ grub_lexer_yyrealloc (void *ptr, yy_size_t size,
return grub_realloc (ptr, size);
}
#define MAX(a,b) ((a) < (b) ? (b) : (a))
static void copy_string (struct grub_parser_param *parser, const char *str, unsigned hint)
{
int size;
@ -311,7 +365,7 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi
len = hint ? hint : grub_strlen (str);
if (parser->lexerstate->used + len >= parser->lexerstate->size)
{
size = MAX (len, parser->lexerstate->size) * 2;
size = grub_max (len, parser->lexerstate->size) * 2;
ptr = grub_realloc (parser->lexerstate->text, size);
if (!ptr)
{
@ -325,3 +379,17 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi
grub_strcpy (parser->lexerstate->text + parser->lexerstate->used - 1, str);
parser->lexerstate->used += len;
}
static int
resplit (const char *text, yyscan_t yyscanner)
{
/* resplit text */
if (yy_scan_string (text, yyscanner))
{
yyget_extra (yyscanner)->lexerstate->merge_start = 1;
yy_push_state (SPLIT, yyscanner);
return 0;
}
grub_script_yyerror (yyget_extra (yyscanner), 0);
return 1;
}