Browse Source

Add null coalescing operator to C# lexer and parser.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@389 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 21 years ago
parent
commit
1dcf29e24d
  1. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Resources/SyntaxModes.xml
  2. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Resources/XML-Mode.xshd
  3. 2
      src/Libraries/NRefactory/NRefactory.sln
  4. 1
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt
  5. 4
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs
  6. 226
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs
  7. 2
      src/Libraries/NRefactory/Project/Src/Parser/AST/General/Expressions/BinaryOperatorExpression.cs
  8. 3264
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs
  9. 5
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG
  10. 59
      src/Libraries/NRefactory/Test/Lexer/CSharp/CustomLexerTests.cs
  11. 55
      src/Libraries/NRefactory/Test/Lexer/CSharp/LexerTests.cs
  12. 3
      src/Libraries/NRefactory/Test/NRefactoryTests.csproj
  13. 6
      src/Libraries/NRefactory/Test/Parser/Expressions/BinaryOperatorExpressionTests.cs
  14. 13
      src/Libraries/NRefactory/Test/Parser/Expressions/ConditionalExpressionTests.cs

2
src/Libraries/ICSharpCode.TextEditor/Project/Resources/SyntaxModes.xml

@ -45,5 +45,5 @@ @@ -45,5 +45,5 @@
<Mode file = "XML-Mode.xshd"
name = "XML"
extensions = ".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.build;.xfrm"/>
extensions = ".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.proj;.build;.xfrm"/>
</SyntaxModes>

2
src/Libraries/ICSharpCode.TextEditor/Project/Resources/XML-Mode.xshd

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
<?xml version="1.0" ?>
<!-- syntaxdefinition for XML 2000 by Mike Krueger -->
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.build;.xfrm">
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.proj;.build;.xfrm">
<Digits name="Digits" bold="false" italic="false" color="DarkBlue" />
<RuleSets>

2
src/Libraries/NRefactory/NRefactory.sln

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# SharpDevelop 2.0.0.9999
# SharpDevelop 2.0.0.382
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryTests", "Test\NRefactoryTests.csproj", "{870115DD-960A-4406-A6B9-600BCDC36A03}"

1
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt

@ -25,6 +25,7 @@ Colon = ":" @@ -25,6 +25,7 @@ Colon = ":"
DoubleColon = "::"
Semicolon = ";"
Question = "?"
DoubleQuestion = "??"
Comma = ","
Dot = "."

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

@ -633,6 +633,10 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -633,6 +633,10 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
}
return new Token(Tokens.GreaterThan, x, y);
case '?':
if (ReaderPeek() == '?') {
ReaderRead();
return new Token(Tokens.DoubleQuestion, x, y);
}
return new Token(Tokens.Question, x, y);
case ';':
return new Token(Tokens.Semicolon, x, y);

226
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs

