Example #1
0
        int here_document(int term, int indent)
        {
            int c;
            string line = String.Empty;
            RNode list = null;
            int linesave = thread.line;

            newtok();
            switch (term) {
            case '\'':
                goto case '`';
            case '"':
                goto case '`';
            case '`':
                while ((c = nextc()) != term) {
                    tokadd(c);
                }
                if (term == '\'') term = '\0';
                break;

            default:
                c = term;
                term = '"';
                if (!is_identchar(c)) {
                    ruby.warn("use of bare << to mean <<\"\" is deprecated");
                    break;
                }
                while (is_identchar(c)) {
                    tokadd(c);
                    c = nextc();
                }
                pushback(c);
                break;
            }
            string lastline_save = lastline;
            int offset_save = pcur - pbeg;
            string eos = string.Copy(tok());
            int len = eos.Length;

            string str = String.Empty;
            for (;;) {
                lastline = line = getline();
                if (line == null) {
                    thread.line = linesave;
                    thread.CompileError("can't find string \"" + eos + "\" anywhere before EOF");
                    return 0;
                }
                thread.line++;
                string p = line;
                if (indent > 0) {
                    while (p.Length > 0 && (p[0] == ' ' || p[0] == '\t')) {
                        p = p.Substring(1);
                    }
                }
                if (String.Compare(eos, 0, p, 0, len) == 0) {
                    if (p[len] == '\n' || p[len] == '\r')
                        break;
                    if (len == line.Length)
                        break;
                }
                pbeg = pcur = 0;
                pend = pcur + line.Length;
            retry:
                switch (parse_string(term, '\n', '\n')) {
                case Token.tSTRING:
                    // fall down to the next case
                case Token.tXSTRING:
                    {
                    yylval = (string)yylval + "\n";
                    }
                    if (list == null) {
                        str += (string)yylval;
                    }
                    else {
                        RNode.list_append(thread, list, new RNStr(thread, ruby, (string)yylval));
                    }
                    break;
                case Token.tDSTRING:
                    if (list == null) list = new RNDStr(thread, ruby, str);
                    goto case Token.tDXSTRING;
                case Token.tDXSTRING:
                    if (list == null) list = new RNDXStr(thread, ruby, str);

                    RNode.list_append(thread, (RNode)yylval, new RNStr(thread, ruby, "\n"));
                    RNStr val = new RNStr((RNStr)yylval);
                    yylval = new RNArray(thread, val);
                    ((RNode)yylval).next = ((RNode)yylval).head.next;
                    RNode.list_concat(list, (RNode)yylval);
                    break;

                case 0:
                    thread.line = linesave;
                    thread.CompileError("can't find string \"" + eos + "\" anywhere before EOF");
                    return 0;
                }
                if (pcur != pend) {
                    goto retry;
                }
            }
            lastline = lastline_save;
            pbeg = 0;
            pend = lastline.Length;
            pcur = offset_save;

            lex_state = EXPR.END;
            heredoc_end = thread.line;
            thread.line = linesave;
            if (list != null) {
                list.SetLine(linesave+1);
                yylval = list;
            }
            switch (term) {
            case '\0':
                goto case '"';
            case '\'':
                goto case '"';
            case '"':
                if (list != null) return Token.tDSTRING;
                yylval = str;
                return Token.tSTRING;
            case '`':
                if (list != null) return Token.tDXSTRING;
                yylval = str;
                return Token.tXSTRING;
            }
            return 0;
        }
Example #2
0
        int parse_string(int func, int term, int paren)
        {
            int c;
            RNode list = null;
            int strstart;
            int nest = 0;

            if (func == '\'') {
                return parse_qstring(term, paren);
            }
            if (func == 0) {                /* read 1 line for heredoc */
                                /* -1 for chomp */
                yylval = lastline.Substring(pbeg, pend - pbeg - 1);
                pcur = pend;
                return Token.tSTRING;
            }
            strstart = thread.line;
            newtok();
            while ((c = nextc()) != term || nest > 0) {
                if (c == -1) {
                    thread.line = strstart;
                    thread.CompileError("unterminated string meets end of file");
                    return 0;
                }
                /*
                if (ismbchar(c)) {
                    int i, len = mbclen(c)-1;

                    for (i = 0; i < len; i++) {
                        tokadd(c);
                        c = nextc();
                    }
                }
                */
                else if (c == '#') {
                    list = str_extend(list, term);
                    if (list is RNEOF)
                    {
                        thread.line = strstart;
                        thread.CompileError("unterminated string meets end of file");
                        return 0;
                    }
                    continue;
                }
                else if (c == '\\') {
                    c = nextc();
                    if (c == '\n')
                        continue;
                    if (c == term) {
                        tokadd(c);
                    }
                    else {
                        pushback(c);
                        if (func != '"') tokadd('\\');
                        tokadd(read_escape());
                    }
                    continue;
                }
                if (paren != 0) {
                    if (c == paren) nest++;
                    if (c == term && nest-- == 0) break;
                }
                tokadd(c);
            }

            lex_state = EXPR.END;

            if (list != null) {
                list.SetLine(strstart);
                if (toklen() > 0) {
                    RNode.list_append(thread, list, new RNStr(thread, ruby, tok()));
                }
                yylval = list;
                if (func == '`') {
                    yylval = new RNDXStr(list);
                    return Token.tDXSTRING;
                }
                else {
                    return Token.tDSTRING;
                }
            }
            else {
                yylval = tok();
                return (func == '`') ? Token.tXSTRING : Token.tSTRING;
            }
        }