Author: toshok
Date: 2005-03-24 02:28:16 -0500 (Thu, 24 Mar 2005)
New Revision: 42192
Removed:
trunk/debugger/cslex/
trunk/debugger/frontend/CSharpTokenizer.lex
Modified:
trunk/debugger/ChangeLog
trunk/debugger/Makefile.am
trunk/debugger/frontend/CSharpExpressionParser.jay
trunk/debugger/frontend/CSharpTokenizer.cs
trunk/debugger/frontend/Expression.cs
trunk/debugger/frontend/Makefile.am
Log:
2005-03-23 Chris Toshok <[EMAIL PROTECTED]>
* cslex/ remove.
* Makefile.am (SUBDIRS): remove cslex
* frontend/Expression.cs (NumberExpression..ctor): add ctors for
uint, long, ulong, float, double, and decimal.
(PropertyGroupExpression): cut and paste job of
MethodGroupExpression, for use in finding overloaded properties -
i.e. indexers.
(ArrayAccessExpression): allow multiple index expressions, and
deal with indexers properly.
* frontend/CSharpExpressionParser.jay: add many, many tokens.
(constant): add more productions.
(expression): make the array (foo[...]) production take multiple
expressions, and pass them as an array to ArrayIndexExpression.
* frontend/Makefile.am (noinst_DATA): remove CSharpTokenizer_lex.cs
(MAINTAINERCLEANFILES): same.
(EXTRA_DIST): same.
* frontend/CSharpTokenizer.lex: nuke this, cslex generated lexers
can't deal with unicode. which sucks. hard.
* frontend/CSharpTokenizer.cs: ressurect this, and make lots of
improvements. we can now deal with floats (courtesy of code
ripped off of monodevelop), and lots of operator tokens were
added.
Modified: trunk/debugger/ChangeLog
===================================================================
--- trunk/debugger/ChangeLog 2005-03-24 06:31:17 UTC (rev 42191)
+++ trunk/debugger/ChangeLog 2005-03-24 07:28:16 UTC (rev 42192)
@@ -1,3 +1,34 @@
+2005-03-23 Chris Toshok <[EMAIL PROTECTED]>
+
+ * cslex/ remove.
+
+ * Makefile.am (SUBDIRS): remove cslex
+
+ * frontend/Expression.cs (NumberExpression..ctor): add ctors for
+ uint, long, ulong, float, double, and decimal.
+ (PropertyGroupExpression): cut and paste job of
+ MethodGroupExpression, for use in finding overloaded properties -
+ i.e. indexers.
+ (ArrayAccessExpression): allow multiple index expressions, and
+ deal with indexers properly.
+
+ * frontend/CSharpExpressionParser.jay: add many, many tokens.
+ (constant): add more productions.
+ (expression): make the array (foo[...]) production take multiple
+ expressions, and pass them as an array to ArrayIndexExpression.
+
+ * frontend/Makefile.am (noinst_DATA): remove CSharpTokenizer_lex.cs
+ (MAINTAINERCLEANFILES): same.
+ (EXTRA_DIST): same.
+
+ * frontend/CSharpTokenizer.lex: nuke this, cslex generated lexers
+ can't deal with unicode. which sucks. hard.
+
+ * frontend/CSharpTokenizer.cs: ressurect this, and make lots of
+ improvements. we can now deal with floats (courtesy of code
+ ripped off of monodevelop), and lots of operator tokens were
+ added.
+
2005-03-13 Chris Toshok <[EMAIL PROTECTED]>
* frontend/Makefile.am (MAINTAINERCLEANFILES): add
Modified: trunk/debugger/Makefile.am
===================================================================
--- trunk/debugger/Makefile.am 2005-03-24 06:31:17 UTC (rev 42191)
+++ trunk/debugger/Makefile.am 2005-03-24 07:28:16 UTC (rev 42192)
@@ -1,4 +1,4 @@
-SUBDIRS = cslex jay interfaces classes glue arch backends frontend wrapper test
+SUBDIRS = jay interfaces classes glue arch backends frontend wrapper test
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = mono-debugger.pc
Modified: trunk/debugger/frontend/CSharpExpressionParser.jay
===================================================================
--- trunk/debugger/frontend/CSharpExpressionParser.jay 2005-03-24 06:31:17 UTC
(rev 42191)
+++ trunk/debugger/frontend/CSharpExpressionParser.jay 2005-03-24 07:28:16 UTC
(rev 42192)
@@ -33,35 +33,51 @@
// do not remove.
%token IDENTIFIER
-%token INTEGER
+%token INT
+%token UINT
%token FLOAT
-%token NUMBER
+%token DOUBLE
+%token DECIMAL
+%token ULONG
+%token LONG
%token STRING
%token HASH
%token AT
-%token PERCENT
%token DOLLAR
%token DOT
%token DOTDOT
%token NOT
%token COMMA
+%token ASSIGN
%token EQUAL
-%token EQUALEQUAL
%token NOTEQUAL
%token STAR
%token PLUS
%token MINUS
%token DIV
+%token PERCENT
+%token STARASSIGN
+%token PLUSASSIGN
+%token MINUSASSIGN
+%token DIVASSIGN
+%token PERCENTASSIGN
%token OPAREN
%token CPAREN
%token OBRACKET
%token CBRACKET
+%token RIGHTSHIFT
+%token RIGHTSHIFTASSIGN
+%token LEFTSHIFT
+%token LEFTSHIFTASSIGN
%token LT
%token GT
%token LE
%token GE
%token AND
%token OR
+%token OROR
+%token ANDAND
+%token NOT
%token COLON
%token QUESTION
%token AMPERSAND
@@ -91,7 +107,7 @@
primary_expression
: expression
- | expression EQUAL expression
+ | expression ASSIGN expression
{
$$ = new AssignmentExpression ((Expression) $1, (Expression)
$3);
}
@@ -106,18 +122,35 @@
{
$$ = new BoolExpression (false);
}
- | NUMBER
+ | LONG
{
$$ = new NumberExpression ((long) $1);
}
- | INTEGER
+ | ULONG
{
+ $$ = new NumberExpression ((ulong) $1);
+ }
+ | INT
+ {
$$ = new NumberExpression ((int) $1);
}
+ | UINT
+ {
+ $$ = new NumberExpression ((uint) $1);
+ }
| FLOAT
{
$$ = new NumberExpression ((float) $1);
}
+ | DOUBLE
+ {
+ $$ = new NumberExpression ((double) $1);
+ }
+ | DECIMAL
+ {
+ $$ = new NumberExpression ((decimal) $1);
+ }
+
| STRING
{
$$ = new StringExpression ((string) $1);
@@ -154,15 +187,18 @@
{
$$ = new AddressOfExpression ((Expression) $2);
}
- | expression OBRACKET expression CBRACKET
+ | expression OBRACKET expression_list CBRACKET
{
- $$ = new ArrayAccessExpression ((Expression) $1, (Expression)
$3);
+ Expression[] exps = new Expression [((ArrayList) $3).Count];
+ ((ArrayList) $3).CopyTo (exps, 0);
+
+ $$ = new ArrayAccessExpression ((Expression) $1, exps);
}
- | expression OPAREN argument_list CPAREN
+ | expression OPAREN expression_list_0 CPAREN
{
$$ = new InvocationExpression ((Expression) $1, ((Expression
[]) $3));
}
- | NEW variable_or_type_name OPAREN argument_list CPAREN
+ | NEW variable_or_type_name OPAREN expression_list_0 CPAREN
{
$$ = new NewExpression ((Expression) $2, ((Expression []) $4));
}
@@ -180,21 +216,21 @@
}
;
-argument_list
+expression_list_0
: /* empty */
{
$$ = new Expression [0];
}
- | argument_list_0
+ | expression_list
{
- Expression[] args = new Expression [((ArrayList) $1).Count];
- ((ArrayList) $1).CopyTo (args, 0);
+ Expression[] exps = new Expression [((ArrayList) $1).Count];
+ ((ArrayList) $1).CopyTo (exps, 0);
- $$ = args;
+ $$ = exps;
}
;
-argument_list_0
+expression_list
: expression
{
ArrayList args = new ArrayList ();
@@ -202,7 +238,7 @@
$$ = args;
}
- | argument_list_0 COMMA expression
+ | expression_list COMMA expression
{
ArrayList args = (ArrayList) $1;
args.Add ($3);
@@ -238,8 +274,7 @@
this.reader = new MyTextReader ();
this.current_context = context;
- lexer = new Tokenizer (reader);
- lexer.Name = name;
+ lexer = new Tokenizer (context, reader, name);
}
public Expression Parse (string text)
Modified: trunk/debugger/frontend/CSharpTokenizer.cs
===================================================================
--- trunk/debugger/frontend/CSharpTokenizer.cs 2005-03-24 06:31:17 UTC (rev
42191)
+++ trunk/debugger/frontend/CSharpTokenizer.cs 2005-03-24 07:28:16 UTC (rev
42192)
@@ -32,7 +32,24 @@
int putback_char;
Object val;
+ ScriptingContext context;
+ TextReader reader;
+ string ref_name;
+ int current_token;
+ int col = 1;
+
//
+ // Whether tokens have been seen on this line
+ //
+ bool tokens_seen = false;
+
+ //
+ // Details about the error encoutered by the tokenizer
+ //
+ string error_details;
+
+
+ //
// Class initializer
//
static Tokenizer ()
@@ -52,24 +69,11 @@
keywords.Add ("this", Token.THIS);
keywords.Add ("base", Token.BASE);
keywords.Add ("catch", Token.CATCH);
+ keywords.Add ("true", Token.TRUE);
+ keywords.Add ("false", Token.FALSE);
+ keywords.Add ("null", Token.FALSE);
}
- ScriptingContext context;
- TextReader reader;
- string ref_name;
- int current_token;
- int col = 1;
-
- //
- // Whether tokens have been seen on this line
- //
- bool tokens_seen = false;
-
- //
- // Details about the error encoutered by the tokenizer
- //
- string error_details;
-
public string error {
get {
return error_details;
@@ -99,10 +103,10 @@
int c;
int top = count != -1 ? count : 4;
- getChar ();
+ GetChar ();
error = false;
for (i = 0; i < top; i++){
- c = getChar ();
+ c = GetChar ();
if (c >= '0' && c <= '9')
c = (int) c - (int) '0';
@@ -117,7 +121,7 @@
total = (total * 16) + c;
if (count == -1){
- int p = peekChar ();
+ int p = PeekChar ();
if (p == -1)
break;
if (!is_hex ((char)p))
@@ -133,7 +137,7 @@
int d;
int v;
- d = peekChar ();
+ d = PeekChar ();
if (c != '\\')
return c;
@@ -179,11 +183,11 @@
context.Error ("Unrecognized escape sequence in
" + (char)d);
return d;
}
- getChar ();
+ GetChar ();
return v;
}
- int getChar ()
+ int GetChar ()
{
if (putback_char != -1){
int x = putback_char;
@@ -194,7 +198,7 @@
return reader.Read ();
}
- int peekChar ()
+ int PeekChar ()
{
if (putback_char != -1)
return putback_char;
@@ -210,19 +214,9 @@
public bool advance ()
{
- return peekChar () >= 0;
+ return PeekChar () >= 0;
}
- bool is_identifier_start_character (char c)
- {
- return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
|| c == '_' || Char.IsLetter (c);
- }
-
- bool is_identifier_part_character (char c)
- {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c);
- }
-
int GetKeyword (string name, bool tokens_seen)
{
object o = keywords [name];
@@ -240,72 +234,212 @@
return -1;
}
- //
- // Invoked if we know we have .digits or digits
- //
- int is_number (int c)
+#region "taken from MonoDevelop's Lexer.cs"
+ int ReadDigit(char ch)
{
- number_builder.Length = 0;
+ ++col;
- if (c >= '0' && c <= '9'){
- if (c == '0' && peekChar () == 'x' || peekChar
() == 'X'){
- getChar ();
- hex_digits (-1);
-
- string s = number_builder.ToString ();
-
- val = (long) System.UInt64.Parse (s,
NumberStyles.HexNumber);
- return Token.NUMBER;
+ StringBuilder sb = new StringBuilder(ch.ToString());
+ StringBuilder prefix = new StringBuilder();
+ StringBuilder suffix = new StringBuilder();
+
+ bool ishex = false;
+ bool isunsigned = false;
+ bool islong = false;
+ bool isfloat = false;
+ bool isdouble = false;
+ bool isdecimal = false;
+
+ if (ch == '0' && Char.ToUpper((char)PeekChar()) == 'X')
{
+ const string hex = "0123456789ABCDEF";
+ GetChar(); // skip 'x'
+ ++col;
+ while
(hex.IndexOf(Char.ToUpper((char)PeekChar())) != -1) {
+
sb.Append(Char.ToUpper((char)GetChar()));
+ ++col;
}
- decimal_digits (c);
-
- val = (int) System.UInt32.Parse
(number_builder.ToString ());
- return Token.INTEGER;
+ ishex = true;
+ prefix.Append("0x");
+ } else {
+ while (Char.IsDigit((char)PeekChar())) {
+ sb.Append((char)GetChar());
+ ++col;
+ }
}
-
- throw new Exception ("Is Number should never reach this
point");
- }
-
- bool decimal_digits (int c)
- {
- int d;
- bool seen_digits = false;
- if (c != -1)
- number_builder.Append ((char) c);
+ if (PeekChar() == '.') { // read floating point number
+ isdouble = true; // double is default
+ if (ishex) {
+ error_details = "No hexadecimal
floating point values allowed";
+ return Token.ERROR;
+ }
+ sb.Append((char)GetChar());
+ ++col;
+
+ while (Char.IsDigit((char)PeekChar())) { //
read decimal digits beyond the dot
+ sb.Append((char)GetChar());
+ ++col;
+ }
+ }
- while ((d = peekChar ()) != -1){
- if (d >= '0' && d <= '9'){
- number_builder.Append ((char) d);
- getChar ();
- seen_digits = true;
- } else
- break;
+ if (Char.ToUpper((char)PeekChar()) == 'E') { // read
exponent
+ isdouble = true;
+ sb.Append((char)GetChar());
+ ++col;
+ if (PeekChar() == '-' || PeekChar() == '+') {
+ sb.Append((char)GetChar());
+ ++col;
+ }
+ while (Char.IsDigit((char)PeekChar())) { //
read exponent value
+ sb.Append((char)GetChar());
+ ++col;
+ }
+ isunsigned = true;
}
- return seen_digits;
+ if (Char.ToUpper((char)PeekChar()) == 'F') { // float
value
+ suffix.Append(PeekChar());
+ GetChar();
+ ++col;
+ isfloat = true;
+ } else if (Char.ToUpper((char)PeekChar()) == 'D') { //
double type suffix (obsolete, double is default)
+ suffix.Append(PeekChar());
+ GetChar();
+ ++col;
+ isdouble = true;
+ } else if (Char.ToUpper((char)PeekChar()) == 'M') { //
decimal value
+ suffix.Append(PeekChar());
+ GetChar();
+ ++col;
+ isdecimal = true;
+ } else if (!isdouble) {
+ if (Char.ToUpper((char)PeekChar()) == 'U') {
+ suffix.Append(PeekChar());
+ GetChar();
+ ++col;
+ isunsigned = true;
+ }
+
+ if (Char.ToUpper((char)PeekChar()) == 'L') {
+ suffix.Append(PeekChar());
+ GetChar();
+ ++col;
+ islong = true;
+ if (!isunsigned &&
Char.ToUpper((char)PeekChar()) == 'U') {
+ suffix.Append(PeekChar());
+ GetChar();
+ ++col;
+ isunsigned = true;
+ }
+ }
+ }
+
+ string digit = sb.ToString();
+ //string stringValue = String.Concat(prefix.ToString(),
digit, suffix.ToString());
+ if (isfloat) {
+ try {
+ NumberFormatInfo numberFormatInfo = new
NumberFormatInfo();
+
numberFormatInfo.CurrencyDecimalSeparator = ".";
+ val = Single.Parse(digit,
numberFormatInfo);
+ return Token.FLOAT;
+ } catch (Exception) {
+ error_details = String.Format("Can't
parse float {0}", digit);
+
+ val = 0f;
+ return Token.FLOAT;
+ }
+ }
+ if (isdecimal) {
+ try {
+ NumberFormatInfo numberFormatInfo = new
NumberFormatInfo();
+
numberFormatInfo.CurrencyDecimalSeparator = ".";
+ val = Decimal.Parse(digit,
numberFormatInfo);
+ return Token.DECIMAL;
+ } catch (Exception) {
+ error_details = String.Format("Can't
parse decimal {0}", digit);
+ val = 0m;
+ return Token.DECIMAL;
+ }
+ }
+ if (isdouble) {
+ try {
+ NumberFormatInfo numberFormatInfo = new
NumberFormatInfo();
+
numberFormatInfo.CurrencyDecimalSeparator = ".";
+ val = Double.Parse(digit,
numberFormatInfo);
+ return Token.DOUBLE;
+ } catch (Exception) {
+ error_details = String.Format("Can't
parse double {0}", digit);
+ val = 0d;
+ return Token.DOUBLE;
+ }
+ }
+
+ double d = 0;
+ // FIXME:
http://bugzilla.ximian.com/show_bug.cgi?id=72221
+ if (!Double.TryParse(digit, ishex ?
NumberStyles.HexNumber : NumberStyles.Integer, null, out d)) {
+ error_details = String.Format("Can't parse
integral constant {0}", digit);
+ val = 0;
+ return Token.INT;
+ }
+ if (d < long.MinValue || d > long.MaxValue) {
+ islong = true;
+ isunsigned = true;
+ }
+ else if (d < uint.MinValue || d > uint.MaxValue) {
+ islong = true;
+ }
+ else if (d < int.MinValue || d > int.MaxValue) {
+ isunsigned = true;
+ }
+ if (islong) {
+ if (isunsigned) {
+ try {
+ val = UInt64.Parse(digit, ishex
? NumberStyles.HexNumber : NumberStyles.Number);
+ return Token.ULONG;
+ } catch (Exception) {
+ error_details =
String.Format("Can't parse unsigned long {0}", digit);
+ val = 0UL;
+ return Token.ULONG;
+ }
+ } else {
+ try {
+ val = Int64.Parse(digit, ishex
? NumberStyles.HexNumber : NumberStyles.Number);
+ return Token.LONG;
+ } catch (Exception) {
+ error_details =
String.Format("Can't parse long {0}", digit);
+ val = 0L;
+ return Token.LONG;
+ }
+ }
+ } else {
+ if (isunsigned) {
+ try {
+ val = UInt32.Parse(digit, ishex
? NumberStyles.HexNumber : NumberStyles.Number);
+ return Token.UINT;
+ } catch (Exception) {
+ error_details =
String.Format("Can't parse unsigned int {0}", digit);
+ val = 0U;
+ return Token.UINT;
+ }
+ } else {
+ try {
+ val = Int32.Parse(digit, ishex
? NumberStyles.HexNumber : NumberStyles.Number);
+ return Token.INT;
+ } catch (Exception) {
+ error_details =
String.Format("Can't parse int {0}", digit);
+ val = 0;
+ return Token.INT;
+ }
+ }
+ }
}
+#endregion
bool is_hex (int e)
{
return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F')
|| (e >= 'a' && e <= 'f');
}
-
- void hex_digits (int c)
- {
- int d;
- if (c != -1)
- number_builder.Append ((char) c);
- while ((d = peekChar ()) != -1){
- if (is_hex (d)){
- number_builder.Append ((char) d);
- getChar ();
- } else
- break;
- }
- }
-
private int consume_identifier (int c, bool quoted)
{
bool old_tokens_seen = tokens_seen;
@@ -315,9 +449,9 @@
id_builder.Append ((char) c);
- while ((c = peekChar ()) != -1) {
- if (is_identifier_part_character ((char) c)){
- id_builder.Append ((char)getChar ());
+ while ((c = PeekChar ()) != -1) {
+ if (Char.IsLetterOrDigit ((char)c) || c == '_')
{
+ id_builder.Append ((char)GetChar ());
col++;
} else
break;
@@ -342,11 +476,11 @@
int c;
string_builder.Length = 0;
- while ((c = getChar ()) != -1){
+ while ((c = GetChar ()) != -1){
if (c == '"'){
- if (quoted && peekChar () == '"'){
+ if (quoted && PeekChar () == '"'){
string_builder.Append ((char)
c);
- getChar ();
+ GetChar ();
continue;
} else {
val = string_builder.ToString
();
@@ -379,7 +513,7 @@
id_builder.Length = 0;
- while ((c = getChar ()) != -1){
+ while ((c = GetChar ()) != -1){
if (c == '\''){
val = id_builder.ToString ();
return Token.IDENTIFIER;
@@ -397,96 +531,187 @@
return Token.EOF;
}
- private string consume_help ()
- {
- int c;
- StringBuilder sb = new StringBuilder ();
-
- while ((c = getChar ()) != -1){
- if (c == '\n') {
- col = 0;
- return sb.ToString ();
- }
-
- col++;
- sb.Append ((char) c);
- }
-
- return sb.ToString ();
- }
-
public int xtoken ()
{
int c;
val = null;
// optimization: eliminate col and implement #directive
semantic correctly.
- for (;(c = getChar ()) != -1; col++) {
- if (is_identifier_start_character ((char)c))
- return consume_identifier (c, false);
+ for (;(c = GetChar ()) != -1; col++) {
if (c == 0)
continue;
- else if (c == '#')
+
+ if (Char.IsLetter ((char)c) || c == '_')
+ return consume_identifier (c, false);
+
+ if (c == '\'')
+ return consume_quoted_identifier ();
+
+ if (c == '"')
+ return consume_string (false);
+
+ if (Char.IsDigit ((char)c)) {
+ tokens_seen = true;
+ return ReadDigit ((char)c);
+ }
+
+ if (c == '#')
return Token.HASH;
else if (c == '@')
return Token.AT;
- else if (c == '%')
- return Token.PERCENT;
else if (c == '$')
return Token.DOLLAR;
- else if (c == '.')
- if ((c = peekChar ()) == '.') {
- getChar ();
+ else if (c == '.') {
+ if (Char.IsDigit ((char)PeekChar())) {
+ putback(c);
+ col -=2;
+ return ReadDigit ('0');
+ }
+
+ if ((c = PeekChar ()) == '.') {
+ GetChar ();
return Token.DOTDOT;
}
- else {
- return Token.DOT;
+
+ return Token.DOT;
+ }
+ else if (c == '!') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.NOTEQUAL;
}
- else if (c == '!')
- return Token.BANG;
- else if (c == '=')
+
+ return Token.NOT;
+ }
+ else if (c == '=') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.EQUAL;
+ }
+
return Token.ASSIGN;
- else if (c == '*')
+ }
+ else if (c == '*') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.STARASSIGN;
+ }
+
return Token.STAR;
- else if (c == '+')
+ }
+ else if (c == '+') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.PLUSASSIGN;
+ }
+
return Token.PLUS;
- else if (c == '-') // FIXME: negative numbers...
+ }
+ else if (c == '-') { // FIXME: negative
numbers...
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.MINUSASSIGN;
+ }
+ if ((c = PeekChar ()) == '>') {
+ GetChar ();
+ return Token.ARROW;
+ }
+
return Token.MINUS;
- else if (c == '/')
+ }
+ else if (c == '/') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.DIVASSIGN;
+ }
+
return Token.DIV;
+ }
+ else if (c == '%') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.PERCENTASSIGN;
+ }
+
+ return Token.PERCENT;
+ }
+ else if (c == '|') {
+ if ((c = PeekChar ()) == '|') {
+ GetChar ();
+ return Token.OROR;
+ }
+
+ return Token.OR;
+ }
+ else if (c == '&') {
+ if ((c = PeekChar ()) == '&') {
+ GetChar ();
+ return Token.ANDAND;
+ }
+
+ return Token.AMPERSAND;
+ }
else if (c == '(')
- return Token.OPEN_PARENS;
+ return Token.OPAREN;
else if (c == ')')
- return Token.CLOSE_PARENS;
+ return Token.CPAREN;
else if (c == '[')
- return Token.OPEN_BRACKET;
+ return Token.OBRACKET;
else if (c == ']')
- return Token.CLOSE_BRACKET;
+ return Token.CBRACKET;
else if (c == ',')
return Token.COMMA;
- else if (c == '<')
- return Token.OP_LT;
- else if (c == '>')
- return Token.OP_GT;
- else if (c == ':')
- return Token.COLON;
- else if (c == '&')
- return Token.AMPERSAND;
+ else if (c == '<') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.LE;
+ }
- if (c >= '0' && c <= '9') {
- tokens_seen = true;
- return is_number (c);
+ if ((c = PeekChar ()) == '<') {
+ GetChar ();
+
+ if (PeekChar () == '=') {
+ GetChar();
+ return
Token.LEFTSHIFTASSIGN;
+ }
+ else
+ return Token.LEFTSHIFT;
+ }
+
+ return Token.LT;
}
+ else if (c == '>') {
+ if ((c = PeekChar ()) == '=') {
+ GetChar ();
+ return Token.GE;
+ }
- if (c == '"')
- return consume_string (false);
+ if ((c = PeekChar ()) == '>') {
+ GetChar ();
+ if (PeekChar () == '=') {
+ GetChar();
+ return
Token.RIGHTSHIFTASSIGN;
+ }
+ else
+ return Token.RIGHTSHIFT;
+ }
+
+ return Token.GT;
+ }
+ else if (c == ':')
+ return Token.COLON;
+ else if (c == '?')
+ return Token.QUESTION;
+
if (c == ' ' || c == '\t' || c == '\f' || c ==
'\v' || c == '\r' || c == '\n'){
if (current_token == Token.HASH) {
error_details = "No whitespace
allowed after `#'";
return Token.ERROR;
- } else if (current_token == Token.AT) {
+ }
+
+ if (current_token == Token.AT) {
error_details = "No whitespace
allowed after `@'";
return Token.ERROR;
}
@@ -496,8 +721,6 @@
continue;
}
- if (c == '\'')
- return consume_quoted_identifier ();
error_details = "Unknown character `" + (char)
c + "'";
return Token.ERROR;
@@ -544,7 +767,7 @@
//
// Returns a verbose representation of the current location
//
- public string location {
+ public string Location {
get {
string det;
Deleted: trunk/debugger/frontend/CSharpTokenizer.lex
===================================================================
--- trunk/debugger/frontend/CSharpTokenizer.lex 2005-03-24 06:31:17 UTC (rev
42191)
+++ trunk/debugger/frontend/CSharpTokenizer.lex 2005-03-24 07:28:16 UTC (rev
42192)
@@ -1,202 +0,0 @@
-using System;
-using System.Text;
-using System.IO;
-using System.Reflection;
-using System.Collections;
-using System.Globalization;
-using Mono.Debugger;
-
-public class Yytoken {
- public readonly int Index;
- public readonly string Text;
- public readonly object Value;
- public readonly int Line;
- public readonly int CharBegin;
- public readonly int CharEnd;
-
- internal Yytoken (int index)
- {
- Index = index;
- }
-
- internal Yytoken (int index, string text, int line, int charBegin, int
charEnd)
- {
- Index = index;
- Text = text;
- Line = line;
- CharBegin = charBegin;
- CharEnd = charEnd;
- }
-
- internal Yytoken (int index, string text, object value, int line, int
charBegin, int charEnd)
- {
- Index = index;
- Text = text;
- Value = value;
- Line = line;
- CharBegin = charBegin;
- CharEnd = charEnd;
- }
-
- public override String ToString()
- {
- return "Token #"+ Index + ": " + Text + " (line "+ Line + ")";
- }
-}
-
-%%
-
-%public
-%namespace Mono.Debugger.Frontend.CSharp
-%class Tokenizer
-%implements yyParser.yyInput
-
-%eofval{
- return new Yytoken (Token.EOF);
-%eofval}
-
-%{
- string name;
-
- public string Name {
- set { name = value; }
- get { return name; }
- }
-
- Yytoken current_token;
-
- public bool advance () {
- current_token = yylex();
- return current_token.Index != Token.EOF;
- }
-
- public int token () {
- return current_token.Index;
- }
-
- public Object value () {
- return current_token.Value;
- }
-
- public void restart () {
- yyline = 0;
- yychar = 1;
- }
-
- static Hashtable tokenValues;
-
- private static Hashtable TokenValueName
- {
- get {
- if (tokenValues == null)
- tokenValues = GetTokenValueNameHash ();
-
- return tokenValues;
- }
- }
-
- private static Hashtable GetTokenValueNameHash ()
- {
- Type t = typeof (Token);
- FieldInfo [] fields = t.GetFields ();
- Hashtable hash = new Hashtable ();
- foreach (FieldInfo field in fields) {
- if (field.IsLiteral && field.IsStatic &&
field.FieldType == typeof (int))
- hash.Add (field.GetValue (null),
field.Name);
- }
- return hash;
- }
-
- //
- // Returns a verbose representation of the current location
- //
- public string Location {
- get {
- string det;
-
-#if false
- if (current_token == Token.ERROR)
- det = "detail: " + error_details;
- else
-#endif
- det = "";
-
- // return "Line: "+line+" Col: "+col + "\n"
+
- // "VirtLine: "+ref_line +
- // " Token: "+current_token + " " + det;
- string current_token_name = TokenValueName
[current_token.Index] as string;
- if (current_token_name == null)
- current_token_name =
current_token.ToString ();
-
- return String.Format ("{0}, Token: {1} {2}",
name,
- current_token_name, det);
- }
- }
-
-
-%}
-
-%line
-%char
-
-DIGIT=[0-9]
-ALPHA=[A-Za-z]
-HEXDIGIT=[A-Fa-f0-9]
-IDENTIFIER=[A-Za-z_][A-Za-z0-9_]*
-NEWLINE=((\r\n)|\n)
-NONNEWLINE_WHITE_SPACE_CHAR=[\ \t\b\012]
-WHITE_SPACE_CHAR=[{NEWLINE}\ \t\b\012]
-STRING_TEXT=(\\\"|[^{NEWLINE}\"]|\\{WHITE_SPACE_CHAR}+\\)*
-
-%%
-
-<YYINITIAL> {DIGIT}+ { return new Yytoken (Token.INTEGER, yytext(), (int)
UInt32.Parse (yytext()), yyline, yychar, yychar+1); }
-<YYINITIAL> {DIGIT}*\.{DIGIT}+ { return new Yytoken (Token.FLOAT, yytext(),
Single.Parse (yytext()), yyline, yychar, yychar+1); }
-<YYINITIAL> 0x{HEXDIGIT}+ { return new Yytoken (Token.NUMBER, yytext(), (long)
UInt64.Parse (yytext(), NumberStyles.HexNumber), yyline,yychar,
yychar+yytext().Length);}
-
-<YYINITIAL> "." { return new Yytoken (Token.DOT, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> ".." { return new Yytoken (Token.DOTDOT, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "#" { return new Yytoken (Token.HASH, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "@" { return new Yytoken (Token.AT, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "%" { return new Yytoken (Token.PERCENT, yytext(), yyline,
yychar, yychar+1); }
-<YYINITIAL> "$" { return new Yytoken (Token.DOLLAR, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "&" { return new Yytoken (Token.AMPERSAND, yytext(), yyline,
yychar, yychar+1); }
-<YYINITIAL> "?" { return new Yytoken (Token.QUESTION, yytext(), yyline,
yychar, yychar+1); }
-<YYINITIAL> ":" { return new Yytoken (Token.COLON, yytext(), yyline, yychar,
yychar+1); }
-
-<YYINITIAL> "!" { return new Yytoken (Token.NOT, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "=" { return new Yytoken (Token.EQUAL, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "*" { return new Yytoken (Token.STAR, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "+" { return new Yytoken (Token.PLUS, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "-" { return new Yytoken (Token.MINUS, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "/" { return new Yytoken (Token.DIV, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "(" { return new Yytoken (Token.OPAREN, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> ")" { return new Yytoken (Token.CPAREN, yytext(), yyline, yychar,
yychar+1); }
-<YYINITIAL> "[" { return new Yytoken (Token.OBRACKET, yytext(), yyline,
yychar, yychar+1); }
-<YYINITIAL> "]" { return new Yytoken (Token.CBRACKET, yytext(), yyline,
yychar, yychar+1); }
-
-<YYINITIAL> "->" { return new Yytoken (Token.ARROW, yytext(), yyline, yychar,
yychar + 2); }
-
-<YYINITIAL> "==" { return new Yytoken (Token.EQUALEQUAL, yytext(), yyline,
yychar, yychar + 2); }
-<YYINITIAL> "!=" { return new Yytoken (Token.NOTEQUAL, yytext(), yyline,
yychar, yychar + 2); }
-<YYINITIAL> "<" { return new Yytoken (Token.LT, yytext(), yyline, yychar,
yychar + 1); }
-<YYINITIAL> ">" { return new Yytoken (Token.GT, yytext(), yyline, yychar,
yychar + 1); }
-<YYINITIAL> "<=" { return new Yytoken (Token.LE, yytext(), yyline, yychar,
yychar + 2); }
-<YYINITIAL> ">=" { return new Yytoken (Token.GE, yytext(), yyline, yychar,
yychar + 2); }
-<YYINITIAL> "||" { return new Yytoken (Token.OR, yytext(), yyline, yychar,
yychar + 2); }
-<YYINITIAL> "&&" { return new Yytoken (Token.AND, yytext(), yyline, yychar,
yychar + 2); }
-
-<YYINITIAL> "new" { return new Yytoken (Token.NEW, yytext(), yyline, yychar,
yychar+yytext().Length); }
-<YYINITIAL> "this" { return new Yytoken (Token.THIS, yytext(), yyline,
yychar, yychar+yytext().Length); }
-<YYINITIAL> "base" { return new Yytoken (Token.BASE, yytext(), yyline,
yychar, yychar+yytext().Length); }
-<YYINITIAL> "catch" { return new Yytoken (Token.CATCH, yytext(), yyline,
yychar, yychar+yytext().Length); }
-<YYINITIAL> "true" { return new Yytoken (Token.TRUE, yytext(), yyline,
yychar, yychar+yytext().Length); }
-<YYINITIAL> "false" { return new Yytoken (Token.FALSE, yytext(), yyline,
yychar, yychar+yytext().Length); }
-<YYINITIAL> "null" { return new Yytoken (Token.NULL, yytext(), yyline,
yychar, yychar+yytext().Length); }
-
-<YYINITIAL> \"{STRING_TEXT}\" { return new Yytoken (Token.STRING, yytext(),
yytext().Substring(1, yytext().Length - 1), yyline, yychar,
yychar+yytext().Length); }
-<YYINITIAL> {IDENTIFIER} { return new Yytoken (Token.IDENTIFIER,
yytext(), yytext(), yyline, yychar, yychar+yytext().Length);}
-
-<YYINITIAL> {WHITE_SPACE_CHAR}+ { return null; }
-
-<YYINITIAL> . { Console.WriteLine ("illegal character: <{0}>", yytext());
return null; }
Modified: trunk/debugger/frontend/Expression.cs
===================================================================
--- trunk/debugger/frontend/Expression.cs 2005-03-24 06:31:17 UTC (rev
42191)
+++ trunk/debugger/frontend/Expression.cs 2005-03-24 07:28:16 UTC (rev
42192)
@@ -214,16 +214,36 @@
this.val = val;
}
+ public NumberExpression (uint val)
+ {
+ this.val = val;
+ }
+
public NumberExpression (long val)
{
this.val = val;
}
+ public NumberExpression (ulong val)
+ {
+ this.val = val;
+ }
+
public NumberExpression (float val)
{
this.val = val;
}
+ public NumberExpression (double val)
+ {
+ this.val = val;
+ }
+
+ public NumberExpression (decimal val)
+ {
+ this.val = val;
+ }
+
public long Value {
get {
if (val is int)
@@ -867,6 +887,130 @@
}
}
+ public class PropertyGroupExpression : Expression
+ {
+ ITargetStructType stype;
+ ITargetStructObject instance;
+ ILanguage language;
+ string name;
+ ArrayList props;
+
+ public PropertyGroupExpression (ITargetStructType stype, string
name,
+ ITargetStructObject instance,
+ ILanguage language, ArrayList
props)
+ {
+ this.stype = stype;
+ this.instance = instance;
+ this.language = language;
+ this.name = name;
+ this.props = props;
+ resolved = true;
+ }
+
+ public override string Name {
+ get { return stype.Name + "." + name; }
+ }
+
+ public bool IsStatic {
+ get { return instance == null; }
+ }
+
+ protected override Expression DoResolve (ScriptingContext
context)
+ {
+ return this;
+ }
+
+#if false
+ public ITargetFunctionObject EvaluateProperty (ScriptingContext
context,
+ StackFrame frame,
+ bool getter,
+ Expression[]
arguments)
+ {
+ ITargetPropertyInfo prop = OverloadResolve (context,
getter, arguments);
+
+ if (prop.IsStatic)
+ return stype.GetStaticProperty (frame,
prop.Index);
+ else if (!IsStatic)
+ return instance.GetProperty (prop.Index);
+ else
+ throw new ScriptingException (
+ "Instance property {0} cannot be used
in " +
+ "static context.", Name);
+ }
+#endif
+
+ protected ITargetPropertyInfo OverloadResolve (ScriptingContext
context,
+ bool getter,
+ ITargetType[]
types)
+ {
+ ArrayList candidates = new ArrayList ();
+
+ foreach (ITargetPropertyInfo prop in props) {
+ if ((types != null) &&
+ (prop.Getter.ParameterTypes.Length !=
types.Length))
+ continue;
+
+ candidates.Add (prop);
+ }
+
+ if (candidates.Count == 1)
+ return (ITargetPropertyInfo) candidates [0];
+
+ if (candidates.Count == 0)
+ throw new ScriptingException (
+ "No overload of property `{0}' has {1}
indices.",
+ Name, types.Length);
+
+ if (types == null)
+ throw new ScriptingException (
+ "Ambiguous property `{0}'; need to use
" +
+ "full name", Name);
+
+ ITargetPropertyInfo match = OverloadResolve (
+ context, language, stype, types, candidates);
+
+ if (match == null)
+ throw new ScriptingException (
+ "Ambiguous property `{0}'; need to use
" +
+ "full name", Name);
+
+ return match;
+ }
+
+ public static ITargetPropertyInfo OverloadResolve
(ScriptingContext context,
+ ILanguage
language,
+
ITargetStructType stype,
+
ITargetType[] types,
+ ArrayList
candidates)
+ {
+ ITargetPropertyInfo match = null;
+ foreach (ITargetPropertyInfo prop in candidates) {
+
+ if (prop.Getter.ParameterTypes.Length !=
types.Length)
+ continue;
+
+ bool ok = true;
+ for (int i = 0; i < types.Length; i++) {
+ if (prop.Getter.ParameterTypes
[i].TypeHandle != types [i].TypeHandle) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (!ok)
+ continue;
+
+ // We need to find exactly one match
+ if (match != null)
+ return null;
+
+ match = prop;
+ }
+
+ return match;
+ }
+ }
+
#if FIXME
// So you can extend this by just creating a subclass
// of BinaryOperator that implements DoEvaluate and
@@ -1443,15 +1587,23 @@
public class ArrayAccessExpression : Expression
{
- Expression expr, index;
+ Expression expr;
+ Expression[] indices;
string name;
- public ArrayAccessExpression (Expression expr, Expression index)
+ public ArrayAccessExpression (Expression expr, Expression[]
indices)
{
this.expr = expr;
- this.index = index;
+ this.indices = indices;
- name = String.Format ("{0}[{1}]", expr.Name, index);
+ StringBuilder sb = new StringBuilder("");
+ bool comma = false;
+ foreach (Expression index in indices) {
+ if (comma) sb.Append(",");
+ sb.Append (index.ToString());
+ comma = true;
+ }
+ name = String.Format ("{0}[{1}]", expr.Name,
sb.ToString());
}
public override string Name {
@@ -1462,55 +1614,114 @@
protected override Expression DoResolve (ScriptingContext
context)
{
+ int i;
expr = expr.Resolve (context);
if (expr == null)
return null;
- index = index.Resolve (context);
- if (index == null)
- return null;
+ for (i = 0; i < indices.Length; i ++) {
+ indices[i] = indices[i].Resolve (context);
+ if (indices[i] == null)
+ return null;
+ }
resolved = true;
return this;
}
+ int GetIntIndex (Expression index, ScriptingContext context) {
+ try {
+ return (int) index.Evaluate (context);
+ }
+ catch (Exception e) {
+ throw new ScriptingException (
+ "Cannot convert {0} to an integer
for indexing: {1}",
+ index, e);
+ }
+ }
+
protected override ITargetObject DoEvaluateVariable
(ScriptingContext context)
{
int i;
-
ITargetObject obj = expr.EvaluateVariable (context);
- try {
- i = (int) this.index.Evaluate (context);
- } catch (Exception e) {
- throw new ScriptingException (
- "Cannot convert {0} to an integer for
indexing: {1}",
- this.index, e);
+ // array[int]
+ ITargetArrayObject aobj = obj as ITargetArrayObject;
+ if (aobj != null) {
+ // single dimensional array only at present
+ i = GetIntIndex (this.indices[0], context);
+
+ if ((i < aobj.LowerBound) || (i >=
aobj.UpperBound)) {
+ if (aobj.UpperBound == 0)
+ throw new ScriptingException (
+ "Index
{0} of array expression {1} out of bounds " +
+ "(array
is of zero length)", i, expr.Name);
+ else
+ throw new ScriptingException (
+ "Index
{0} of array expression {1} out of bounds " +
+ "(must
be between {2} and {3}).", i, expr.Name,
+
aobj.LowerBound, aobj.UpperBound - 1);
+ }
+
+ return aobj [i];
}
- ITargetArrayObject aobj = obj as ITargetArrayObject;
- if (aobj == null) {
- ITargetPointerObject pobj = obj as
ITargetPointerObject;
- if ((pobj != null) && pobj.Type.IsArray)
+ // pointer[int]
+ ITargetPointerObject pobj = obj as ITargetPointerObject;
+ if (pobj != null) {
+ // single dimensional array only at present
+ i = GetIntIndex (this.indices[0], context);
+
+ if (pobj.Type.IsArray)
return pobj.GetArrayElement (i);
throw new ScriptingException (
- "Variable {0} is
not an array type.", expr.Name);
+ "Variable {0} is not an
array type.", expr.Name);
}
- if ((i < aobj.LowerBound) || (i >= aobj.UpperBound)) {
- if (aobj.UpperBound == 0)
- throw new ScriptingException (
- "Index
{0} of array expression {1} out of bounds " +
- "(array
is of zero length)", i, expr.Name);
- else
- throw new ScriptingException (
- "Index
{0} of array expression {1} out of bounds " +
- "(must be
between {2} and {3}).", i, expr.Name,
-
aobj.LowerBound, aobj.UpperBound - 1);
+ // indexers
+ ITargetStructObject sobj = obj as ITargetStructObject;
+ if (sobj != null) {
+ StackFrame frame = context.CurrentFrame.Frame;
+ ITargetPropertyInfo prop_info;
+ ArrayList candidates = new ArrayList ();
+
+ candidates.AddRange (sobj.Type.Properties);
+
+ ITargetType[] indextypes = new ITargetType
[indices.Length];
+ ITargetObject[] indexargs = new ITargetObject
[indices.Length];
+ for (i = 0; i < indices.Length; i++) {
+ indextypes [i] = indices
[i].EvaluateType (context);
+ if (indextypes [i] == null)
+ return null;
+ indexargs [i] = indices
[i].EvaluateVariable (context);
+ if (indexargs [i] == null)
+ return null;
+ }
+
+ prop_info =
PropertyGroupExpression.OverloadResolve (context, frame.Language, sobj.Type,
indextypes,
+
candidates);
+
+ if (prop_info == null) {
+ throw new ScriptingException ("Could
not find matching indexer.");
+ }
+
+ ITargetTypeInfo getter_info = (ITargetTypeInfo)
prop_info.Getter.Resolve ();
+ if (getter_info == null) {
+ return null;
+ }
+
+ ITargetFunctionObject func =
getter_info.GetObject (sobj.Location) as ITargetFunctionObject;
+ if (func == null) {
+ return null;
+ }
+
+ return func.Invoke (indexargs, false);
}
-
- return aobj [i];
+
+ throw new ScriptingException (
+ "{0} is neither an
array/pointer type, nor is it " +
+ "an object with a valid
indexer.");
}
protected override ITargetType DoEvaluateType (ScriptingContext
context)
Modified: trunk/debugger/frontend/Makefile.am
===================================================================
--- trunk/debugger/frontend/Makefile.am 2005-03-24 06:31:17 UTC (rev 42191)
+++ trunk/debugger/frontend/Makefile.am 2005-03-24 07:28:16 UTC (rev 42192)
@@ -1,4 +1,4 @@
-noinst_DATA = CSharpExpressionParser.cs CSharpTokenizer_lex.cs
+noinst_DATA = CSharpExpressionParser.cs
JAY = $(top_builddir)/jay/jay
CSLEX = $(top_builddir)/cslex/cslex.exe
@@ -6,11 +6,8 @@
CSharpExpressionParser.cs: CSharpExpressionParser.jay
$(JAY) -ctv < skeleton $< > tmp-p && mv -f tmp-p
CSharpExpressionParser.cs
-CSharpTokenizer_lex.cs: CSharpTokenizer.lex
- mono $(CSLEX) $<
+MAINTAINERCLEANFILES = CSharpExpressionParser.cs y.output
-MAINTAINERCLEANFILES = CSharpExpressionParser.cs CSharpTokenizer_lex.cs
y.output
-
EXTRA_DIST = \
CL.cs \
Command.cs \
@@ -18,8 +15,6 @@
Expression.cs \
CSharpExpressionParser.cs \
CSharpExpressionParser.jay \
- CSharpTokenizer_lex.cs \
- CSharpTokenizer.lex \
GnuReadLine.cs \
IExpressionParser.cs \
Interpreter.cs \
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches