summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-02-11 14:55:00 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-02-11 14:55:00 +0000
commitb64a3e41202c86e5eaa410fe182b3dfdb2b0dc4c (patch)
treedfca666818ec67f8c525619dd4075d14b7ebb1ed /parse.y
parent0d2b4a6dd8df62fb796b05c734b1d97f1a6f1eda (diff)
merge revision(s) r42479,r42490,r42509,r43083,r43084,r43085: [Backport #8756] [Backport #9248]
* parse.y (rb_enc_symname_type): allow ID_ATTRSET for ID_INSTANCE, ID_GLOBAL, ID_CLASS, ID_JUNK too. [Bug #8756] * parse.y (rb_id_attrset): fix inconsistency with literals, allow ID_ATTRSET and return it itself, but ID_JUNK cannot make ID_ATTRSET. and raise a NameError instead of rb_bug() for invalid argument. * parse.y (rb_id_attrset, intern_str): allow junk attrset ID for Struct. * parse.y (rb_id_attrset): check if the argument is valid type as an attribute. * parse.y (rb_id_attrset): allow other than ID_ATTRSET. * parse.y (intern_str): ditto. try stem ID for ID_INSTANCE, ID_GLOBAL, ID_CLASS, ID_JUNK too. [Bug #8756] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@44911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y111
1 files changed, 76 insertions, 35 deletions
diff --git a/parse.y b/parse.y
index 9b5617d000..9f10260eae 100644
--- a/parse.y
+++ b/parse.y
@@ -8678,9 +8678,41 @@ block_dup_check_gen(struct parser_params *parser, NODE *node1, NODE *node2)
}
}
+static const char id_type_names[][9] = {
+ "LOCAL",
+ "INSTANCE",
+ "", /* INSTANCE2 */
+ "GLOBAL",
+ "ATTRSET",
+ "CONST",
+ "CLASS",
+ "JUNK",
+};
+
ID
rb_id_attrset(ID id)
{
+ if (!is_notop_id(id)) {
+ switch (id) {
+ case tAREF: case tASET:
+ return tASET; /* only exception */
+ }
+ rb_name_error(id, "cannot make operator ID :%s attrset", rb_id2name(id));
+ }
+ else {
+ int scope = (int)(id & ID_SCOPE_MASK);
+ switch (scope) {
+ case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
+ case ID_CONST: case ID_CLASS: case ID_JUNK:
+ break;
+ case ID_ATTRSET:
+ return id;
+ default:
+ rb_name_error(id, "cannot make %s ID %+"PRIsVALUE" attrset",
+ id_type_names[scope], ID2SYM(id));
+
+ }
+ }
id &= ~ID_SCOPE_MASK;
id |= ID_ATTRSET;
return id;
@@ -10062,8 +10094,11 @@ rb_enc_symname_p(const char *name, rb_encoding *enc)
return rb_enc_symname2_p(name, strlen(name), enc);
}
+#define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
+#define IDSET_ATTRSET_FOR_INTERN (~(~0U<<ID_SCOPE_MASK) & ~(1U<<ID_ATTRSET))
+
static int
-rb_enc_symname_type(const char *name, long len, rb_encoding *enc)
+rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_atttset)
{
const char *m = name;
const char *e = m + len;
@@ -10148,7 +10183,7 @@ rb_enc_symname_type(const char *name, long len, rb_encoding *enc)
++m;
break;
case '=':
- if (type != ID_CONST && type != ID_LOCAL) return -1;
+ if (!(allowed_atttset & (1U << type))) return -1;
type = ID_ATTRSET;
++m;
break;
@@ -10161,15 +10196,15 @@ rb_enc_symname_type(const char *name, long len, rb_encoding *enc)
int
rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
{
- return rb_enc_symname_type(name, len, enc) != -1;
+ return rb_enc_symname_type(name, len, enc, IDSET_ATTRSET_FOR_SYNTAX) != -1;
}
static int
-rb_str_symname_type(VALUE name)
+rb_str_symname_type(VALUE name, unsigned int allowed_atttset)
{
const char *ptr = StringValuePtr(name);
long len = RSTRING_LEN(name);
- int type = rb_enc_symname_type(ptr, len, rb_enc_get(name));
+ int type = rb_enc_symname_type(ptr, len, rb_enc_get(name), allowed_atttset);
RB_GC_GUARD(name);
return type;
}
@@ -10294,26 +10329,27 @@ intern_str(VALUE str)
}
}
}
-
- if (m[last] == '=') {
- /* attribute assignment */
- if (!rb_enc_symname2_p(name, last, enc))
- goto junk;
- id = rb_intern3(name, last, enc);
- if (id > tLAST_OP_ID && !is_attrset_id(id)) {
- enc = rb_enc_get(rb_id2str(id));
- id = rb_id_attrset(id);
- goto id_register;
- }
- id = ID_ATTRSET;
+ break;
+ }
+ if (name[last] == '=') {
+ /* attribute assignment */
+ if (last > 1 && name[last-1] == '=')
+ goto junk;
+ id = rb_intern3(name, last, enc);
+ if (id > tLAST_OP_ID && !is_attrset_id(id)) {
+ enc = rb_enc_get(rb_id2str(id));
+ id = rb_id_attrset(id);
+ goto id_register;
}
- else if (rb_enc_isupper(m[0], enc)) {
+ id = ID_ATTRSET;
+ }
+ else if (id == 0) {
+ if (rb_enc_isupper(m[0], enc)) {
id = ID_CONST;
- }
+ }
else {
id = ID_LOCAL;
}
- break;
}
if (!rb_enc_isdigit(*m, enc)) {
while (m <= name + last && is_identchar(m, e, enc)) {
@@ -10325,7 +10361,7 @@ intern_str(VALUE str)
}
}
}
- if (m - name < len) id = ID_JUNK;
+ if (id != ID_ATTRSET && m - name < len) id = ID_JUNK;
if (sym_check_asciionly(str)) symenc = rb_usascii_encoding();
new_id:
if (symenc != enc) rb_enc_associate(str, symenc);
@@ -10408,16 +10444,21 @@ rb_id2str(ID id)
}
if (is_attrset_id(id)) {
- ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
+ ID id_stem = (id & ~ID_SCOPE_MASK);
VALUE str;
- while (!(str = rb_id2str(id2))) {
- if (!is_local_id(id2)) return 0;
- id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
- }
+ do {
+ if (!!(str = rb_id2str(id_stem | ID_LOCAL))) break;
+ if (!!(str = rb_id2str(id_stem | ID_CONST))) break;
+ if (!!(str = rb_id2str(id_stem | ID_INSTANCE))) break;
+ if (!!(str = rb_id2str(id_stem | ID_GLOBAL))) break;
+ if (!!(str = rb_id2str(id_stem | ID_CLASS))) break;
+ if (!!(str = rb_id2str(id_stem | ID_JUNK))) break;
+ return 0;
+ } while (0);
str = rb_str_dup(str);
rb_str_cat(str, "=", 1);
- rb_intern_str(str);
+ register_symid_str(id, str);
if (st_lookup(global_symbols.id_str, id, &data)) {
VALUE str = (VALUE)data;
if (RBASIC(str)->klass == 0)
@@ -10600,43 +10641,43 @@ rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc)
int
rb_is_const_name(VALUE name)
{
- return rb_str_symname_type(name) == ID_CONST;
+ return rb_str_symname_type(name, 0) == ID_CONST;
}
int
rb_is_class_name(VALUE name)
{
- return rb_str_symname_type(name) == ID_CLASS;
+ return rb_str_symname_type(name, 0) == ID_CLASS;
}
int
rb_is_global_name(VALUE name)
{
- return rb_str_symname_type(name) == ID_GLOBAL;
+ return rb_str_symname_type(name, 0) == ID_GLOBAL;
}
int
rb_is_instance_name(VALUE name)
{
- return rb_str_symname_type(name) == ID_INSTANCE;
+ return rb_str_symname_type(name, 0) == ID_INSTANCE;
}
int
rb_is_attrset_name(VALUE name)
{
- return rb_str_symname_type(name) == ID_ATTRSET;
+ return rb_str_symname_type(name, IDSET_ATTRSET_FOR_INTERN) == ID_ATTRSET;
}
int
rb_is_local_name(VALUE name)
{
- return rb_str_symname_type(name) == ID_LOCAL;
+ return rb_str_symname_type(name, 0) == ID_LOCAL;
}
int
rb_is_method_name(VALUE name)
{
- switch (rb_str_symname_type(name)) {
+ switch (rb_str_symname_type(name, 0)) {
case ID_LOCAL: case ID_ATTRSET: case ID_JUNK:
return TRUE;
}
@@ -10646,7 +10687,7 @@ rb_is_method_name(VALUE name)
int
rb_is_junk_name(VALUE name)
{
- return rb_str_symname_type(name) == -1;
+ return rb_str_symname_type(name, IDSET_ATTRSET_FOR_SYNTAX) == -1;
}
#endif /* !RIPPER */