@ -29,121 +29,122 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -29,121 +29,122 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
public const int DoubleColon = 10;
public const int Semicolon = 11;
public const int Question = 12;
public const int Comma = 13;
public const int Dot = 14;
public const int OpenCurlyBrace = 15;
public const int CloseCurlyBrace = 16;
public const int OpenSquareBracket = 17;
public const int CloseSquareBracket = 18;
public const int OpenParenthesis = 19;
public const int CloseParenthesis = 20;
public const int GreaterThan = 21;
public const int LessThan = 22;
public const int Not = 23;
public const int LogicalAnd = 24;
public const int LogicalOr = 25;
public const int BitwiseComplement = 26;
public const int BitwiseAnd = 27;
public const int BitwiseOr = 28;
public const int Xor = 29;
public const int Increment = 30;
public const int Decrement = 31;
public const int Equal = 32;
public const int NotEqual = 33;
public const int GreaterEqual = 34;
public const int LessEqual = 35;
public const int ShiftLeft = 36;
public const int PlusAssign = 37;
public const int MinusAssign = 38;
public const int TimesAssign = 39;
public const int DivAssign = 40;
public const int ModAssign = 41;
public const int BitwiseAndAssign = 42;
public const int BitwiseOrAssign = 43;
public const int XorAssign = 44;
public const int ShiftLeftAssign = 45;
public const int Pointer = 46;
public const int DoubleQuestion = 13;
public const int Comma = 14;
public const int Dot = 15;
public const int OpenCurlyBrace = 16;
public const int CloseCurlyBrace = 17;
public const int OpenSquareBracket = 18;
public const int CloseSquareBracket = 19;
public const int OpenParenthesis = 20;
public const int CloseParenthesis = 21;
public const int GreaterThan = 22;
public const int LessThan = 23;
public const int Not = 24;
public const int LogicalAnd = 25;
public const int LogicalOr = 26;
public const int BitwiseComplement = 27;
public const int BitwiseAnd = 28;
public const int BitwiseOr = 29;
public const int Xor = 30;
public const int Increment = 31;
public const int Decrement = 32;
public const int Equal = 33;
public const int NotEqual = 34;
public const int GreaterEqual = 35;
public const int LessEqual = 36;
public const int ShiftLeft = 37;
public const int PlusAssign = 38;
public const int MinusAssign = 39;
public const int TimesAssign = 40;
public const int DivAssign = 41;
public const int ModAssign = 42;
public const int BitwiseAndAssign = 43;
public const int BitwiseOrAssign = 44;
public const int XorAssign = 45;
public const int ShiftLeftAssign = 46;
public const int Pointer = 47;
// ----- keywords -----
public const int Abstract = 47;
public const int As = 48;
public const int Base = 49;
public const int Bool = 50;
public const int Break = 51;
public const int Byte = 52;
public const int Case = 53;
public const int Catch = 54;
public const int Char = 55;
public const int Checked = 56;
public const int Class = 57;
public const int Const = 58;
public const int Continue = 59;
public const int Decimal = 60;
public const int Default = 61;
public const int Delegate = 62;
public const int Do = 63;
public const int Double = 64;
public const int Else = 65;
public const int Enum = 66;
public const int Event = 67;
public const int Explicit = 68;
public const int Extern = 69;
public const int False = 70;
public const int Finally = 71;
public const int Fixed = 72;
public const int Float = 73;
public const int For = 74;
public const int Foreach = 75;
public const int Goto = 76;
public const int If = 77;
public const int Implicit = 78;
public const int In = 79;
public const int Int = 80;
public const int Interface = 81;
public const int Internal = 82;
public const int Is = 83;
public const int Lock = 84;
public const int Long = 85;
public const int Namespace = 86;
public const int New = 87;
public const int Null = 88;
public const int Object = 89;
public const int Operator = 90;
public const int Out = 91;
public const int Override = 92;
public const int Params = 93;
public const int Private = 94;
public const int Protected = 95;
public const int Public = 96;
public const int Readonly = 97;
public const int Ref = 98;
public const int Return = 99;
public const int Sbyte = 100;
public const int Sealed = 101;
public const int Short = 102;
public const int Sizeof = 103;
public const int Stackalloc = 104;
public const int Static = 105;
public const int String = 106;
public const int Struct = 107;
public const int Switch = 108;
public const int This = 109;
public const int Throw = 110;
public const int True = 111;
public const int Try = 112;
public const int Typeof = 113;
public const int Uint = 114;
public const int Ulong = 115;
public const int Unchecked = 116;
public const int Unsafe = 117;
public const int Ushort = 118;
public const int Using = 119;
public const int Virtual = 120;
public const int Void = 121;
public const int Volatile = 122;
public const int While = 123;
public const int Abstract = 48;
public const int As = 49;
public const int Base = 50;
public const int Bool = 51;
public const int Break = 52;
public const int Byte = 53;
public const int Case = 54;
public const int Catch = 55;
public const int Char = 56;
public const int Checked = 57;
public const int Class = 58;
public const int Const = 59;
public const int Continue = 60;
public const int Decimal = 61;
public const int Default = 62;
public const int Delegate = 63;
public const int Do = 64;
public const int Double = 65;
public const int Else = 66;
public const int Enum = 67;
public const int Event = 68;
public const int Explicit = 69;
public const int Extern = 70;
public const int False = 71;
public const int Finally = 72;
public const int Fixed = 73;
public const int Float = 74;
public const int For = 75;
public const int Foreach = 76;
public const int Goto = 77;
public const int If = 78;
public const int Implicit = 79;
public const int In = 80;
public const int Int = 81;
public const int Interface = 82;
public const int Internal = 83;
public const int Is = 84;
public const int Lock = 85;
public const int Long = 86;
public const int Namespace = 87;
public const int New = 88;
public const int Null = 89;
public const int Object = 90;
public const int Operator = 91;
public const int Out = 92;
public const int Override = 93;
public const int Params = 94;
public const int Private = 95;
public const int Protected = 96;
public const int Public = 97;
public const int Readonly = 98;
public const int Ref = 99;
public const int Return = 100;
public const int Sbyte = 101;
public const int Sealed = 102;
public const int Short = 103;
public const int Sizeof = 104;
public const int Stackalloc = 105;
public const int Static = 106;
public const int String = 107;
public const int Struct = 108;
public const int Switch = 109;
public const int This = 110;
public const int Throw = 111;
public const int True = 112;
public const int Try = 113;
public const int Typeof = 114;
public const int Uint = 115;
public const int Ulong = 116;
public const int Unchecked = 117;
public const int Unsafe = 118;
public const int Ushort = 119;
public const int Using = 120;
public const int Virtual = 121;
public const int Void = 122;
public const int Volatile = 123;
public const int While = 124;
public const int maxToken = 124;
public const int maxToken = 125;
static BitArray NewSet(params int[] values)
{
BitArray bitArray = new BitArray(maxToken);
@ -178,6 +179,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -178,6 +179,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
"::",
";",
"?",
"??",
",",
".",
"{",

2
src/Libraries/NRefactory/Project/Src/Parser/AST/General/Expressions/BinaryOperatorExpression.cs

@ -70,6 +70,8 @@ namespace ICSharpCode.NRefactory.Parser.AST @@ -70,6 +70,8 @@ namespace ICSharpCode.NRefactory.Parser.AST
AsCast,
/// <summary>VB-only: Like</summary>
Like,
/// <summary>C#: ??</summary>
NullCoalescing,
}
public class BinaryOperatorExpression : Expression

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

