static void yyprint PARAMS ((FILE *, int, YYSTYPE));
static void yyerror PARAMS ((const char *));
+static int yylexname PARAMS ((void));
static inline int _yylex PARAMS ((void));
static int yylex PARAMS ((void));
static void init_reswords PARAMS ((void));
/* RID_AT_IMPLEMENTATION */ IMPLEMENTATION
};
+ifobjc
+/* Lookup table for ObjC keywords beginning with '@'. Crude but
+ hopefully effective. */
+#define N_at_reswords ((int) RID_AT_IMPLEMENTATION - (int)RID_AT_ENCODE + 1)
+static tree objc_rid_sans_at[N_at_reswords];
+end ifobjc
+
static void
init_reswords ()
{
C_RID_CODE (id) = reswords[i].rid;
C_IS_RESERVED_WORD (id) = 1;
ridpointers [(int) reswords[i].rid] = id;
+
+ifobjc
+ /* Enter ObjC @-prefixed keywords into the "sans" table
+ _without_ their leading at-sign. Again, all these
+ identifiers are reachable by the get_identifer table, so it's
+ not necessary to make objc_rid_sans_at a GC root. */
+ if (reswords[i].word[0] == '@')
+ objc_rid_sans_at[(int) reswords[i].rid - (int) RID_AT_ENCODE]
+ = get_identifier (reswords[i].word + 1);
+end ifobjc
}
ifobjc
save_and_forget_protocol_qualifiers ();
error ("%s before %s'\\x%x'", string, ell, val);
}
else if (last_token == CPP_STRING
- || last_token == CPP_WSTRING
- || last_token == CPP_OSTRING)
+ || last_token == CPP_WSTRING)
error ("%s before string constant", string);
else if (last_token == CPP_NUMBER
|| last_token == CPP_INT
error ("%s before '%s' token", string, NAME(last_token));
}
+static int
+yylexname ()
+{
+ tree decl;
+
+ if (C_IS_RESERVED_WORD (yylval.ttype))
+ {
+ enum rid rid_code = C_RID_CODE (yylval.ttype);
+ /* Return the canonical spelling for this keyword. */
+ yylval.ttype = ridpointers[(int) rid_code];
+ return rid_to_yy[(int) rid_code];
+ }
+
+ decl = lookup_name (yylval.ttype);
+ if (decl)
+ {
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return TYPENAME;
+ /* A user-invisible read-only initialized variable
+ should be replaced by its value.
+ We handle only strings since that's the only case used in C. */
+ else if (TREE_CODE (decl) == VAR_DECL
+ && DECL_IGNORED_P (decl)
+ && TREE_READONLY (decl)
+ && DECL_INITIAL (decl) != 0
+ && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+ {
+ tree stringval = DECL_INITIAL (decl);
+
+ /* Copy the string value so that we won't clobber anything
+ if we put something in the TREE_CHAIN of this one. */
+ yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
+ TREE_STRING_POINTER (stringval));
+ return STRING;
+ }
+ }
+ else if (doing_objc_thang)
+ {
+ tree objc_interface_decl = is_class_name (yylval.ttype);
+
+ if (objc_interface_decl)
+ {
+ yylval.ttype = objc_interface_decl;
+ return CLASSNAME;
+ }
+ }
+
+ return IDENTIFIER;
+}
+
+
static inline int
_yylex ()
{
- retry:
+ get_next:
last_token = c_lex (&yylval.ttype);
-
+ifobjc
+ reconsider:
+end ifobjc
switch (last_token)
{
case CPP_EQ: return '=';
case CPP_EOF:
if (cpp_pop_buffer (parse_in) == 0)
return 0;
- goto retry;
+ goto get_next;
case CPP_NAME:
- if (C_IS_RESERVED_WORD (yylval.ttype))
- {
- enum rid rid_code = C_RID_CODE (yylval.ttype);
- /* Return the canonical spelling for this keyword. */
- yylval.ttype = ridpointers[(int) rid_code];
- return rid_to_yy[(int) rid_code];
- }
-
- if (IDENTIFIER_POINTER (yylval.ttype)[0] == '@')
- {
- error ("invalid identifier `%s'", IDENTIFIER_POINTER (yylval.ttype));
- return IDENTIFIER;
- }
-
- {
- tree decl;
-
- decl = lookup_name (yylval.ttype);
-
- if (decl)
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- return TYPENAME;
- /* A user-invisible read-only initialized variable
- should be replaced by its value.
- We handle only strings since that's the only case used in C. */
- else if (TREE_CODE (decl) == VAR_DECL
- && DECL_IGNORED_P (decl)
- && TREE_READONLY (decl)
- && DECL_INITIAL (decl) != 0
- && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
- {
- tree stringval = DECL_INITIAL (decl);
-
- /* Copy the string value so that we won't clobber anything
- if we put something in the TREE_CHAIN of this one. */
- yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
- TREE_STRING_POINTER (stringval));
- return STRING;
- }
- }
- else if (doing_objc_thang)
- {
- tree objc_interface_decl = is_class_name (yylval.ttype);
-
- if (objc_interface_decl)
- {
- yylval.ttype = objc_interface_decl;
- return CLASSNAME;
- }
- }
-
- return IDENTIFIER;
- }
+ return yylexname ();
case CPP_INT:
case CPP_FLOAT:
case CPP_WSTRING:
return STRING;
- case CPP_OSTRING:
- return OBJC_STRING;
-
+ /* This token is Objective-C specific. It gives the next
+ token special significance. */
+ case CPP_ATSIGN:
+ifobjc
+ last_token = c_lex (&yylval.ttype);
+ if (last_token == CPP_STRING)
+ return OBJC_STRING;
+ else if (last_token == CPP_NAME)
+ {
+ int i;
+ for (i = 0; i < N_at_reswords; i++)
+ if (objc_rid_sans_at[i] == yylval.ttype)
+ {
+ int rid_code = i + (int) RID_AT_ENCODE;
+ yylval.ttype = ridpointers[rid_code];
+ return rid_to_yy[rid_code];
+ }
+ }
+ error ("syntax error at '@' token");
+ goto reconsider;
+end ifobjc
/* These tokens are C++ specific (and will not be generated
in C mode, but let's be cautious). */
case CPP_SCOPE:
/* These tokens should not survive translation phase 4. */
case CPP_HASH:
case CPP_PASTE:
- error ("syntax error before '%s' token", NAME(last_token));
- goto retry;
+ error ("syntax error at '%s' token", NAME(last_token));
+ goto get_next;
default:
abort ();
}
-
/* NOTREACHED */
}
case '}': result->type = CPP_CLOSE_BRACE; break;
case ';': result->type = CPP_SEMICOLON; break;
- case '@':
- if (CPP_OPTION (pfile, objc))
- {
- /* In Objective C, '@' may begin keywords or strings, like
- @keyword or @"string". It would be nice to call
- get_effective_char here and test the result. However, we
- would then need to pass 2 characters to parse_identifier,
- making it ugly and slowing down its main loop. Instead,
- we assume we have an identifier, and recover if not. */
- result->type = CPP_NAME;
- result->val.node = parse_identifier (pfile, c);
- if (result->val.node->length != 1)
- break;
-
- /* OK, so it wasn't an identifier. Maybe a string? */
- if (buffer->read_ahead == '"')
- {
- c = '"';
- ACCEPT_CHAR (CPP_OSTRING);
- goto make_string;
- }
- }
- goto random_char;
+ /* @ is a punctuator in Objective C. */
+ case '@': result->type = CPP_ATSIGN; break;
random_char:
default:
{
case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break;
case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break;
- case CPP_OSTRING: left = '"'; right = '"'; tag = '@'; break;
case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break;
case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break;
case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break;
{
case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break;
case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break;
- case CPP_OSTRING: left = '"'; right = '"'; tag = '@'; break;
case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break;
case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break;
case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break;
return CPP_NUMBER;
break;
- case CPP_OTHER:
- if (CPP_OPTION (pfile, objc) && token1->val.c == '@')
- {
- if (b == CPP_NAME) return CPP_NAME;
- if (b == CPP_STRING) return CPP_OSTRING;
- }
-
default:
break;
}