Skip to content

Commit

Permalink
Fixes #2088. Allow partial but not actual esoteric interpolation sequ…
Browse files Browse the repository at this point in the history
…ences to be regexp values
  • Loading branch information
enebo committed Nov 3, 2014
1 parent 78999e2 commit 8801d55
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 15 deletions.
15 changes: 14 additions & 1 deletion core/src/main/java/org/jruby/lexer/yacc/RubyYaccLexer.java
Expand Up @@ -1596,7 +1596,20 @@ private int dollar() throws IOException {
return identifierToken(Tokens.tGVAR, tokenBuffer.toString().intern());
}
}


// FIXME: I added number gvars here and they did not.
public boolean isGlobalCharPunct(int c) {
switch (c) {
case '_': case '~': case '*': case '$': case '?': case '!': case '@':
case '/': case '\\': case ';': case ',': case '.': case '=': case ':':
case '<': case '>': case '\"': case '-': case '&': case '`': case '\'':
case '+': case '1': case '2': case '3': case '4': case '5': case '6':
case '7': case '8': case '9': case '0':
return true;
}
return isIdentifierChar(c);
}

private int dot() throws IOException {
int c;

Expand Down
86 changes: 72 additions & 14 deletions core/src/main/java/org/jruby/lexer/yacc/StringTerm.java
Expand Up @@ -81,6 +81,74 @@ private int endFound(RubyYaccLexer lexer, LexerSource src) throws IOException {
return Tokens.tSTRING_END;
}

// Return of 0 means failed to find anything. Non-zero means return that from lexer.
private int parsePeekVariableName(RubyYaccLexer lexer, LexerSource src) throws IOException {
int c = src.read(); // byte right after #
int significant = -1;
switch (c) {
case '$': { // we unread back to before the $ so next lex can read $foo
int c2 = src.read();

if (c2 == '-') {
int c3 = src.read();

if (c3 == RubyYaccLexer.EOF) {
src.unread(c3); src.unread(c2);
return 0;
}

significant = c3; // $-0 potentially
src.unread(c3); src.unread(c2);
break;
} else if (lexer.isGlobalCharPunct(c2)) { // $_ potentially
src.unread(c2); src.unread(c);
lexer.setValue(new Token("#" + c2, lexer.getPosition()));
return Tokens.tSTRING_DVAR;
}

significant = c2; // $FOO potentially
src.unread(c2);
break;
}
case '@': { // we unread back to before the @ so next lex can read @foo
int c2 = src.read();

if (c2 == '@') {
int c3 = src.read();

if (c3 == RubyYaccLexer.EOF) {
src.unread(c3); src.unread(c2);
return 0;
}

significant = c3; // #@@foo potentially
src.unread(c3); src.unread(c2);
break;
}

significant = c2; // #@foo potentially
src.unread(c2);
break;
}
case '{':
lexer.setValue(new Token("#" + c, lexer.getPosition()));
return Tokens.tSTRING_DBEG;
default:
// We did not find significant char after # so push it back to
// be processed as an ordinary string.
src.unread(c);
return 0;
}

if (significant != -1 && Character.isAlphabetic(significant) || significant == '_') {
src.unread(c);
lexer.setValue(new Token("#" + significant, lexer.getPosition()));
return Tokens.tSTRING_DVAR;
}

return 0;
}

public int parseString(RubyYaccLexer lexer, LexerSource src) throws IOException {
boolean spaceSeen = false;
int c;
Expand All @@ -105,22 +173,12 @@ public int parseString(RubyYaccLexer lexer, LexerSource src) throws IOException
lexer.getPosition();
return ' ';
}

ByteList buffer = createByteList(lexer);

ByteList buffer = createByteList(lexer);
if ((flags & RubyYaccLexer.STR_FUNC_EXPAND) != 0 && c == '#') {
c = src.read();
switch (c) {
case '$':
case '@':
src.unread(c);
lexer.setValue(new Token("#" + c, lexer.getPosition()));
return Tokens.tSTRING_DVAR;
case '{':
lexer.setValue(new Token("#" + c, lexer.getPosition()));
return Tokens.tSTRING_DBEG;
}
buffer.append((byte) '#');
int token = parsePeekVariableName(lexer, src);

if (token != 0) return token;
}
src.unread(c);

Expand Down

0 comments on commit 8801d55

Please sign in to comment.