なかだです。

At Tue, 17 Sep 2002 22:52:00 +0900,
Paul Brannan wrote:
> I do recall one of the apocalypses mentioning a perl rfc that proposed a
> <<< operator for 'here documents', which would remove whitespace from
> the 'here document' (at compile-time) that matched the whitespace in
> front of the terminator.  Doesn't seem like a bad idea for either perl
> or ruby.

しばらく前のruby-coreの話ですが、こういうのはどうでしょうか。

    p <<-|EOS
      |  foo
      |    bar
    EOS
    # => "  foo\n    bar\n"

つまり、<<-とterminatorの間にクォーテーション以外の記号があった場合、
行頭の空白とその記号までを削除します。その記号がなければエラーです。


Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.239 diff -u -2 -p -r1.239 parse.y --- parse.y 30 Dec 2002 22:56:21 -0000 1.239 +++ parse.y 1 Jan 2003 00:49:46 -0000 @@ -2859,4 +2859,5 @@ regx_options() #define STR_FUNC_SYMBOL 0x10 #define STR_FUNC_INDENT 0x20 +#define STR_FUNC_LSTRIP 0x40 enum string_type { @@ -3020,4 +3021,5 @@ heredoc_identifier() { int c = nextc(), term, func = 0, len; + unsigned char margin = 0; if (c == '-') { @@ -3025,4 +3027,5 @@ heredoc_identifier() func = STR_FUNC_INDENT; } + again: switch (c) { case '\'': @@ -3048,4 +3051,10 @@ heredoc_identifier() default: if (!is_identchar(c)) { + if (!margin && (func & STR_FUNC_INDENT) && ISPRINT(c) && !isspace(c)) { + func |= STR_FUNC_LSTRIP; + margin = (unsigned char)c; + c = nextc(); + goto again; + } pushback(c); if (func & STR_FUNC_INDENT) { @@ -3065,4 +3074,5 @@ heredoc_identifier() } + if (margin) tokadd(margin); tokfix(); len = lex_p - lex_pbeg; @@ -3101,5 +3111,5 @@ whole_match_p(eos, len, indent) while (*p && ISSPACE(*p)) p++; } - n= lex_pend - (p + len); + n = lex_pend - (p + len); if (n < 0 || n > 0 && p[len] != '\n' && p[len] != '\r') return Qfalse; if (strncmp(eos, p, len) == 0) return Qtrue; @@ -3112,5 +3122,5 @@ here_document(here) { int c, func, indent = 0; - char *eos, *p, *pend; + char *eos, *p, *pend, margin = 0; long len; VALUE str = 0; @@ -3119,4 +3129,5 @@ here_document(here) len = RSTRING(here->nd_lit)->len - 1; indent = (func = *eos++) & STR_FUNC_INDENT; + if (func & STR_FUNC_LSTRIP) margin = eos[--len]; if ((c = nextc()) == -1) { @@ -3136,4 +3147,11 @@ here_document(here) p = RSTRING(lex_lastline)->ptr; pend = lex_pend; + if (margin) { + while ((c = *p) == ' ' || c == '\t') p++; + if (margin && *p++ != margin) { + lex_p = p; + goto no_margin; + } + } if (pend > p) { switch (pend[-1]) { @@ -3173,5 +3191,11 @@ here_document(here) } do { - pushback(c); + if (margin && was_bol()) { + while (c == ' ' || c == '\t') c = nextc(); + if (margin && c != margin) goto no_margin; + } + else { + pushback(c); + } if ((c = tokadd_string(func, '\n', 0)) == -1) goto error; if (c != '\n') { @@ -3188,4 +3212,15 @@ here_document(here) yylval.node = NEW_STR(str); return tSTRING_CONTENT; + + no_margin: + { + char buf[40]; + sprintf(buf, "can't find left margin character \"%c\"", margin); + --lex_p; + yyerror(buf); + heredoc_restore(lex_strterm); + lex_strterm = 0; + return 0; + } }
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