From: Yusuke Endoh Date: 2011-10-04T00:19:24+09:00 Subject: [ruby-core:39878] Re: Discussion results (here documents with indents) Hello, 2011/10/4 Trans : > Yes, in fact #margin was born from the idea of %L. The downside of > #margin is that it requires more processing overhead, where as the > literal notation would be very fast (if it is possible to implement in > Ruby parser). Actually, I prefer %L, but didn't succeed to implement it. It is difficult to determine the end of %L. My patch requires an empty line at the end. Though, nobu may be able to overcome the difficulty? $ cat t.rb p %L!foo !bar !b#{ ?a }z $ ./miniruby t.rb "foo\nbar\nbaz" $ cat t.rb p %L!foo !bar !b#{ ?a }z p 1 $ ./miniruby t.rb t.rb:4: syntax error, unexpected tIDENTIFIER, expecting $end $ cat t.rb p %L!foo !bar !b#{ ?a }z p 1 $ ./miniruby t.rb "foo\nbar\nbaz" 1 diff --git a/parse.y b/parse.y index 437f534..4165a09 100644 --- a/parse.y +++ b/parse.y @@ -5878,7 +5878,7 @@ parser_tokadd_string(struct parser_params *parser, } while (0) while ((c = nextc()) != -1) { - if (paren && c == paren) { + if (paren && c == paren && !(func & STR_FUNC_INDENT)) { ++*nest; } else if (c == term) { @@ -5995,6 +5995,19 @@ parser_parse_string(struct parser_params *parser, NODE *quote) space = 1; } if (c == term && !quote->nd_nest) { + if (func & STR_FUNC_INDENT) { + do {c = nextc();} while (c != term && ISSPACE(c)); + if (c != paren) { + lex_state = EXPR_BEG; + pushback(c); + if (!(func & STR_FUNC_REGEXP)) return tSTRING_END; + set_yylval_num(0); + return tREGEXP_END; + } + set_yylval_str(STR_NEW2("\n")); + return tSTRING_CONTENT; + } + else { if (func & STR_FUNC_QWORDS) { quote->nd_func = -1; return ' '; @@ -6002,6 +6015,7 @@ parser_parse_string(struct parser_params *parser, NODE *quote) if (!(func & STR_FUNC_REGEXP)) return tSTRING_END; set_yylval_num(regx_options()); return tREGEXP_END; + } } if (space) { pushback(c); @@ -7563,9 +7577,14 @@ parser_yylex(struct parser_params *parser) if (IS_BEG()) { int term; int paren; + int indent; c = nextc(); quotation: + if (c == 'L') { + indent = STR_FUNC_INDENT; + c = nextc(); + } if (c == -1 || !ISALNUM(c)) { term = c; c = 'Q'; @@ -7587,14 +7606,18 @@ parser_yylex(struct parser_params *parser) else if (term == '{') term = '}'; else if (term == '<') term = '>'; else paren = 0; + if (indent) { + paren = term; + term = '\n'; + } switch (c) { case 'Q': - lex_strterm = NEW_STRTERM(str_dquote, term, paren); + lex_strterm = NEW_STRTERM(str_dquote | indent, term, paren); return tSTRING_BEG; case 'q': - lex_strterm = NEW_STRTERM(str_squote, term, paren); + lex_strterm = NEW_STRTERM(str_squote | indent, term, paren); return tSTRING_BEG; case 'W': -- Yusuke Endoh