Browse Source

Fixed SD2-423: Cast to array types cause parser error.

Fixed C# lexer bug with long hexadecimal literals.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@392 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
041bf1f1b8
  1. 10
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs
  2. 2082
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs
  3. 94
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG
  4. 6
      src/Libraries/NRefactory/Test/Lexer/CSharp/NumberLexerTest.cs
  5. 68
      src/Libraries/NRefactory/Test/Parser/Expressions/CastExpressionTests.cs

10
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs

@ -271,9 +271,13 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -271,9 +271,13 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
// Try to determine a parsable value using ranges. (Quick hack!)
double d = 0;
if (!ishex && !Double.TryParse(digit,NumberStyles.Integer, null, out d)) {
errors.Error(y, x, String.Format("Can't parse integral constant {0}", digit));
return new Token(Tokens.Literal, x, y, stringValue.ToString(), 0);
if (ishex) {
d = ulong.Parse(digit, NumberStyles.HexNumber);
} else {
if (!Double.TryParse(digit, NumberStyles.Integer, null, out d)) {
errors.Error(y, x, String.Format("Can't parse integral constant {0}", digit));
return new Token(Tokens.Literal, x, y, stringValue.ToString(), 0);
}
}
if (d < long.MinValue || d > long.MaxValue) {

2082
src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs

File diff suppressed because it is too large Load Diff

94
src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG

@ -58,34 +58,49 @@ bool IsTypeCast() @@ -58,34 +58,49 @@ bool IsTypeCast()
}
// "(" ( typeKW [ "[" {","} "]" | "*" ] | void ( "[" {","} "]" | "*" ) ) ")"
// only for built-in types, all others use GuessTypeCast!
bool IsSimpleTypeCast ()
{
// assert: la.kind == _lpar
lexer.StartPeek();
Token pt1 = lexer.Peek();
Token pt = lexer.Peek();
Token pt = lexer.Peek();
if (Tokens.TypeKW[pt1.kind]) {
if (!IsTypeKWForTypeCast(ref pt)) {
return false;
}
return pt.kind == Tokens.CloseParenthesis;
}
/* !!! Proceeds from current peek position !!! */
bool IsTypeKWForTypeCast(ref Token pt)
{
if (Tokens.TypeKW[pt.kind]) {
pt = lexer.Peek();
if (pt.kind == Tokens.Times || pt.kind == Tokens.OpenSquareBracket) {
return IsPointerOrDims(ref pt) && pt.kind == Tokens.CloseParenthesis;
return IsPointerOrDims(ref pt);
} else {
return pt.kind == Tokens.CloseParenthesis;
return true;
}
} else if (pt1.kind == Tokens.Void) {
return IsPointerOrDims(ref pt) && pt.kind == Tokens.CloseParenthesis;
} else if (pt.kind == Tokens.Void) {
pt = lexer.Peek();
return IsPointerOrDims(ref pt);
}
return false;
}
// "(" NonGenericTypeName ")" castFollower
// NonGenericTypeName = ident [ "::" ident ] { "." ident }
bool GuessTypeCast ()
/* !!! Proceeds from current peek position !!! */
bool IsTypeNameOrKWForTypeCast(ref Token pt)
{
// assert: la.kind == _lpar
StartPeek();
Token pt = Peek();
if (IsTypeKWForTypeCast(ref pt))
return true;
else
return IsTypeNameForTypeCast(ref pt);
}
// TypeName = ident [ "::" ident ] { "." ident } ["<" TypeNameOrKW { "," TypeNameOrKW } ">" ] PointerOrDims
/* !!! Proceeds from current peek position !!! */
bool IsTypeNameForTypeCast(ref Token pt)
{
// ident
if (pt.kind != Tokens.Identifier) {
return false;
@ -107,13 +122,42 @@ bool GuessTypeCast () @@ -107,13 +122,42 @@ bool GuessTypeCast ()
}
pt = Peek();
}
if (pt.kind == Tokens.LessThan) {
do {
pt = Peek();
if (!IsTypeNameOrKWForTypeCast(ref pt)) {
return false;
}
} while (pt.kind == Tokens.Comma);
if (pt.kind != Tokens.GreaterThan) {
return false;
}
pt = Peek();
}
if (pt.kind == Tokens.Times || pt.kind == Tokens.OpenSquareBracket) {
return IsPointerOrDims(ref pt);
}
return true;
}
// "(" TypeName ")" castFollower
bool GuessTypeCast ()
{
// assert: la.kind == _lpar
StartPeek();
Token pt = Peek();
if (!IsTypeNameForTypeCast(ref pt)) {
return false;
}
// ")"
if (pt.kind != Tokens.CloseParenthesis) {
return false;
}
// check successor
pt = Peek();
return Tokens.CastFollower[pt.kind] || (Tokens.TypeKW[pt.kind] && lexer.Peek().kind == Tokens.Dot);
if (pt.kind != Tokens.CloseParenthesis) {
return false;
}
// check successor
pt = Peek();
return Tokens.CastFollower[pt.kind] || (Tokens.TypeKW[pt.kind] && lexer.Peek().kind == Tokens.Dot);
}
// END IsTypeCast
@ -2085,16 +2129,6 @@ PrimaryExpr<out Expression pexpr> @@ -2085,16 +2129,6 @@ PrimaryExpr<out Expression pexpr>
/*--- member access */
| "->" ident (. pexpr = new PointerReferenceExpression(pexpr, t.val); .)
| "." ident (. pexpr = new FieldReferenceExpression(pexpr, t.val);.)
/*| "::" ident (.
if (pexpr is IdentifierExpression) {
if (((IdentifierExpression)pexpr).Identifier == "global") {
pexpr = new GlobalReferenceExpression();
}
} else {
Error("expression before :: must be an identifier");
}
pexpr = new FieldReferenceExpression(pexpr, t.val);
.) */
/* member access on generic type */
| ( IF (IsGenericFollowedBy(Tokens.Dot) && IsTypeReferenceExpression(pexpr))
TypeArgumentList<out typeList> )

6
src/Libraries/NRefactory/Test/Lexer/CSharp/NumberLexerTest.cs

@ -70,6 +70,12 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp @@ -70,6 +70,12 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
CheckToken("0xAB1f", 0xAB1f);
}
[Test]
public void TestLongHexadecimalInteger()
{
CheckToken("0x4244636f446c6d58", 0x4244636f446c6d58);
}
[Test]
public void TestDouble()
{

68
src/Libraries/NRefactory/Test/Parser/Expressions/CastExpressionTests.cs

@ -25,6 +25,47 @@ namespace ICSharpCode.NRefactory.Tests.AST @@ -25,6 +25,47 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.IsTrue(ce.Expression is IdentifierExpression);
Assert.IsFalse(ce.IsSpecializedCast);
}
[Test]
public void CSharpArrayCastExpression()
{
CastExpression ce = (CastExpression)ParseUtilCSharp.ParseExpression("(MyType[])o", typeof(CastExpression));
Assert.AreEqual("MyType", ce.CastTo.Type);
Assert.AreEqual(new int[] { 0 }, ce.CastTo.RankSpecifier);
Assert.IsTrue(ce.Expression is IdentifierExpression);
Assert.IsFalse(ce.IsSpecializedCast);
}
[Test]
public void GenericCastExpression()
{
CastExpression ce = (CastExpression)ParseUtilCSharp.ParseExpression("(List<string>)o", typeof(CastExpression));
Assert.AreEqual("List", ce.CastTo.Type);
Assert.AreEqual("string", ce.CastTo.GenericTypes[0].Type);
Assert.IsTrue(ce.Expression is IdentifierExpression);
Assert.IsFalse(ce.IsSpecializedCast);
}
[Test]
public void GenericArrayCastExpression()
{
CastExpression ce = (CastExpression)ParseUtilCSharp.ParseExpression("(List<string>[])o", typeof(CastExpression));
Assert.AreEqual("List", ce.CastTo.Type);
Assert.AreEqual("string", ce.CastTo.GenericTypes[0].Type);
Assert.AreEqual(new int[] { 0 }, ce.CastTo.RankSpecifier);
Assert.IsTrue(ce.Expression is IdentifierExpression);
Assert.IsFalse(ce.IsSpecializedCast);
}
[Test]
public void CSharpCastMemberReferenceOnParenthesizedExpression()
{
// yes, we really wanted to evaluate .Member on expr and THEN cast the result to MyType
CastExpression ce = (CastExpression)ParseUtilCSharp.ParseExpression("(MyType)(expr).Member", typeof(CastExpression));
Assert.AreEqual("MyType", ce.CastTo.Type);
Assert.IsTrue(ce.Expression is FieldReferenceExpression);
Assert.IsFalse(ce.IsSpecializedCast);
}
#endregion
#region VB.NET
@ -113,11 +154,36 @@ namespace ICSharpCode.NRefactory.Tests.AST @@ -113,11 +154,36 @@ namespace ICSharpCode.NRefactory.Tests.AST
TestSpecializedCast("CLng(o)", typeof(System.Int64));
}
[Test]
public void VBNetSpecializedSByteCastExpression()
{
TestSpecializedCast("CSByte(o)", typeof(System.SByte));
}
[Test]
public void VBNetSpecializedUInt16CastExpression()
{
TestSpecializedCast("CUShort(o)", typeof(System.UInt16));
}
[Test]
public void VBNetSpecializedUInt32CastExpression()
{
TestSpecializedCast("CUInt(o)", typeof(System.UInt32));
}
[Test]
public void VBNetSpecializedUInt64CastExpression()
{
TestSpecializedCast("CULng(o)", typeof(System.UInt64));
}
[Test]
public void VBNetSpecializedObjectCastExpression()
{
TestSpecializedCast("CObj(o)", typeof(System.Object));
}
}
#endregion
}
}

Loading…
Cancel
Save