File diff suppressed because it is too large Load Diff

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

@ -433,6 +433,7 @@ TOKENS @@ -433,6 +433,7 @@ TOKENS
"::"
";"
"?"
"??"
","
"."
"{"
@ -1902,7 +1903,9 @@ Expr<out Expression expr> @@ -1902,7 +1903,9 @@ Expr<out Expression expr>
UnaryExpr<out expr>
/*--- conditional expression: */
(
ConditionalOrExpr<ref expr> [ "?" Expr<out expr1> ":" Expr<out expr2> (. expr = new ConditionalExpression(expr, expr1, expr2); .) ]
ConditionalOrExpr<ref expr>
[ "??" Expr<out expr1> (. expr = new BinaryOperatorExpression(expr, BinaryOperatorType.NullCoalescing, expr1); .) ]
[ "?" Expr<out expr1> ":" Expr<out expr2> (. expr = new ConditionalExpression(expr, expr1, expr2); .) ]
/*--- assignment: */
| (. AssignmentOperatorType op; Expression val; .) AssignmentOperator<out op> Expr<out val> (. expr = new AssignmentExpression(expr, op, val); .)
)

59
src/Libraries/NRefactory/Test/Lexer/CSharp/CustomLexerTests.cs

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="Daniel Grunwald" email=""/>
// <version>$Revision$</version>
// </file>
using System;
using System.IO;
using NUnit.Framework;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.CSharp;
using ICSharpCode.NRefactory.PrettyPrinter;
namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
{
[TestFixture]
public sealed class CustomLexerTests
{
ILexer GenerateLexer(StringReader sr)
{
return ParserFactory.CreateLexer(SupportedLanguages.CSharp, sr);
}
[Test]
public void TestEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{}+"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
Assert.AreEqual(Tokens.Plus, lexer.NextToken().kind);
Assert.AreEqual(Tokens.EOF, lexer.NextToken().kind);
}
[Test]
public void TestSkippedEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{}+"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
lexer.NextToken();
lexer.SkipCurrentBlock();
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.LookAhead.kind);
Assert.AreEqual(Tokens.Plus, lexer.NextToken().kind);
Assert.AreEqual(Tokens.EOF, lexer.NextToken().kind);
}
[Test]
public void TestSkippedNonEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{ TestMethod('}'); /* }}} */ while(1) {break;} }+"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
lexer.NextToken();
lexer.SkipCurrentBlock();
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.LookAhead.kind);
Assert.AreEqual(Tokens.Plus, lexer.NextToken().kind);
Assert.AreEqual(Tokens.EOF, lexer.NextToken().kind);
}
}
}

55
src/Libraries/NRefactory/Test/Lexer/CSharp/LexerTest.cs → src/Libraries/NRefactory/Test/Lexer/CSharp/LexerTests.cs

