From d4f0b0fc6cdb9ae2fd5fc057d621bc80b36a7b18 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 12 Apr 2010 22:03:27 +0000 Subject: [PATCH] * Indented strings. --- src/libexpr/eval-test.cc | 1 + src/libexpr/eval.cc | 6 +++ src/libexpr/lexer.l | 19 +++---- src/libexpr/nixexpr.cc | 19 ++----- src/libexpr/nixexpr.hh | 18 +++---- src/libexpr/parser.y | 70 ++++++++++++-------------- src/nix-instantiate/nix-instantiate.cc | 2 +- 7 files changed, 65 insertions(+), 70 deletions(-) diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc index dd8ead04a..782e36d38 100644 --- a/src/libexpr/eval-test.cc +++ b/src/libexpr/eval-test.cc @@ -67,6 +67,7 @@ void run(Strings args) doTest(state, "__add 1 2"); doTest(state, "null"); doTest(state, "\"foo\""); + doTest(state, "''\n foo\n bar\n ''"); doTest(state, "let s = \"bar\"; in \"foo${s}\""); doTest(state, "if true then 1 else 2"); doTest(state, "if false then 1 else 2"); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 21c22333b..62b493bbf 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -367,6 +367,12 @@ bool EvalState::evalBool(Env & env, Expr * e) } +void Expr::eval(EvalState & state, Env & env, Value & v) +{ + abort(); +} + + void ExprInt::eval(EvalState & state, Env & env, Value & v) { mkInt(v, n); diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index e905700fd..7aa05db8c 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -111,10 +111,11 @@ inherit { return INHERIT; } \" { BEGIN(STRING); return '"'; } ([^\$\"\\]|\$[^\{\"]|\\.)+ { -/* !!! Not quite right: we want a follow restriction on "$", it - shouldn't be followed by a "{". Right now "$\"" will be consumed - as part of a string, rather than a "$" followed by the string - terminator. Disallow "$\"" for now. */ + /* !!! Not quite right: we want a follow restriction on + "$", it shouldn't be followed by a "{". Right now + "$\"" will be consumed as part of a string, rather + than a "$" followed by the string terminator. + Disallow "$\"" for now. */ yylval->e = unescapeStr(yytext); return STR; } @@ -124,25 +125,25 @@ inherit { return INHERIT; } \'\'(\ *\n)? { BEGIN(IND_STRING); return IND_STRING_OPEN; } ([^\$\']|\$[^\{\']|\'[^\'\$])+ { - //yylval->t = makeIndStr(toATerm(yytext)); + yylval->e = new ExprIndStr(yytext); return IND_STR; } \'\'\$ { - //yylval->t = makeIndStr(toATerm("$")); + yylval->e = new ExprIndStr("$"); return IND_STR; } \'\'\' { - //yylval->t = makeIndStr(toATerm("''")); + yylval->e = new ExprIndStr("''"); return IND_STR; } \'\'\\. { - //yylval->t = unescapeStr(yytext + 2); + yylval->e = new ExprIndStr(yytext + 2); return IND_STR; } \$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } \'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; } \' { - //yylval->t = makeIndStr(toATerm("'")); + yylval->e = new ExprIndStr("'"); return IND_STR; } . return yytext[0]; /* just in case: shouldn't be reached */ diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index b044aaa94..6ef996bdc 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -15,6 +15,11 @@ std::ostream & operator << (std::ostream & str, Expr & e) } +void Expr::show(std::ostream & str) +{ + abort(); +} + void ExprInt::show(std::ostream & str) { str << n; @@ -152,20 +157,6 @@ ATerm bottomupRewrite(TermFun & f, ATerm e) } -Expr makeAttrs(const ATermMap & attrs) -{ - ATermList bnds = ATempty; - for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) { - Expr e; - ATerm pos; - if (!matchAttrRHS(i->value, e, pos)) - abort(); /* can't happen */ - bnds = ATinsert(bnds, makeBind(i->key, e, pos)); - } - return makeAttrs(bnds); -} - - static void varsBoundByPattern(ATermMap & map, Pattern pat) { ATerm name; diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index d6e088c41..725f9fe88 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -35,11 +35,8 @@ struct EvalState; struct Expr { - virtual void show(std::ostream & str) = 0; - virtual void eval(EvalState & state, Env & env, Value & v) - { - throw Error("not implemented"); - } + virtual void show(std::ostream & str); + virtual void eval(EvalState & state, Env & env, Value & v); }; std::ostream & operator << (std::ostream & str, Expr & e); @@ -62,6 +59,13 @@ struct ExprString : Expr COMMON_METHODS }; +/* Temporary class used during parsing of indented strings. */ +struct ExprIndStr : Expr +{ + string s; + ExprIndStr(const string & s) : s(s) { }; +}; + struct ExprPath : Expr { string s; @@ -206,10 +210,6 @@ struct TermFun ATerm bottomupRewrite(TermFun & f, ATerm e); -/* Create an attribute set expression from an Attrs value. */ -Expr makeAttrs(const ATermMap & attrs); - - /* Check whether all variables are defined in the given expression. Throw an exception if this isn't the case. */ void checkVarDefs(const ATermMap & def, Expr e); diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 83f454845..22ce7e3f3 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -174,11 +174,12 @@ static void checkPatternVars(ATerm pos, Pattern pat) ATermMap map; checkPatternVars(pos, map, pat); } +#endif -static Expr stripIndentation(ATermList es) +static Expr * stripIndentation(vector & es) { - if (es == ATempty) return makeStr(""); + if (es.empty()) return new ExprString(""); /* Figure out the minimum indentation. Note that by design whitespace-only final lines are not taken into account. (So @@ -186,9 +187,9 @@ static Expr stripIndentation(ATermList es) bool atStartOfLine = true; /* = seen only whitespace in the current line */ unsigned int minIndent = 1000000; unsigned int curIndent = 0; - ATerm e; - for (ATermIterator i(es); i; ++i) { - if (!matchIndStr(*i, e)) { + foreach (vector::iterator, i, es) { + ExprIndStr * e = dynamic_cast(*i); + if (!e) { /* Anti-quotations end the current start-of-line whitespace. */ if (atStartOfLine) { atStartOfLine = false; @@ -196,12 +197,11 @@ static Expr stripIndentation(ATermList es) } continue; } - string s = aterm2String(e); - for (unsigned int j = 0; j < s.size(); ++j) { + for (unsigned int j = 0; j < e->s.size(); ++j) { if (atStartOfLine) { - if (s[j] == ' ') + if (e->s[j] == ' ') curIndent++; - else if (s[j] == '\n') { + else if (e->s[j] == '\n') { /* Empty line, doesn't influence minimum indentation. */ curIndent = 0; @@ -209,7 +209,7 @@ static Expr stripIndentation(ATermList es) atStartOfLine = false; if (curIndent < minIndent) minIndent = curIndent; } - } else if (s[j] == '\n') { + } else if (e->s[j] == '\n') { atStartOfLine = true; curIndent = 0; } @@ -217,37 +217,37 @@ static Expr stripIndentation(ATermList es) } /* Strip spaces from each line. */ - ATermList es2 = ATempty; + vector * es2 = new vector; atStartOfLine = true; unsigned int curDropped = 0; - unsigned int n = ATgetLength(es); - for (ATermIterator i(es); i; ++i, --n) { - if (!matchIndStr(*i, e)) { + unsigned int n = es.size(); + for (vector::iterator i = es.begin(); i != es.end(); ++i, --n) { + ExprIndStr * e = dynamic_cast(*i); + if (!e) { atStartOfLine = false; curDropped = 0; - es2 = ATinsert(es2, *i); + es2->push_back(*i); continue; } - string s = aterm2String(e); string s2; - for (unsigned int j = 0; j < s.size(); ++j) { + for (unsigned int j = 0; j < e->s.size(); ++j) { if (atStartOfLine) { - if (s[j] == ' ') { + if (e->s[j] == ' ') { if (curDropped++ >= minIndent) - s2 += s[j]; + s2 += e->s[j]; } - else if (s[j] == '\n') { + else if (e->s[j] == '\n') { curDropped = 0; - s2 += s[j]; + s2 += e->s[j]; } else { atStartOfLine = false; curDropped = 0; - s2 += s[j]; + s2 += e->s[j]; } } else { - s2 += s[j]; - if (s[j] == '\n') atStartOfLine = true; + s2 += e->s[j]; + if (e->s[j] == '\n') atStartOfLine = true; } } @@ -258,13 +258,12 @@ static Expr stripIndentation(ATermList es) if (p != string::npos && s2.find_first_not_of(' ', p + 1) == string::npos) s2 = string(s2, 0, p + 1); } - - es2 = ATinsert(es2, makeStr(s2)); + + es2->push_back(new ExprString(s2)); } - return makeConcatStrings(ATreverse(es2)); + return new ExprConcatStrings(es2); } -#endif void backToString(yyscan_t scanner); @@ -316,11 +315,10 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err %type expr_app expr_select expr_simple %type expr_list %type binds -%type attrpath ind_string_parts %type formals %type formal -%type ids -%type string_parts +%type ids attrpath +%type string_parts ind_string_parts %token ID ATTRPATH %token STR IND_STR %token INT @@ -411,11 +409,9 @@ expr_simple else if ($2->size() == 1) $$ = $2->front(); else $$ = new ExprConcatStrings($2); } - /* | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { - $$ = stripIndentation(ATreverse($2)); + $$ = stripIndentation(*$2); } - */ | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } | URI { $$ = new ExprString($1); } | '(' expr ')' { $$ = $2; } @@ -437,9 +433,9 @@ string_parts ; ind_string_parts - : ind_string_parts IND_STR { $$ = ATinsert($1, $2); } - | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = ATinsert($1, $3); } - | { $$ = ATempty; } + : ind_string_parts IND_STR { $$ = $1; $1->push_back($2); } + | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = $1; $1->push_back($3); } + | { $$ = new vector; } ; binds diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 466c7b499..ba34fc63b 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -42,7 +42,7 @@ void processExpr(EvalState & state, const Strings & attrPaths, bool evalOnly, bool xmlOutput, Expr * e) { if (parseOnly) - std::cout << format("%1%\n"); + std::cout << format("%1%\n") % *e; else foreach (Strings::const_iterator, i, attrPaths) { Value v;