* Indented strings.
This commit is contained in:
		
							parent
							
								
									a60317f20f
								
							
						
					
					
						commit
						d4f0b0fc6c
					
				
					 7 changed files with 65 additions and 70 deletions
				
			
		|  | @ -67,6 +67,7 @@ void run(Strings args) | ||||||
|     doTest(state, "__add 1 2"); |     doTest(state, "__add 1 2"); | ||||||
|     doTest(state, "null"); |     doTest(state, "null"); | ||||||
|     doTest(state, "\"foo\""); |     doTest(state, "\"foo\""); | ||||||
|  |     doTest(state, "''\n  foo\n  bar\n    ''"); | ||||||
|     doTest(state, "let s = \"bar\"; in \"foo${s}\""); |     doTest(state, "let s = \"bar\"; in \"foo${s}\""); | ||||||
|     doTest(state, "if true then 1 else 2"); |     doTest(state, "if true then 1 else 2"); | ||||||
|     doTest(state, "if false then 1 else 2"); |     doTest(state, "if false then 1 else 2"); | ||||||
|  |  | ||||||
|  | @ -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) | void ExprInt::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     mkInt(v, n); |     mkInt(v, n); | ||||||
|  |  | ||||||
|  | @ -111,10 +111,11 @@ inherit     { return INHERIT; } | ||||||
| 
 | 
 | ||||||
| \"          { BEGIN(STRING); return '"'; } | \"          { BEGIN(STRING); return '"'; } | ||||||
| <STRING>([^\$\"\\]|\$[^\{\"]|\\.)+ { | <STRING>([^\$\"\\]|\$[^\{\"]|\\.)+ { | ||||||
| /* !!! Not quite right: we want a follow restriction on "$", it |               /* !!! Not quite right: we want a follow restriction on | ||||||
|    shouldn't be followed by a "{".  Right now "$\"" will be consumed |                  "$", it shouldn't be followed by a "{".  Right now | ||||||
|    as part of a string, rather than a "$" followed by the string |                  "$\"" will be consumed as part of a string, rather | ||||||
|    terminator.  Disallow "$\"" for now. */ |                  than a "$" followed by the string terminator. | ||||||
|  |                  Disallow "$\"" for now. */ | ||||||
|               yylval->e = unescapeStr(yytext); |               yylval->e = unescapeStr(yytext); | ||||||
|               return STR; |               return STR; | ||||||
|             } |             } | ||||||
|  | @ -124,25 +125,25 @@ inherit     { return INHERIT; } | ||||||
| 
 | 
 | ||||||
