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. 57
      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 @@
<Mode file = "XML-Mode.xshd" <Mode file = "XML-Mode.xshd"
name = "XML" 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> </SyntaxModes>

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

@ -1,6 +1,6 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<!-- syntaxdefinition for XML 2000 by Mike Krueger --> <!-- 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" /> <Digits name="Digits" bold="false" italic="false" color="DarkBlue" />
<RuleSets> <RuleSets>

2
src/Libraries/NRefactory/NRefactory.sln

@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00 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}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryTests", "Test\NRefactoryTests.csproj", "{870115DD-960A-4406-A6B9-600BCDC36A03}" 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 = ":"
DoubleColon = "::" DoubleColon = "::"
Semicolon = ";" Semicolon = ";"
Question = "?" Question = "?"
DoubleQuestion = "??"
Comma = "," Comma = ","
Dot = "." Dot = "."

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

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

57
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
Assert.AreEqual(Tokens.Question, lexer.NextToken().kind); Assert.AreEqual(Tokens.Question, lexer.NextToken().kind);
} }
[Test]
public void TestDoubleQuestion()
{
ILexer lexer = GenerateLexer(new StringReader("??"));
Assert.AreEqual(Tokens.DoubleQuestion, lexer.NextToken().kind);
}
[Test] [Test]
public void TestComma() public void TestComma()
{ {
@ -119,41 +126,7 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
ILexer lexer = GenerateLexer(new StringReader("}")); ILexer lexer = GenerateLexer(new StringReader("}"));
Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().kind); 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] [Test]
public void TestOpenSquareBracket() public void TestOpenSquareBracket()
{ {
@ -294,13 +267,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
Assert.AreEqual(Tokens.ShiftLeft, lexer.NextToken().kind); Assert.AreEqual(Tokens.ShiftLeft, lexer.NextToken().kind);
} }
// [Test]
// public void TestShiftRight()
// {
// ILexer lexer = GenerateLexer(new StringReader(">>"));
// Assert.AreEqual(Tokens.ShiftRight, lexer.NextToken().kind);
// }
[Test] [Test]
public void TestPlusAssign() public void TestPlusAssign()
{ {
@ -364,13 +330,6 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp
Assert.AreEqual(Tokens.ShiftLeftAssign, lexer.NextToken().kind); Assert.AreEqual(Tokens.ShiftLeftAssign, lexer.NextToken().kind);
} }
// [Test]
// public void TestShiftRightAssign()
// {
// ILexer lexer = GenerateLexer(new StringReader(">>="));
// Assert.AreEqual(Tokens.ShiftRightAssign, lexer.NextToken().kind);
// }
[Test()] [Test()]
public void TestAbstract() public void TestAbstract()
{ {

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

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

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

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

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

@ -26,10 +26,21 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.IsTrue(ce.TrueExpression is InvocationExpression); Assert.IsTrue(ce.TrueExpression is InvocationExpression);
Assert.IsTrue(ce.FalseExpression is FieldReferenceExpression); 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 #endregion
#region VB.NET #region VB.NET
// No VB.NET representation // No VB.NET representation
#endregion #endregion
} }
} }

Loading…
Cancel
Save