@ -92,6 +92,13 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp @@ -92,6 +92,13 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
Assert.AreEqual(Tokens.Question, lexer.NextToken().kind);
}
[Test]
public void TestDoubleQuestion()
{
ILexer lexer = GenerateLexer(new StringReader("??"));
Assert.AreEqual(Tokens.DoubleQuestion, lexer.NextToken().kind);
}
[Test]
public void TestComma()
{
@ -120,40 +127,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp @@ -120,40 +127,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
}
[Test]
public void TestEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{}+"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind);
Assert.AreEqual(Tokens.Plus, lexer.NextToken().kind);
Assert.AreEqual(Tokens.EOF, lexer.NextToken().kind);
}
[Test]
public void TestSkippedEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{}+"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
lexer.NextToken();
lexer.SkipCurrentBlock();
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.LookAhead.kind);
Assert.AreEqual(Tokens.Plus, lexer.NextToken().kind);
Assert.AreEqual(Tokens.EOF, lexer.NextToken().kind);
}
[Test]
public void TestSkippedNonEmptyBlock()
{
ILexer lexer = GenerateLexer(new StringReader("{ TestMethod('}'); /* }}} */ while(1) {break;} }+"));
Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().kind);
lexer.NextToken();
lexer.SkipCurrentBlock();
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.LookAhead.kind);
Assert.AreEqual(Tokens.Plus, lexer.NextToken().kind);
Assert.AreEqual(Tokens.EOF, lexer.NextToken().kind);
}
[Test]
public void TestOpenSquareBracket()
{
@ -294,13 +267,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp @@ -294,13 +267,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
Assert.AreEqual(Tokens.ShiftLeft, lexer.NextToken().kind);
}
// [Test]
// public void TestShiftRight()
// {
// ILexer lexer = GenerateLexer(new StringReader(">>"));
// Assert.AreEqual(Tokens.ShiftRight, lexer.NextToken().kind);
// }
[Test]
public void TestPlusAssign()
{
@ -364,13 +330,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp @@ -364,13 +330,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
Assert.AreEqual(Tokens.ShiftLeftAssign, lexer.NextToken().kind);
}
// [Test]
// public void TestShiftRightAssign()
// {
// ILexer lexer = GenerateLexer(new StringReader(">>="));
// Assert.AreEqual(Tokens.ShiftRightAssign, lexer.NextToken().kind);
// }
[Test()]
public void TestAbstract()
{

3
src/Libraries/NRefactory/Test/NRefactoryTests.csproj

@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Lexer\CSharp\LexerTest.cs" />
<Compile Include="Lexer\CSharp\LexerTests.cs" />
<Compile Include="General\UnitTest.cs" />
<Compile Include="Parser\GlobalScope\AttributeSectionTests.cs" />
<Compile Include="Output\CSharp\CSharpOutputTest.cs" />
@ -129,6 +129,7 @@ @@ -129,6 +129,7 @@
<Compile Include="Parser\TypeLevel\CustomEventTests.cs" />
<Compile Include="Lexer\CSharp\LexerPositionTests.cs" />
<Compile Include="Lexer\VBNet\LexerPositionTests.cs" />
<Compile Include="Lexer\CSharp\CustomLexerTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Project\NRefactory.csproj">

6
src/Libraries/NRefactory/Test/Parser/Expressions/BinaryOperatorExpressionTests.cs

@ -136,6 +136,12 @@ namespace ICSharpCode.NRefactory.Tests.AST @@ -136,6 +136,12 @@ namespace ICSharpCode.NRefactory.Tests.AST
CSharpTestBinaryOperatorExpressionTest("a >> b", BinaryOperatorType.ShiftRight);
}
[Test]
public void CSharpNullCoalescingTest()
{
CSharpTestBinaryOperatorExpressionTest("a ?? b", BinaryOperatorType.NullCoalescing);
}
[Test]
public void CSharpISTest()
{

13
src/Libraries/NRefactory/Test/Parser/Expressions/ConditionalExpressionTests.cs

@ -26,10 +26,21 @@ namespace ICSharpCode.NRefactory.Tests.AST @@ -26,10 +26,21 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.IsTrue(ce.TrueExpression is InvocationExpression);
Assert.IsTrue(ce.FalseExpression is FieldReferenceExpression);
}
[Test]
public void CSharpConditionalIsExpressionTest()
{
// (as is b?) ERROR (conflict with nullables, SD2-419)
ConditionalExpression ce = (ConditionalExpression)ParseUtilCSharp.ParseExpression("a is b ? a() : a.B", typeof(ConditionalExpression));
Assert.IsTrue(ce.Condition is BinaryOperatorExpression);
Assert.IsTrue(ce.TrueExpression is InvocationExpression);
Assert.IsTrue(ce.FalseExpression is FieldReferenceExpression);
}
#endregion
#region VB.NET
// No VB.NET representation
// No VB.NET representation
#endregion
}
}

Loading…
Cancel
Save