| \'\'(\ *\n)?     { BEGIN(IND_STRING); return IND_STRING_OPEN; } | \'\'(\ *\n)?     { BEGIN(IND_STRING); return IND_STRING_OPEN; } | ||||||
| <IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ { | <IND_STRING>([^\$\']|\$[^\{\']|\'[^\'\$])+ { | ||||||
|                    //yylval->t = makeIndStr(toATerm(yytext)); |                    yylval->e = new ExprIndStr(yytext); | ||||||
|                    return IND_STR; |                    return IND_STR; | ||||||
|                  } |                  } | ||||||
| <IND_STRING>\'\'\$ { | <IND_STRING>\'\'\$ { | ||||||
|                    //yylval->t = makeIndStr(toATerm("$")); |                    yylval->e = new ExprIndStr("$"); | ||||||
|                    return IND_STR; |                    return IND_STR; | ||||||
|                  } |                  } | ||||||
| <IND_STRING>\'\'\' { | <IND_STRING>\'\'\' { | ||||||
|                    //yylval->t = makeIndStr(toATerm("''")); |                    yylval->e = new ExprIndStr("''"); | ||||||
|                    return IND_STR; |                    return IND_STR; | ||||||
|                  } |                  } | ||||||
| <IND_STRING>\'\'\\. { | <IND_STRING>\'\'\\. { | ||||||
|                    //yylval->t = unescapeStr(yytext + 2); |                    yylval->e = new ExprIndStr(yytext + 2); | ||||||
|                    return IND_STR; |                    return IND_STR; | ||||||
|                  } |                  } | ||||||
| <IND_STRING>\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } | <IND_STRING>\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } | ||||||
| <IND_STRING>\'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; } | <IND_STRING>\'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; } | ||||||
| <IND_STRING>\'   { | <IND_STRING>\'   { | ||||||
|                    //yylval->t = makeIndStr(toATerm("'")); |                    yylval->e = new ExprIndStr("'"); | ||||||
|                    return IND_STR; |                    return IND_STR; | ||||||
|                  } |                  } | ||||||
| <IND_STRING>.    return yytext[0]; /* just in case: shouldn't be reached */ | <IND_STRING>.    return yytext[0]; /* just in case: shouldn't be reached */ | ||||||
|  |  | ||||||
|  | @ -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) | void ExprInt::show(std::ostream & str) | ||||||
| { | { | ||||||
|     str << n; |     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) | static void varsBoundByPattern(ATermMap & map, Pattern pat) | ||||||
| { | { | ||||||
|     ATerm name; |     ATerm name; | ||||||
|  |  | ||||||
|  | @ -35,11 +35,8 @@ struct EvalState; | ||||||
| 
 | 
 | ||||||
| struct Expr | struct Expr | ||||||
| { | { | ||||||
|     virtual void show(std::ostream & str) = 0; |     virtual void show(std::ostream & str); | ||||||
|     virtual void eval(EvalState & state, Env & env, Value & v) |     virtual void eval(EvalState & state, Env & env, Value & v); | ||||||
|     { |  | ||||||
|         throw Error("not implemented"); |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| std::ostream & operator << (std::ostream & str, Expr & e); | std::ostream & operator << (std::ostream & str, Expr & e); | ||||||
|  | @ -62,6 +59,13 @@ struct ExprString : Expr | ||||||
|     COMMON_METHODS |     COMMON_METHODS | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /* Temporary class used during parsing of indented strings. */ | ||||||
|  | struct ExprIndStr : Expr | ||||||
|  | { | ||||||
|  |     string s; | ||||||
|  |     ExprIndStr(const string & s) : s(s) { }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct ExprPath : Expr | struct ExprPath : Expr | ||||||
| { | { | ||||||
|     string s; |     string s; | ||||||
|  | @ -206,10 +210,6 @@ struct TermFun | ||||||
| ATerm bottomupRewrite(TermFun & f, ATerm e); | 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.
 | /* Check whether all variables are defined in the given expression.
 | ||||||
|    Throw an exception if this isn't the case. */ |    Throw an exception if this isn't the case. */ | ||||||
| void checkVarDefs(const ATermMap & def, Expr e); | void checkVarDefs(const ATermMap & def, Expr e); | ||||||
|  |  | ||||||
|  | @ -174,11 +174,12 @@ static void checkPatternVars(ATerm pos, Pattern pat) | ||||||
|     ATermMap map; |     ATermMap map; | ||||||
|     checkPatternVars(pos, map, pat); |     checkPatternVars(pos, map, pat); | ||||||
| } | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Expr stripIndentation(ATermList es) | static Expr * stripIndentation(vector<Expr *> & es) | ||||||
| { | { | ||||||
|     if (es == ATempty) return makeStr(""); |     if (es.empty()) return new ExprString(""); | ||||||
|      |      | ||||||
|     /* Figure out the minimum indentation.  Note that by design |     /* Figure out the minimum indentation.  Note that by design | ||||||
|        whitespace-only final lines are not taken into account.  (So |        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 */ |     bool atStartOfLine = true; /* = seen only whitespace in the current line */ | ||||||
|     unsigned int minIndent = 1000000; |     unsigned int minIndent = 1000000; | ||||||
|     unsigned int curIndent = 0; |     unsigned int curIndent = 0; | ||||||
|     ATerm e; |     foreach (vector<Expr *>::iterator, i, es) { | ||||||
|     for (ATermIterator i(es); i; ++i) { |         ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i); | ||||||
|         if (!matchIndStr(*i, e)) { |         if (!e) { | ||||||
|             /* Anti-quotations end the current start-of-line whitespace. */ |             /* Anti-quotations end the current start-of-line whitespace. */ | ||||||
|             if (atStartOfLine) { |             if (atStartOfLine) { | ||||||
|                 atStartOfLine = false; |                 atStartOfLine = false; | ||||||
|  | @ -196,12 +197,11 @@ static Expr stripIndentation(ATermList es) | ||||||
|             } |             } | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|         string s = aterm2String(e); |         for (unsigned int j = 0; j < e->s.size(); ++j) { | ||||||
|         for (unsigned int j = 0; j < s.size(); ++j) { |  | ||||||
|             if (atStartOfLine) { |             if (atStartOfLine) { | ||||||
|                 if (s[j] == ' ') |                 if (e->s[j] == ' ') | ||||||
|                     curIndent++; |                     curIndent++; | ||||||
|                 else if (s[j] == '\n') { |                 else if (e->s[j] == '\n') { | ||||||
|                     /* Empty line, doesn't influence minimum |                     /* Empty line, doesn't influence minimum | ||||||
|                        indentation. */ |                        indentation. */ | ||||||
|                     curIndent = 0; |                     curIndent = 0; | ||||||
|  | @ -209,7 +209,7 @@ static Expr stripIndentation(ATermList es) | ||||||
|                     atStartOfLine = false; |                     atStartOfLine = false; | ||||||
|                     if (curIndent < minIndent) minIndent = curIndent; |                     if (curIndent < minIndent) minIndent = curIndent; | ||||||
|                 } |                 } | ||||||
|             } else if (s[j] == '\n') { |             } else if (e->s[j] == '\n') { | ||||||
|                 atStartOfLine = true; |                 atStartOfLine = true; | ||||||
|                 curIndent = 0; |                 curIndent = 0; | ||||||
|             } |             } | ||||||
|  | @ -217,37 +217,37 @@ static Expr stripIndentation(ATermList es) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Strip spaces from each line. */ |     /* Strip spaces from each line. */ | ||||||
|     ATermList es2 = ATempty; |     vector<Expr *> * es2 = new vector<Expr *>; | ||||||
|     atStartOfLine = true; |     atStartOfLine = true; | ||||||
|     unsigned int curDropped = 0; |     unsigned int curDropped = 0; | ||||||
|     unsigned int n = ATgetLength(es); |     unsigned int n = es.size(); | ||||||
|     for (ATermIterator i(es); i; ++i, --n) { |     for (vector<Expr *>::iterator i = es.begin(); i != es.end(); ++i, --n) { | ||||||
|         if (!matchIndStr(*i, e)) { |         ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i); | ||||||
|  |         if (!e) { | ||||||
|             atStartOfLine = false; |             atStartOfLine = false; | ||||||
|             curDropped = 0; |             curDropped = 0; | ||||||
|             es2 = ATinsert(es2, *i); |             es2->push_back(*i); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         string s = aterm2String(e); |  | ||||||
|         string s2; |         string s2; | ||||||
|         for (unsigned int j = 0; j < s.size(); ++j) { |         for (unsigned int j = 0; j < e->s.size(); ++j) { | ||||||
|             if (atStartOfLine) { |             if (atStartOfLine) { | ||||||
|                 if (s[j] == ' ') { |                 if (e->s[j] == ' ') { | ||||||
|                     if (curDropped++ >= minIndent) |                     if (curDropped++ >= minIndent) | ||||||
|                         s2 += s[j]; |                         s2 += e->s[j]; | ||||||
|                 } |                 } | ||||||
|                 else if (s[j] == '\n') { |                 else if (e->s[j] == '\n') { | ||||||
|                     curDropped = 0; |                     curDropped = 0; | ||||||
|                     s2 += s[j]; |                     s2 += e->s[j]; | ||||||
|                 } else { |                 } else { | ||||||
|                     atStartOfLine = false; |                     atStartOfLine = false; | ||||||
|                     curDropped = 0; |                     curDropped = 0; | ||||||
|                     s2 += s[j]; |                     s2 += e->s[j]; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 s2 += s[j]; |                 s2 += e->s[j]; | ||||||
|                 if (s[j] == '\n') atStartOfLine = true; |                 if (e->s[j] == '\n') atStartOfLine = true; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -259,12 +259,11 @@ static Expr stripIndentation(ATermList es) | ||||||
|                 s2 = string(s2, 0, p + 1); |                 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); | void backToString(yyscan_t scanner); | ||||||
|  | @ -316,11 +315,10 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err | ||||||
| %type <e> expr_app expr_select expr_simple | %type <e> expr_app expr_select expr_simple | ||||||
| %type <list> expr_list | %type <list> expr_list | ||||||
| %type <attrs> binds | %type <attrs> binds | ||||||
| %type <ts> attrpath ind_string_parts |  | ||||||
| %type <formals> formals | %type <formals> formals | ||||||
| %type <formal> formal | %type <formal> formal | ||||||
| %type <ids> ids | %type <ids> ids attrpath | ||||||
| %type <string_parts> string_parts | %type <string_parts> string_parts ind_string_parts | ||||||
| %token <id> ID ATTRPATH | %token <id> ID ATTRPATH | ||||||
| %token <e> STR IND_STR | %token <e> STR IND_STR | ||||||
| %token <n> INT | %token <n> INT | ||||||
|  | @ -411,11 +409,9 @@ expr_simple | ||||||
|       else if ($2->size() == 1) $$ = $2->front(); |       else if ($2->size() == 1) $$ = $2->front(); | ||||||
|       else $$ = new ExprConcatStrings($2); |       else $$ = new ExprConcatStrings($2); | ||||||
|   } |   } | ||||||
|   /* |  | ||||||
|   | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { |   | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { | ||||||
|       $$ = stripIndentation(ATreverse($2)); |       $$ = stripIndentation(*$2); | ||||||
|   } |   } | ||||||
|   */ |  | ||||||
|   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } |   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } | ||||||
|   | URI { $$ = new ExprString($1); } |   | URI { $$ = new ExprString($1); } | ||||||
|   | '(' expr ')' { $$ = $2; } |   | '(' expr ')' { $$ = $2; } | ||||||
|  | @ -437,9 +433,9 @@ string_parts | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| ind_string_parts | ind_string_parts | ||||||
|   : ind_string_parts IND_STR { $$ = ATinsert($1, $2); } |   : ind_string_parts IND_STR { $$ = $1; $1->push_back($2); } | ||||||
|   | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = ATinsert($1, $3); } |   | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = $1; $1->push_back($3); } | ||||||
|   | { $$ = ATempty; } |   | { $$ = new vector<Expr *>; } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
| binds | binds | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ void processExpr(EvalState & state, const Strings & attrPaths, | ||||||
|     bool evalOnly, bool xmlOutput, Expr * e) |     bool evalOnly, bool xmlOutput, Expr * e) | ||||||
| { | { | ||||||
|     if (parseOnly) |     if (parseOnly) | ||||||
|         std::cout << format("%1%\n"); |         std::cout << format("%1%\n") % *e; | ||||||
|     else |     else | ||||||
|         foreach (Strings::const_iterator, i, attrPaths) { |         foreach (Strings::const_iterator, i, attrPaths) { | ||||||
|             Value v; |             Value v; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue