In Ruby, there are a lot of usages of colon.
- Symbol :aaa
- Symbol with single quotes :'aaa'
- Symbol with double quotes :"aaa"
- Conditional operator aaa ? bbb : ccc
- Class hierarchy A::B
The following is an excerpt from parse.y relates a colon:
case ':':
c = nextc();
if (c == ':') {
if (IS_BEG() ||
lex_state == EXPR_CLASS || (IS_ARG() && space_seen)) {
lex_state = EXPR_BEG;
return tCOLON3;
}
lex_state = EXPR_DOT;
return tCOLON2;
}
if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || (c != -1 && ISSPACE(c))) {
pushback(c);
lex_state = EXPR_BEG;
return ':';
}
switch (c) {
case '\'':
lex_strterm = NEW_STRTERM(str_ssym, c, 0);
break;
case '"':
lex_strterm = NEW_STRTERM(str_dsym, c, 0);
break;
default:
pushback(c);
break;
}
lex_state = EXPR_FNAME;
return tSYMBEG;
If the next character of ':' is ':', in a nutshell if '::' has come, it returns tCOLON3 (:: at the very left) or tCOLON2 (:: at the right hand). Otherwise if the colon is just after expressions, it's a conditional operator. Ditto if the next character is a space. Otherwise finally the colon is a prefix of symbol.
I've never known that we can have a newline after ::
!
class A::
B
end
It's valid.
OK... So, let's try to add a new literal :-)
which has equivalent to =>
.
diff --git a/parse.y b/parse.y
index e2e92ce..8e49bf4 100644
--- a/parse.y
+++ b/parse.y
@@ -7082,6 +7082,9 @@ parser_yylex(struct parser_params *parser)
case ':':
c = nextc();
+ if (c == '-' && nextc() == ')') {
+ return tASSOC;
+ }
if (c == ':') {
if (IS_BEG() ||
lex_state == EXPR_CLASS || (IS_ARG() && space_seen)) {
That's easy.
$ ./ruby -e 'p({ 1 :-) 2 })'
{1=>2}
cool!
No comments:
Post a Comment