diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2006-05-01 14:01:47 +0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2006-05-01 14:01:47 +0000 |
commit | 0064599a27ec44880e4ff6fa19f453e610b5ef07 (patch) | |
tree | 50289edc19dc99d5423ce8f57b99c5b8eb5597c1 /src/libexpr/lexer.l | |
parent | 6cecad2be0f7ced82658ec2a86bcf61583487959 (diff) | |
download | guix-0064599a27ec44880e4ff6fa19f453e610b5ef07.tar.gz |
* String interpolation. Expressions like
"--with-freetype2-library=" + freetype + "/lib" can now be written as "--with-freetype2-library=${freetype}/lib" An arbitrary expression can be enclosed within ${...}, not just identifiers. * Escaping in string literals: \n, \r, \t interpreted as in C, any other character following \ is interpreted as-is. * Newlines are now allowed in string literals.
Diffstat (limited to 'src/libexpr/lexer.l')
-rw-r--r-- | src/libexpr/lexer.l | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index d5a14f517a..47f2bca1e6 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -3,6 +3,9 @@ %option never-interactive +%x STRING + + %{ #include <string.h> #include <aterm2.h> @@ -28,6 +31,9 @@ static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) } } +ATerm toATerm(const char * s); +ATerm unescapeStr(const char * s); + #define YY_USER_INIT initLoc(yylloc) #define YY_USER_ACTION adjustLoc(yylloc, yytext, yyleng); @@ -36,7 +42,6 @@ static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) ID [a-zA-Z\_][a-zA-Z0-9\_\']* INT [0-9]+ -STR \"[^\n\"]*\" PATH [a-zA-Z0-9\.\_\-\+]*(\/[a-zA-Z0-9\.\_\-\+]+)+ URI [a-zA-Z][a-zA-Z0-9\+\-\.]*\:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']+ @@ -61,19 +66,27 @@ inherit { return INHERIT; } \/\/ { return UPDATE; } \+\+ { return CONCAT; } -{ID} { yylval->t = ATmake("<str>", yytext); return ID; /* !!! alloc */ } +{ID} { yylval->t = toATerm(yytext); return ID; /* !!! alloc */ } {INT} { int n = atoi(yytext); /* !!! overflow */ yylval->t = ATmake("<int>", n); return INT; } -{STR} { int len = strlen(yytext); - yytext[len - 1] = 0; - yylval->t = ATmake("<str>", yytext + 1); - yytext[len - 1] = '\"'; - return STR; /* !!! alloc */ + +\" { BEGIN(STRING); return '"'; } +<STRING>([^\$\"\\]|\\.|\$[^\{\$])+ { +/* Note: a dollar *is* allowed as-is in a string, as long as it's + not followed by a open brace. This should probably be disallowed + eventually. */ + yylval->t = unescapeStr(yytext); /* !!! alloc */ + return STR; } -{PATH} { yylval->t = ATmake("<str>", yytext); return PATH; /* !!! alloc */ } -{URI} { yylval->t = ATmake("<str>", yytext); return URI; /* !!! alloc */ } +<STRING>\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } +<STRING>\" { BEGIN(INITIAL); return '"'; } +<STRING>. return yytext[0]; /* just in case: shouldn't be reached */ + + +{PATH} { yylval->t = toATerm(yytext); return PATH; /* !!! alloc */ } +{URI} { yylval->t = toATerm(yytext); return URI; /* !!! alloc */ } [ \t\n]+ /* eat up whitespace */ \#[^\n]* /* single-line comments */ @@ -83,3 +96,13 @@ inherit { return INHERIT; } %% + +/* Horrible, disgusting hack: allow the parser to set the scanner + start condition back to STRING. Necessary in interpolations like + "foo${expr}bar"; after the close brace we have to go back to the + STRING state. */ +void backToString(yyscan_t scanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*) scanner; + BEGIN(STRING); +} |