// This also implements the preprocessor
//
// Author: Miguel de Icaza (miguel@gnu.org)
-// Marek Safar (marek.safar@seznam.cz)
+// Marek Safar (marek.safar@gmail.com)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com)
// Copyright 2004-2008 Novell, Inc
-//
+// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
//
using System;
{
return Create (null, row, column);
}
+
+ public static LocatedToken Create (string value, Location loc)
+ {
+ return Create (value, loc.Row, loc.Column);
+ }
public static LocatedToken Create (string value, int row, int column)
{
}
}
- enum PreprocessorDirective
+ public enum PreprocessorDirective
{
Invalid = 0,
public bool parsing_attribute_section;
+ public bool parsing_modifiers;
+
//
// The special characters to inject on streams to run the unit parser
// in the special expression mode. Using private characters from
escaped_identifiers.Add (loc);
}
- public bool IsEscapedIdentifier (MemberName name)
+ public bool IsEscapedIdentifier (ATypeNameExpression name)
{
return escaped_identifiers != null && escaped_identifiers.Contains (name.Location);
}
else
tab_size = 8;
- //
- // FIXME: This could be `Location.Push' but we have to
- // find out why the MS compiler allows this
- //
Mono.CSharp.Location.Push (file, file);
}
res = -1;
break;
- // TODO: async, it's modifiers context only
case Token.ASYNC:
- if (context.Settings.Version != LanguageVersion.Future) {
+ if (parsing_modifiers) {
+ //
+ // Skip attributes section or constructor called async
+ //
+ if (parsing_attribute_section || peek_token () == Token.OPEN_PARENS) {
+ res = -1;
+ } else {
+ // async is keyword
+ }
+ } else if (parsing_block > 0) {
+ switch (peek_token ()) {
+ case Token.DELEGATE:
+ case Token.OPEN_PARENS_LAMBDA:
+ // async is keyword
+ break;
+ case Token.IDENTIFIER:
+ PushPosition ();
+ xtoken ();
+ if (xtoken () != Token.ARROW)
+ res = -1;
+
+ PopPosition ();
+ break;
+ default:
+ res = -1;
+ break;
+ }
+ } else {
res = -1;
}
+
+ if (res == Token.ASYNC && context.Settings.Version <= LanguageVersion.V_4) {
+ Report.FeatureIsNotAvailable (context, Location, "asynchronous functions");
+ }
+
break;
- // TODO: async, it's async block context only
case Token.AWAIT:
- if (context.Settings.Version != LanguageVersion.Future) {
+ if (parsing_block == 0)
res = -1;
- }
break;
}
// we need to convert to a special type, and then choose
// the best representation for the integer
//
- int adjust_int (int c, Location loc)
+ ILiteralConstant adjust_int (int c, Location loc)
{
- ILiteralConstant res;
try {
if (number_pos > 9){
ulong ul = (uint) (number_builder [0] - '0');
for (int i = 1; i < number_pos; i++){
ul = checked ((ul * 10) + ((uint)(number_builder [i] - '0')));
}
- res = integer_type_suffix (ul, c, loc);
+
+ return integer_type_suffix (ul, c, loc);
} else {
uint ui = (uint) (number_builder [0] - '0');
for (int i = 1; i < number_pos; i++){
ui = checked ((ui * 10) + ((uint)(number_builder [i] - '0')));
}
- res = integer_type_suffix (ui, c, loc);
+
+ return integer_type_suffix (ui, c, loc);
}
} catch (OverflowException) {
Error_NumericConstantTooLong ();
- res = new IntLiteral (context.BuiltinTypes, 0, loc);
+ return new IntLiteral (context.BuiltinTypes, 0, loc);
}
catch (FormatException) {
Report.Error (1013, Location, "Invalid number");
- res = new IntLiteral (context.BuiltinTypes, 0, loc);
+ return new IntLiteral (context.BuiltinTypes, 0, loc);
}
-
- val = res;
-#if FULL_AST
- res.ParsedValue = new char[number_pos];
- Array.Copy (number_builder, res.ParsedValue, number_pos);
-#endif
- return Token.LITERAL;
}
ILiteralConstant adjust_real (TypeCode t, Location loc)
{
ILiteralConstant res;
+#if FULL_AST
+ int read_start = reader.Position - 1;
+#endif
number_pos = 0;
var loc = Location;
int peek = peek_char ();
if (peek == 'x' || peek == 'X') {
- res = handle_hex (loc);
- val = res;
+ val = res = handle_hex (loc);
#if FULL_AST
- res.ParsedValue = new char[number_pos + 2];
- res.ParsedValue[0] = (char) c;
- res.ParsedValue[1] = (char) peek;
- Array.Copy (number_builder, 0, res.ParsedValue, 2, number_pos);
+ res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1);
#endif
return Token.LITERAL;
} else {
putback ('.');
number_pos--;
- return adjust_int (-1, loc);
+ val = res = adjust_int (-1, loc);
+
+#if FULL_AST
+ res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1);
+#endif
+ return Token.LITERAL;
}
}
}
var type = real_type_suffix (c);
- if (type == TypeCode.Empty && !is_real){
+ if (type == TypeCode.Empty && !is_real) {
putback (c);
- return adjust_int (c, loc);
- }
+ res = adjust_int (c, loc);
+ } else {
+ is_real = true;
- is_real = true;
+ if (type == TypeCode.Empty) {
+ putback (c);
+ }
- if (type == TypeCode.Empty){
- putback (c);
- c = 0;
+ res = adjust_real (type, loc);
}
- val = res = adjust_real (type, loc);
+ val = res;
#if FULL_AST
- res.ParsedValue = new char[number_pos + (c != 0 ? 1 : 0)];
- Array.Copy (number_builder, res.ParsedValue, number_pos);
- if (c != 0)
- res.ParsedValue[number_pos] = (char) c;
+ res.ParsedValue = reader.ReadChars (read_start, reader.Position - (type == TypeCode.Empty ? 1 : 0));
#endif
return Token.LITERAL;
if (quoted)
start_location = start_location - 1;
+#if FULL_AST
+ int reader_pos = reader.Position;
+#endif
+
while (true){
c = get_char ();
if (c == '"') {
else
s = new string (value_builder, 0, pos);
- val = new StringLiteral (context.BuiltinTypes, s, start_location);
+ ILiteralConstant res = new StringLiteral (context.BuiltinTypes, s, start_location);
+ val = res;
+#if FULL_AST
+ res.ParsedValue = quoted ?
+ reader.ReadChars (reader_pos - 2, reader.Position - 1) :
+ reader.ReadChars (reader_pos - 1, reader.Position);
+#endif
+
return Token.LITERAL;
}
if (c == '\n') {
- if (!quoted)
+ if (!quoted) {
Report.Error (1010, Location, "Newline in constant");
+ val = new StringLiteral (context.BuiltinTypes, new string (value_builder, 0, pos), start_location);
+ return Token.LITERAL;
+ }
} else if (c == '\\' && !quoted) {
int surrogate;
c = escape (c, out surrogate);
if (id_builder [0] >= '_' && !quoted) {
int keyword = GetKeyword (id_builder, pos);
if (keyword != -1) {
- val = LocatedToken.Create (null, ref_line, column);
+ val = LocatedToken.Create (keyword == Token.AWAIT ? "await" : null, ref_line, column);
return keyword;
}
}
int TokenizeBackslash ()
{
+#if FULL_AST
+ int read_start = reader.Position;
+#endif
+ Location start_location = Location;
int c = get_char ();
tokens_seen = true;
if (c == '\'') {
- val = new CharLiteral (context.BuiltinTypes, (char) c, Location);
- Report.Error (1011, Location, "Empty character literal");
+ val = new CharLiteral (context.BuiltinTypes, (char) c, start_location);
+ Report.Error (1011, start_location, "Empty character literal");
return Token.LITERAL;
}
if (c == '\n') {
- Report.Error (1010, Location, "Newline in constant");
+ Report.Error (1010, start_location, "Newline in constant");
return Token.ERROR;
}
if (d != 0)
throw new NotImplementedException ();
- val = new CharLiteral (context.BuiltinTypes, (char) c, Location);
+ ILiteralConstant res = new CharLiteral (context.BuiltinTypes, (char) c, start_location);
+ val = res;
c = get_char ();
if (c != '\'') {
- Report.Error (1012, Location, "Too many characters in character literal");
+ Report.Error (1012, start_location, "Too many characters in character literal");
// Try to recover, read until newline or next "'"
while ((c = get_char ()) != -1) {
}
}
+#if FULL_AST
+ res.ParsedValue = reader.ReadChars (read_start - 1, reader.Position);
+#endif
+
return Token.LITERAL;
}