aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/lexer.l
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-05-01 14:01:47 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-05-01 14:01:47 +0000
commit0064599a27ec44880e4ff6fa19f453e610b5ef07 (patch)
tree50289edc19dc99d5423ce8f57b99c5b8eb5597c1 /src/libexpr/lexer.l
parent6cecad2be0f7ced82658ec2a86bcf61583487959 (diff)
* 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.l41
1 files changed, 32 insertions, 9 deletions
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l
index d5a14f517..47f2bca1e 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);
+}